001 package com.mockrunner.jdbc; 002 003 import java.sql.SQLException; 004 import java.util.ArrayList; 005 import java.util.Arrays; 006 import java.util.Collections; 007 import java.util.HashMap; 008 import java.util.Iterator; 009 import java.util.List; 010 import java.util.Map; 011 012 import com.mockrunner.mock.jdbc.MockResultSet; 013 import com.mockrunner.util.common.ArrayUtil; 014 015 /** 016 * Abstract base class for all statement types 017 * that support parameters, i.e. <code>PreparedStatement</code> 018 * and <code>CallableStatement</code>. 019 */ 020 public abstract class AbstractParameterResultSetHandler extends AbstractResultSetHandler 021 { 022 private boolean exactMatchParameter = false; 023 private Map resultSetsForStatement = new HashMap(); 024 private Map updateCountForStatement = new HashMap(); 025 private Map throwsSQLException = new HashMap(); 026 private Map generatedKeysForStatement = new HashMap(); 027 private Map executedStatementParameters = new HashMap(); 028 029 /** 030 * Collects all SQL strings that were executed. 031 * @param sql the SQL string 032 * @param parameters a copy of the corresponding parameter map 033 */ 034 public void addParameterMapForExecutedStatement(String sql, Map parameters) 035 { 036 if(null != parameters) 037 { 038 if(null == executedStatementParameters.get(sql)) 039 { 040 executedStatementParameters.put(sql, new ParameterSets(sql)); 041 } 042 ParameterSets sets = (ParameterSets)executedStatementParameters.get(sql); 043 sets.addParameterSet(parameters); 044 } 045 } 046 047 /** 048 * Returns the <code>ParameterSets</code> for a specified 049 * SQL string. 050 * @param sql the SQL string 051 * @return the <code>Map</code> of parameters 052 */ 053 public ParameterSets getParametersForExecutedStatement(String sql) 054 { 055 return (ParameterSets)executedStatementParameters.get(sql); 056 } 057 058 /** 059 * Returns the <code>Map</code> of executed SQL strings. 060 * Each string maps to the corresponding {@link ParameterSets} 061 * object. 062 * @return the <code>Map</code> of parameters 063 */ 064 public Map getExecutedStatementParameterMap() 065 { 066 return Collections.unmodifiableMap(executedStatementParameters); 067 } 068 069 /** 070 * @deprecated use {@link #getExecutedStatementParameterMap} 071 */ 072 public Map getExecutedStatementParameter() 073 { 074 return getExecutedStatementParameterMap(); 075 } 076 077 /** 078 * Sets if the specified parameters must match exactly 079 * in order and number. 080 * Defaults to <code>false</code>, i.e. the specified 081 * parameters must be present in the actual parameter 082 * list of the prepared statement with the correct index 083 * but it's ok if there are more actual parameters. 084 * @param exactMatchParameter must parameters match exactly 085 */ 086 public void setExactMatchParameter(boolean exactMatchParameter) 087 { 088 this.exactMatchParameter = exactMatchParameter; 089 } 090 091 /** 092 * Returns the first update count that matches the 093 * specified SQL string and the specified parameters. 094 * If the specified SQL string was prepared to return multiple update 095 * counts, the first one will be returned. 096 * Please note that you can modify the match parameters with 097 * {@link #setCaseSensitive}, {@link #setExactMatch} and 098 * {@link #setUseRegularExpressions} and the match parameters for the 099 * specified parameter list with {@link #setExactMatchParameter}. 100 * @param sql the SQL string 101 * @param parameters the parameters 102 * @return the corresponding update count 103 */ 104 public Integer getUpdateCount(String sql, Map parameters) 105 { 106 Integer[] updateCounts = getUpdateCounts(sql, parameters); 107 if(null != updateCounts && updateCounts.length > 0) 108 { 109 return updateCounts[0]; 110 } 111 return null; 112 } 113 114 /** 115 * Returns the first update count array that matches the 116 * specified SQL string and the specified parameters. 117 * If the specified SQL string was prepared to return one update count, 118 * this value will be wrapped in an array with one element. 119 * Please note that you can modify the match parameters with 120 * {@link #setCaseSensitive}, {@link #setExactMatch} and 121 * {@link #setUseRegularExpressions} and the match parameters for the 122 * specified parameter list with {@link #setExactMatchParameter}. 123 * @param sql the SQL string 124 * @param parameters the parameters 125 * @return the corresponding update count 126 */ 127 public Integer[] getUpdateCounts(String sql, Map parameters) 128 { 129 ParameterWrapper wrapper = (ParameterWrapper)getMatchingParameterWrapper(sql, parameters, updateCountForStatement); 130 if(null != wrapper) 131 { 132 if(wrapper instanceof MockUpdateCountWrapper) 133 { 134 return new Integer[] {((MockUpdateCountWrapper)wrapper).getUpdateCount()}; 135 } 136 else if(wrapper instanceof MockUpdateCountArrayWrapper) 137 { 138 return ((MockUpdateCountArrayWrapper)wrapper).getUpdateCount(); 139 } 140 } 141 return null; 142 } 143 144 /** 145 * Returns the if the specified SQL string with the specified parameters 146 * returns multiple update counts. 147 * Please note that you can modify the match parameters with {@link #setCaseSensitive}, 148 * {@link #setExactMatch} and {@link #setUseRegularExpressions}. 149 * @param sql the SQL string 150 * @return <code>true</code> if the SQL string returns multiple update counts, 151 * <code>false</code> otherwise 152 */ 153 public boolean hasMultipleUpdateCounts(String sql, Map parameters) 154 { 155 ParameterWrapper wrapper = (ParameterWrapper)getMatchingParameterWrapper(sql, parameters, updateCountForStatement); 156 return (wrapper instanceof MockUpdateCountArrayWrapper); 157 } 158 159 /** 160 * Returns the first <code>ResultSet</code> that matches the 161 * specified SQL string and the specified parameters. 162 * If the specified SQL string was prepared to return multiple result 163 * sets, the first one will be returned. 164 * Please note that you can modify the match parameters with 165 * {@link #setCaseSensitive}, {@link #setExactMatch} and 166 * {@link #setUseRegularExpressions} and the match parameters for the 167 * specified parameter list with {@link #setExactMatchParameter}. 168 * @param sql the SQL string 169 * @param parameters the parameters 170 * @return the corresponding {@link MockResultSet} 171 */ 172 public MockResultSet getResultSet(String sql, Map parameters) 173 { 174 MockResultSet[] resultSets = getResultSets(sql, parameters); 175 if(null != resultSets && resultSets.length > 0) 176 { 177 return resultSets[0]; 178 } 179 return null; 180 } 181 182 /** 183 * Returns the first <code>ResultSet[]</code> that matches the 184 * specified SQL string and the specified parameters. 185 * If the specified SQL string was prepared to return one single 186 * <code>ResultSet</code>, this <code>ResultSet</code> will be wrapped 187 * in an array with one element. 188 * Please note that you can modify the match parameters with 189 * {@link #setCaseSensitive}, {@link #setExactMatch} and 190 * {@link #setUseRegularExpressions} and the match parameters for the 191 * specified parameter list with {@link #setExactMatchParameter}. 192 * @param sql the SQL string 193 * @param parameters the parameters 194 * @return the corresponding update count 195 */ 196 public MockResultSet[] getResultSets(String sql, Map parameters) 197 { 198 ParameterWrapper wrapper = (ParameterWrapper)getMatchingParameterWrapper(sql, parameters, resultSetsForStatement); 199 if(null != wrapper) 200 { 201 if(wrapper instanceof MockResultSetWrapper) 202 { 203 return new MockResultSet[] {((MockResultSetWrapper)wrapper).getResultSet()}; 204 } 205 else if(wrapper instanceof MockResultSetArrayWrapper) 206 { 207 return ((MockResultSetArrayWrapper)wrapper).getResultSets(); 208 } 209 } 210 return null; 211 } 212 213 /** 214 * Returns the if the specified SQL string with the specified parameters 215 * returns multiple result sets. 216 * Please note that you can modify the match parameters with {@link #setCaseSensitive}, 217 * {@link #setExactMatch} and {@link #setUseRegularExpressions}. 218 * @param sql the SQL string 219 * @return <code>true</code> if the SQL string returns multiple update counts, 220 * <code>false</code> otherwise 221 */ 222 public boolean hasMultipleResultSets(String sql, Map parameters) 223 { 224 ParameterWrapper wrapper = (ParameterWrapper)getMatchingParameterWrapper(sql, parameters, resultSetsForStatement); 225 return (wrapper instanceof MockResultSetArrayWrapper); 226 } 227 228 /** 229 * Returns if the specified SQL string with the specified parameters 230 * should raise an exception. 231 * This can be used to simulate database exceptions. 232 * Please note that you can modify the match parameters with 233 * {@link #setCaseSensitive}, {@link #setExactMatch} and 234 * {@link #setUseRegularExpressions} and the match parameters for the 235 * specified parameter list with {@link #setExactMatchParameter}. 236 * @param sql the SQL string 237 * @param parameters the parameters 238 * @return <code>true</code> if the specified SQL string should raise an exception, 239 * <code>false</code> otherwise 240 */ 241 public boolean getThrowsSQLException(String sql, Map parameters) 242 { 243 return (getSQLException(sql, parameters) != null); 244 } 245 246 /** 247 * Returns the <code>SQLException</code> the specified SQL string 248 * should throw. Returns <code>null</code> if the specified SQL string 249 * should not throw an exception. 250 * This can be used to simulate database exceptions. 251 * Please note that you can modify the match parameters with 252 * {@link #setCaseSensitive}, {@link #setExactMatch} and 253 * {@link #setUseRegularExpressions} and the match parameters for the 254 * specified parameter list with {@link #setExactMatchParameter}. 255 * @param sql the SQL string 256 * @param parameters the parameters 257 * @return the <code>SQLException</code> or <code>null</code> 258 */ 259 public SQLException getSQLException(String sql, Map parameters) 260 { 261 MockSQLExceptionWrapper wrapper = (MockSQLExceptionWrapper)getMatchingParameterWrapper(sql, parameters, throwsSQLException); 262 if(null != wrapper) 263 { 264 return wrapper.getException(); 265 } 266 return null; 267 } 268 269 /** 270 * Returns the first generated keys <code>ResultSet</code> that 271 * matches the specified SQL string. 272 * Please note that you can modify the match parameters with 273 * {@link #setCaseSensitive}, {@link #setExactMatch} and 274 * {@link #setUseRegularExpressions} and the match parameters for the 275 * specified parameter list with {@link #setExactMatchParameter}. 276 * @param sql the SQL string 277 * @param parameters the parameters 278 * @return the corresponding generated keys {@link MockResultSet} 279 */ 280 public MockResultSet getGeneratedKeys(String sql, Map parameters) 281 { 282 MockResultSetWrapper wrapper = (MockResultSetWrapper)getMatchingParameterWrapper(sql, parameters, generatedKeysForStatement); 283 if(null != wrapper) 284 { 285 return wrapper.getResultSet(); 286 } 287 return null; 288 } 289 290 protected ParameterWrapper getMatchingParameterWrapper(String sql, Map parameters, Map statementMap) 291 { 292 SQLStatementMatcher matcher = new SQLStatementMatcher(getCaseSensitive(), getExactMatch(), getUseRegularExpressions()); 293 List list = matcher.getMatchingObjects(statementMap, sql, true, true); 294 for(int ii = 0; ii < list.size(); ii++) 295 { 296 ParameterWrapper wrapper = (ParameterWrapper)list.get(ii); 297 if(doParameterMatch(wrapper.getParamters(), parameters)) 298 { 299 return wrapper; 300 } 301 } 302 return null; 303 } 304 305 private boolean doParameterMatch(Map expectedParameters, Map actualParameters) 306 { 307 if(exactMatchParameter) 308 { 309 if(actualParameters.size() != expectedParameters.size()) return false; 310 Iterator iterator = actualParameters.keySet().iterator(); 311 while(iterator.hasNext()) 312 { 313 Object currentKey = iterator.next(); 314 if(!actualParameters.containsKey(currentKey)) return false; 315 Object expectedObject = expectedParameters.get(currentKey); 316 if(!ParameterUtil.compareParameter(actualParameters.get(currentKey), expectedObject)) 317 { 318 return false; 319 } 320 } 321 return true; 322 } 323 else 324 { 325 Iterator iterator = expectedParameters.keySet().iterator(); 326 while(iterator.hasNext()) 327 { 328 Object currentKey = iterator.next(); 329 if(!actualParameters.containsKey(currentKey)) return false; 330 Object actualObject = actualParameters.get(currentKey); 331 if(!ParameterUtil.compareParameter(actualObject, expectedParameters.get(currentKey))) 332 { 333 return false; 334 } 335 } 336 return true; 337 } 338 } 339 340 /** 341 * Clears the <code>ResultSet</code> objects. 342 */ 343 public void clearResultSets() 344 { 345 super.clearResultSets(); 346 resultSetsForStatement.clear(); 347 } 348 349 /** 350 * Clears the update counts. 351 */ 352 public void clearUpdateCounts() 353 { 354 super.clearUpdateCounts(); 355 updateCountForStatement.clear(); 356 } 357 358 /** 359 * Clears the list of statements that should throw an exception 360 */ 361 public void clearThrowsSQLException() 362 { 363 super.clearThrowsSQLException(); 364 throwsSQLException.clear(); 365 } 366 367 /** 368 * Clears the list of statements that return generated keys. 369 */ 370 public void clearGeneratedKeys() 371 { 372 super.clearGeneratedKeys(); 373 generatedKeysForStatement.clear(); 374 } 375 376 /** 377 * Prepare a <code>ResultSet</code> for a specified SQL string and 378 * the specified parameters. The specified parameters array 379 * must contain the parameters in the correct order starting with index 0 for 380 * the first parameter. Please keep in mind that parameters in 381 * <code>PreparedStatement</code> objects start with 1 as the first 382 * parameter. So <code>parameters[0]</code> maps to the 383 * parameter with index 1. 384 * Please note that you can modify the match parameters with 385 * {@link #setCaseSensitive}, {@link #setExactMatch} and 386 * {@link #setUseRegularExpressions} and the match parameters for the 387 * specified parameter list with {@link #setExactMatchParameter}. 388 * @param sql the SQL string 389 * @param resultSet the corresponding {@link MockResultSet} 390 * @param parameters the parameters 391 */ 392 public void prepareResultSet(String sql, MockResultSet resultSet, Object[] parameters) 393 { 394 prepareResultSet(sql, resultSet, Arrays.asList(parameters)); 395 } 396 397 /** 398 * Prepare an array of <code>ResultSet</code> objects for a specified SQL string and 399 * the specified parameters. This method can be used for queries that return 400 * multiple result sets. The specified parameters array 401 * must contain the parameters in the correct order starting with index 0 for 402 * the first parameter. Please keep in mind that parameters in 403 * <code>PreparedStatement</code> objects start with 1 as the first 404 * parameter. So <code>parameters[0]</code> maps to the 405 * parameter with index 1. 406 * Please note that you can modify the match parameters with 407 * {@link #setCaseSensitive}, {@link #setExactMatch} and 408 * {@link #setUseRegularExpressions} and the match parameters for the 409 * specified parameter list with {@link #setExactMatchParameter}. 410 * @param sql the SQL string 411 * @param resultSets the corresponding <code>MockResultSet[]</code> 412 * @param parameters the parameters 413 */ 414 public void prepareResultSets(String sql, MockResultSet[] resultSets, Object[] parameters) 415 { 416 prepareResultSets(sql, resultSets, Arrays.asList(parameters)); 417 } 418 419 /** 420 * Prepare a <code>ResultSet</code> for a specified SQL string and 421 * the specified parameters. The specified parameters <code>List</code> 422 * must contain the parameters in the correct order starting with index 0 for 423 * the first parameter. Please keep in mind that parameters in 424 * <code>PreparedStatement</code> objects start with 1 as the first 425 * parameter. So <code>parameters.get(0)</code> maps to the 426 * parameter with index 1. 427 * Please note that you can modify the match parameters with 428 * {@link #setCaseSensitive}, {@link #setExactMatch} and 429 * {@link #setUseRegularExpressions} and the match parameters for the 430 * specified parameter list with {@link #setExactMatchParameter}. 431 * @param sql the SQL string 432 * @param resultSet the corresponding {@link MockResultSet} 433 * @param parameters the parameters 434 */ 435 public void prepareResultSet(String sql, MockResultSet resultSet, List parameters) 436 { 437 Map params = createParameterMap(parameters); 438 prepareResultSet(sql, resultSet, params); 439 } 440 441 /** 442 * Prepare an array of <code>ResultSet</code> objects for a specified SQL string and 443 * the specified parameters. This method can be used for queries that return 444 * multiple result sets. The specified parameters <code>List</code> 445 * must contain the parameters in the correct order starting with index 0 for 446 * the first parameter. Please keep in mind that parameters in 447 * <code>PreparedStatement</code> objects start with 1 as the first 448 * parameter. So <code>parameters.get(0)</code> maps to the 449 * parameter with index 1. 450 * Please note that you can modify the match parameters with 451 * {@link #setCaseSensitive}, {@link #setExactMatch} and 452 * {@link #setUseRegularExpressions} and the match parameters for the 453 * specified parameter list with {@link #setExactMatchParameter}. 454 * @param sql the SQL string 455 * @param resultSets the corresponding <code>MockResultSet[]</code> 456 * @param parameters the parameters 457 */ 458 public void prepareResultSets(String sql, MockResultSet[] resultSets, List parameters) 459 { 460 Map params = createParameterMap(parameters); 461 prepareResultSets(sql, resultSets, params); 462 } 463 464 /** 465 * Prepare a <code>ResultSet</code> for a specified SQL string and 466 * the specified parameters. The specified parameters <code>Map</code> 467 * must contain the parameters by mapping <code>Integer</code> objects 468 * to the corresponding parameter. The <code>Integer</code> object 469 * is the index of the parameter. In the case of a <code>CallableStatement</code>, 470 * <code>String</code> keys for named parameters are also allowed. 471 * Please note that you can modify the match parameters with 472 * {@link #setCaseSensitive}, {@link #setExactMatch} and 473 * {@link #setUseRegularExpressions} and the match parameters for the 474 * specified parameter list with {@link #setExactMatchParameter}. 475 * @param sql the SQL string 476 * @param resultSet the corresponding {@link MockResultSet} 477 * @param parameters the parameters 478 */ 479 public void prepareResultSet(String sql, MockResultSet resultSet, Map parameters) 480 { 481 List list = getListFromMapForSQLStatement(sql, resultSetsForStatement); 482 list.add(new MockResultSetWrapper(resultSet, new HashMap(parameters))); 483 } 484 485 /** 486 * Prepare an array of <code>ResultSet</code> objects for a specified SQL string and 487 * the specified parameters. This method can be used for queries that return 488 * multiple result sets. The specified parameters <code>Map</code> 489 * must contain the parameters by mapping <code>Integer</code> objects 490 * to the corresponding parameter. The <code>Integer</code> object 491 * is the index of the parameter. In the case of a <code>CallableStatement</code>, 492 * <code>String</code> keys for named parameters are also allowed. 493 * Please note that you can modify the match parameters with 494 * {@link #setCaseSensitive}, {@link #setExactMatch} and 495 * {@link #setUseRegularExpressions} and the match parameters for the 496 * specified parameter list with {@link #setExactMatchParameter}. 497 * @param sql the SQL string 498 * @param resultSets the corresponding <code>MockResultSet[]</code> 499 * @param parameters the parameters 500 */ 501 public void prepareResultSets(String sql, MockResultSet[] resultSets, Map parameters) 502 { 503 List list = getListFromMapForSQLStatement(sql, resultSetsForStatement); 504 list.add(new MockResultSetArrayWrapper((MockResultSet[])resultSets.clone(), new HashMap(parameters))); 505 } 506 507 /** 508 * Prepare that the specified SQL string with the specified parameters 509 * should raise an exception. 510 * This can be used to simulate database exceptions. 511 * This method creates an <code>SQLException</code> and will throw this 512 * exception. With {@link #prepareThrowsSQLException(String, SQLException, Object[])} 513 * you can specify the exception. 514 * The specified parameters array must contain the parameters in 515 * the correct order starting with index 0 for the first parameter. 516 * Please keep in mind that parameters in <code>PreparedStatement</code> 517 * objects start with 1 as the first parameter. So <code>parameters[0]</code> 518 * maps to the parameter with index 1. 519 * Please note that you can modify the match parameters with 520 * {@link #setCaseSensitive}, {@link #setExactMatch} and 521 * {@link #setUseRegularExpressions} and the match parameters for the 522 * specified parameter list with {@link #setExactMatchParameter}. 523 * @param sql the SQL string 524 * @param parameters the parameters 525 */ 526 public void prepareThrowsSQLException(String sql, Object[] parameters) 527 { 528 SQLException exc = new SQLException("Statement " + sql + " was specified to throw an exception"); 529 prepareThrowsSQLException(sql, exc, parameters); 530 } 531 532 /** 533 * Prepare that the specified SQL string with the specified parameters 534 * should raise an exception. 535 * This can be used to simulate database exceptions. 536 * This method creates an <code>SQLException</code> and will throw this 537 * exception. With {@link #prepareThrowsSQLException(String, SQLException, List)} 538 * you can specify the exception. 539 * The specified parameters <code>List</code> must contain the 540 * parameters in the correct order starting with index 0 for the first 541 * parameter. Please keep in mind that parameters in 542 * <code>PreparedStatement</code> objects start with 1 as the first 543 * parameter. So <code>parameters.get(0)</code> maps to the parameter 544 * with index 1. 545 * Please note that you can modify the match parameters with 546 * {@link #setCaseSensitive}, {@link #setExactMatch} and 547 * {@link #setUseRegularExpressions} and the match parameters for the 548 * specified parameter list with {@link #setExactMatchParameter}. 549 * @param sql the SQL string 550 * @param parameters the parameters 551 */ 552 public void prepareThrowsSQLException(String sql, List parameters) 553 { 554 SQLException exc = new SQLException("Statement " + sql + " was specified to throw an exception"); 555 prepareThrowsSQLException(sql, exc, parameters); 556 } 557 558 /** 559 * Prepare that the specified SQL string with the specified parameters 560 * should raise an exception. 561 * This can be used to simulate database exceptions. 562 * This method creates an <code>SQLException</code> and will throw this 563 * exception. With {@link #prepareThrowsSQLException(String, SQLException, Map)} 564 * you can specify the exception. 565 * The specified parameters <code>Map</code> must contain the parameters by 566 * mapping <code>Integer</code> objects to the corresponding parameter. 567 * The <code>Integer</code> object is the index of the parameter. In the case 568 * of a <code>CallableStatement</code>, 569 * <code>String</code> keys for named parameters are also allowed. 570 * Please note that you can modify the match parameters with 571 * {@link #setCaseSensitive}, {@link #setExactMatch} and 572 * {@link #setUseRegularExpressions} and the match parameters for the 573 * specified parameter list with {@link #setExactMatchParameter}. 574 * @param sql the SQL string 575 * @param parameters the parameters 576 */ 577 public void prepareThrowsSQLException(String sql, Map parameters) 578 { 579 SQLException exc = new SQLException("Statement " + sql + " was specified to throw an exception"); 580 prepareThrowsSQLException(sql, exc, parameters); 581 } 582 583 /** 584 * Prepare that the specified SQL string with the specified parameters 585 * should raise an exception. 586 * This can be used to simulate database exceptions. 587 * This method takes an exception object that will be thrown. 588 * The specified parameters array must contain the parameters in 589 * the correct order starting with index 0 for the first parameter. 590 * Please keep in mind that parameters in <code>PreparedStatement</code> 591 * objects start with 1 as the first parameter. So <code>parameters[0]</code> 592 * maps to the parameter with index 1. 593 * Please note that you can modify the match parameters with 594 * {@link #setCaseSensitive}, {@link #setExactMatch} and 595 * {@link #setUseRegularExpressions} and the match parameters for the 596 * specified parameter list with {@link #setExactMatchParameter}. 597 * @param sql the SQL string 598 * @param exc the <code>SQLException</code> that should be thrown 599 * @param parameters the parameters 600 */ 601 public void prepareThrowsSQLException(String sql, SQLException exc, Object[] parameters) 602 { 603 prepareThrowsSQLException(sql, exc, Arrays.asList(parameters)); 604 } 605 606 /** 607 * Prepare that the specified SQL string with the specified parameters 608 * should raise an exception. 609 * This can be used to simulate database exceptions. 610 * This method takes an exception object that will be thrown. 611 * The specified parameters <code>List</code> must contain the 612 * parameters in the correct order starting with index 0 for the first 613 * parameter. Please keep in mind that parameters in 614 * <code>PreparedStatement</code> objects start with 1 as the first 615 * parameter. So <code>parameters.get(0)</code> maps to the parameter 616 * with index 1. 617 * Please note that you can modify the match parameters with 618 * {@link #setCaseSensitive}, {@link #setExactMatch} and 619 * {@link #setUseRegularExpressions} and the match parameters for the 620 * specified parameter list with {@link #setExactMatchParameter}. 621 * @param sql the SQL string 622 * @param exc the <code>SQLException</code> that should be thrown 623 * @param parameters the parameters 624 */ 625 public void prepareThrowsSQLException(String sql, SQLException exc, List parameters) 626 { 627 Map params = createParameterMap(parameters); 628 prepareThrowsSQLException(sql, exc, params); 629 } 630 631 /** 632 * Prepare that the specified SQL string with the specified parameters 633 * should raise an exception. 634 * This can be used to simulate database exceptions. 635 * This method takes an exception object that will be thrown. 636 * The specified parameters <code>Map</code> must contain the parameters by 637 * mapping <code>Integer</code> objects to the corresponding parameter. 638 * The <code>Integer</code> object is the index of the parameter. In the case 639 * of a <code>CallableStatement</code>, 640 * <code>String</code> keys for named parameters are also allowed. 641 * Please note that you can modify the match parameters with 642 * {@link #setCaseSensitive}, {@link #setExactMatch} and 643 * {@link #setUseRegularExpressions} and the match parameters for the 644 * specified parameter list with {@link #setExactMatchParameter}. 645 * @param sql the SQL string 646 * @param exc the <code>SQLException</code> that should be thrown 647 * @param parameters the parameters 648 */ 649 public void prepareThrowsSQLException(String sql, SQLException exc, Map parameters) 650 { 651 List list = getListFromMapForSQLStatement(sql, throwsSQLException); 652 list.add(new MockSQLExceptionWrapper(exc, new HashMap(parameters))); 653 } 654 655 /** 656 * Prepare the update count for execute update calls for a specified SQL string 657 * and the specified parameters. The specified parameters array 658 * must contain the parameters in the correct order starting with index 0 for 659 * the first parameter. Please keep in mind that parameters in 660 * <code>PreparedStatement</code> objects start with 1 as the first 661 * parameter. So <code>parameters[0]</code> maps to the 662 * parameter with index 1. 663 * Please note that you can modify the match parameters with 664 * {@link #setCaseSensitive}, {@link #setExactMatch} and 665 * {@link #setUseRegularExpressions} and the match parameters for the 666 * specified parameter list with {@link #setExactMatchParameter}. 667 * @param sql the SQL string 668 * @param updateCount the update count 669 * @param parameters the parameters 670 */ 671 public void prepareUpdateCount(String sql, int updateCount, Object[] parameters) 672 { 673 prepareUpdateCount(sql, updateCount, Arrays.asList(parameters)); 674 } 675 676 /** 677 * Prepare an array update count values for execute update calls for a specified SQL string 678 * and the specified parameters. This method can be used if multiple update counts 679 * are returned. The specified parameters array 680 * must contain the parameters in the correct order starting with index 0 for 681 * the first parameter. Please keep in mind that parameters in 682 * <code>PreparedStatement</code> objects start with 1 as the first 683 * parameter. So <code>parameters[0]</code> maps to the 684 * parameter with index 1. 685 * Please note that you can modify the match parameters with 686 * {@link #setCaseSensitive}, {@link #setExactMatch} and 687 * {@link #setUseRegularExpressions} and the match parameters for the 688 * specified parameter list with {@link #setExactMatchParameter}. 689 * @param sql the SQL string 690 * @param updateCounts the update count array 691 * @param parameters the parameters 692 */ 693 public void prepareUpdateCounts(String sql, int[] updateCounts, Object[] parameters) 694 { 695 prepareUpdateCounts(sql, updateCounts, Arrays.asList(parameters)); 696 } 697 698 /** 699 * Prepare the update count for execute update calls for a specified SQL string 700 * and the specified parameters. The specified parameters <code>List</code> 701 * must contain the parameters in the correct order starting with index 0 for 702 * the first parameter. Please keep in mind that parameters in 703 * <code>PreparedStatement</code> objects start with 1 as the first 704 * parameter. So <code>parameters.get(0)</code> maps to the 705 * parameter with index 1. 706 * Please note that you can modify the match parameters with 707 * {@link #setCaseSensitive}, {@link #setExactMatch} and 708 * {@link #setUseRegularExpressions} and the match parameters for the 709 * specified parameter list with {@link #setExactMatchParameter}. 710 * @param sql the SQL string 711 * @param updateCount the update count 712 * @param parameters the parameters 713 */ 714 public void prepareUpdateCount(String sql, int updateCount, List parameters) 715 { 716 Map params = createParameterMap(parameters); 717 prepareUpdateCount(sql, updateCount, params); 718 } 719 720 /** 721 * Prepare an array update count values for execute update calls for a specified SQL string 722 * and the specified parameters. This method can be used if multiple update counts 723 * are returned. The specified parameters <code>List</code> 724 * must contain the parameters in the correct order starting with index 0 for 725 * the first parameter. Please keep in mind that parameters in 726 * <code>PreparedStatement</code> objects start with 1 as the first 727 * parameter. So <code>parameters.get(0)</code> maps to the 728 * parameter with index 1. 729 * Please note that you can modify the match parameters with 730 * {@link #setCaseSensitive}, {@link #setExactMatch} and 731 * {@link #setUseRegularExpressions} and the match parameters for the 732 * specified parameter list with {@link #setExactMatchParameter}. 733 * @param sql the SQL string 734 * @param updateCounts the update count array 735 * @param parameters the parameters 736 */ 737 public void prepareUpdateCounts(String sql, int[] updateCounts, List parameters) 738 { 739 Map params = createParameterMap(parameters); 740 prepareUpdateCounts(sql, updateCounts, params); 741 } 742 743 /** 744 * Prepare the update count for execute update calls for a specified SQL string 745 * and the specified parameters. The specified parameters <code>Map</code> 746 * must contain the parameters by mapping <code>Integer</code> objects 747 * to the corresponding parameter. The <code>Integer</code> object 748 * is the index of the parameter. In the case of a <code>CallableStatement</code>, 749 * <code>String</code> keys for named parameters are also allowed. 750 * Please note that you can modify the match parameters with 751 * {@link #setCaseSensitive}, {@link #setExactMatch} and 752 * {@link #setUseRegularExpressions} and the match parameters for the 753 * specified parameter list with {@link #setExactMatchParameter}. 754 * @param sql the SQL string 755 * @param updateCount the update count 756 * @param parameters the parameters 757 */ 758 public void prepareUpdateCount(String sql, int updateCount, Map parameters) 759 { 760 List list = getListFromMapForSQLStatement(sql, updateCountForStatement); 761 list.add(new MockUpdateCountWrapper(updateCount, new HashMap(parameters))); 762 } 763 764 /** 765 * Prepare an array update count values for execute update calls for a specified SQL string 766 * and the specified parameters. This method can be used if multiple update counts 767 * are returned. The specified parameters <code>Map</code> 768 * must contain the parameters by mapping <code>Integer</code> objects 769 * to the corresponding parameter. The <code>Integer</code> object 770 * is the index of the parameter. In the case of a <code>CallableStatement</code>, 771 * <code>String</code> keys for named parameters are also allowed. 772 * Please note that you can modify the match parameters with 773 * {@link #setCaseSensitive}, {@link #setExactMatch} and 774 * {@link #setUseRegularExpressions} and the match parameters for the 775 * specified parameter list with {@link #setExactMatchParameter}. 776 * @param sql the SQL string 777 * @param updateCounts the update count array 778 * @param parameters the parameters 779 */ 780 public void prepareUpdateCounts(String sql, int[] updateCounts, Map parameters) 781 { 782 List list = getListFromMapForSQLStatement(sql, updateCountForStatement); 783 list.add(new MockUpdateCountArrayWrapper((int[])updateCounts.clone(), new HashMap(parameters))); 784 } 785 786 /** 787 * Prepare the generated keys <code>ResultSet</code> 788 * for a specified SQL string. 789 * The specified parameters array must contain the parameters in 790 * the correct order starting with index 0 for the first parameter. 791 * Please keep in mind that parameters in <code>PreparedStatement</code> 792 * objects start with 1 as the first parameter. So <code>parameters[0]</code> 793 * maps to the parameter with index 1. 794 * Please note that you can modify the match parameters with 795 * {@link #setCaseSensitive}, {@link #setExactMatch} and 796 * {@link #setUseRegularExpressions} and the match parameters for the 797 * specified parameter list with {@link #setExactMatchParameter}. 798 * @param sql the SQL string 799 * @param generatedKeysResult the generated keys {@link MockResultSet} 800 * @param parameters the parameters 801 */ 802 public void prepareGeneratedKeys(String sql, MockResultSet generatedKeysResult, Object[] parameters) 803 { 804 prepareGeneratedKeys(sql, generatedKeysResult, Arrays.asList(parameters)); 805 } 806 807 /** 808 * Prepare the generated keys <code>ResultSet</code> 809 * for a specified SQL string. 810 * The specified parameters <code>List</code> must contain the 811 * parameters in the correct order starting with index 0 for the first 812 * parameter. Please keep in mind that parameters in 813 * <code>PreparedStatement</code> objects start with 1 as the first 814 * parameter. So <code>parameters.get(0)</code> maps to the parameter 815 * with index 1. 816 * Please note that you can modify the match parameters with 817 * {@link #setCaseSensitive}, {@link #setExactMatch} and 818 * {@link #setUseRegularExpressions} and the match parameters for the 819 * specified parameter list with {@link #setExactMatchParameter}. 820 * @param sql the SQL string 821 * @param generatedKeysResult the generated keys {@link MockResultSet} 822 * @param parameters the parameters 823 */ 824 public void prepareGeneratedKeys(String sql, MockResultSet generatedKeysResult, List parameters) 825 { 826 Map params = createParameterMap(parameters); 827 prepareGeneratedKeys(sql, generatedKeysResult, params); 828 } 829 830 /** 831 * Prepare the generated keys <code>ResultSet</code> 832 * for a specified SQL string. 833 * The specified parameters <code>Map</code> must contain the parameters by 834 * mapping <code>Integer</code> objects to the corresponding parameter. 835 * The <code>Integer</code> object is the index of the parameter. In the case 836 * of a <code>CallableStatement</code>, 837 * <code>String</code> keys for named parameters are also allowed. 838 * Please note that you can modify the match parameters with 839 * {@link #setCaseSensitive}, {@link #setExactMatch} and 840 * {@link #setUseRegularExpressions} and the match parameters for the 841 * specified parameter list with {@link #setExactMatchParameter}. 842 * @param sql the SQL string 843 * @param generatedKeysResult the generated keys {@link MockResultSet} 844 * @param parameters the parameters 845 */ 846 public void prepareGeneratedKeys(String sql, MockResultSet generatedKeysResult, Map parameters) 847 { 848 List list = getListFromMapForSQLStatement(sql, generatedKeysForStatement); 849 list.add(new MockResultSetWrapper(generatedKeysResult, new HashMap(parameters))); 850 } 851 852 private List getListFromMapForSQLStatement(String sql, Map map) 853 { 854 List list = (List)map.get(sql); 855 if(null == list) 856 { 857 list = new ArrayList(); 858 map.put(sql, list); 859 } 860 return list; 861 } 862 863 private Map createParameterMap(List parameters) 864 { 865 Map params = new HashMap(); 866 for(int ii = 0; ii < parameters.size(); ii++) 867 { 868 params.put(new Integer(ii + 1), parameters.get(ii)); 869 } 870 return params; 871 } 872 873 protected class ParameterWrapper 874 { 875 private Map parameters; 876 877 public ParameterWrapper(Map parameters) 878 { 879 this.parameters = parameters; 880 } 881 882 public Map getParamters() 883 { 884 return parameters; 885 } 886 } 887 888 private class MockSQLExceptionWrapper extends ParameterWrapper 889 { 890 private SQLException exception; 891 892 893 public MockSQLExceptionWrapper(SQLException exception, Map parameters) 894 { 895 super(parameters); 896 this.exception = exception; 897 } 898 899 public SQLException getException() 900 { 901 return exception; 902 } 903 } 904 905 private class MockResultSetWrapper extends ParameterWrapper 906 { 907 private MockResultSet resultSet; 908 909 public MockResultSetWrapper(MockResultSet resultSet, Map parameters) 910 { 911 super(parameters); 912 this.resultSet = resultSet; 913 } 914 915 public MockResultSet getResultSet() 916 { 917 return resultSet; 918 } 919 } 920 921 private class MockResultSetArrayWrapper extends ParameterWrapper 922 { 923 private MockResultSet[] resultSets; 924 925 public MockResultSetArrayWrapper(MockResultSet[] resultSets, Map parameters) 926 { 927 super(parameters); 928 this.resultSets = resultSets; 929 } 930 931 public MockResultSet[] getResultSets() 932 { 933 return resultSets; 934 } 935 } 936 937 private class MockUpdateCountWrapper extends ParameterWrapper 938 { 939 private Integer updateCount; 940 941 public MockUpdateCountWrapper(int updateCount, Map parameters) 942 { 943 super(parameters); 944 this.updateCount = new Integer(updateCount); 945 } 946 947 public Integer getUpdateCount() 948 { 949 return updateCount; 950 } 951 } 952 953 private class MockUpdateCountArrayWrapper extends ParameterWrapper 954 { 955 private Integer[] updateCounts; 956 957 public MockUpdateCountArrayWrapper(int[] updateCounts, Map parameters) 958 { 959 super(parameters); 960 this.updateCounts = (Integer[])ArrayUtil.convertToObjectArray(updateCounts); 961 } 962 963 public Integer[] getUpdateCount() 964 { 965 return updateCounts; 966 } 967 } 968 }