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