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 }