001: package com.mockrunner.jdbc;
002:
003: import java.sql.SQLException;
004: import java.util.ArrayList;
005: import java.util.Collections;
006: import java.util.List;
007: import java.util.Map;
008: import java.util.TreeMap;
009:
010: import com.mockrunner.mock.jdbc.MockResultSet;
011: import com.mockrunner.util.common.ArrayUtil;
012:
013: /**
014: * Abstract base class for all <code>ResultSet</code> handlers.
015: * Used to coordinate <code>ResultSet</code> objects for a
016: * statement. You can use this class to prepare <code>ResultSet</code>
017: * objects and update count values that are returned by the
018: * <code>execute</code> method of a statement, if the current
019: * SQL string matches.
020: * Furthermore it can be used to create <code>ResultSet</code> objects.
021: * Please note that the <code>ResultSet</code> objects you create and
022: * prepare with this handler are cloned when executing statements.
023: * So you cannot rely on object identity. You have to use the id
024: * of the <code>ResultSet</code> to identify it.
025: * The <code>ResultSet</code> objects returned by {@link #getReturnedResultSets}
026: * are actually the instances the executed statements returned.
027: */
028: public abstract class AbstractResultSetHandler {
029: private boolean caseSensitive = false;
030: private boolean exactMatch = false;
031: private boolean useRegularExpressions = false;
032: private boolean continueProcessingOnBatchFailure = false;
033: private Object globalResultSets;
034: private Map resultSetsForStatement = new TreeMap();
035: private Object globalUpdateCounts;
036: private Map updateCountForStatement = new TreeMap();
037: private MockResultSet globalGeneratedKeys;
038: private Map generatedKeysForStatement = new TreeMap();
039: private Map returnsResultSetMap = new TreeMap();
040: private Map throwsSQLException = new TreeMap();
041: private List executedStatements = new ArrayList();
042: private List returnedResultSets = new ArrayList();
043:
044: /**
045: * Creates a new <code>ResultSet</code> with a
046: * random id.
047: * @return the new <code>ResultSet</code>
048: */
049: public MockResultSet createResultSet() {
050: return new MockResultSet(String.valueOf(Math.random()));
051: }
052:
053: /**
054: * Creates a new <code>ResultSet</code> with the specified id.
055: * @param id the id
056: * @return the new <code>ResultSet</code>
057: */
058: public MockResultSet createResultSet(String id) {
059: return new MockResultSet(id);
060: }
061:
062: /**
063: * Returns a new <code>ResultSet</code> created by the specified factory.
064: * Creates a random id.
065: * @param factory the {@link ResultSetFactory}
066: * @return the new <code>ResultSet</code>
067: */
068: public MockResultSet createResultSet(ResultSetFactory factory) {
069: return factory.create(String.valueOf(Math.random()));
070: }
071:
072: /**
073: * Returns a new <code>ResultSet</code> created by the specified factory.
074: * @param id the id
075: * @param factory the {@link ResultSetFactory}
076: * @return the new <code>ResultSet</code>
077: */
078: public MockResultSet createResultSet(String id,
079: ResultSetFactory factory) {
080: return factory.create(id);
081: }
082:
083: /**
084: * Set if specified SQL strings should be handled case sensitive.
085: * Defaults to to <code>false</code>, i.e. <i>INSERT</i> is the same
086: * as <i>insert</i>.
087: * Please note that this method controls SQL statement
088: * matching for prepared results and update counts, i.e. what
089: * statements the tested application has to execute to receive
090: * a specified result. Unlike {@link JDBCTestModule#setCaseSensitive(boolean)}
091: * it does not control the statement matching of {@link JDBCTestModule}
092: * methods.
093: * @param caseSensitive enable or disable case sensitivity
094: */
095: public void setCaseSensitive(boolean caseSensitive) {
096: this .caseSensitive = caseSensitive;
097: }
098:
099: /**
100: * Set if specified SQL statements must match exactly.
101: * Defaults to <code>false</code>, i.e. the SQL string
102: * does not need to match exactly. If the original statement
103: * is <i>insert into mytable values(?, ?, ?)</i>
104: * the string <i>insert into mytable</i> will match this statement.
105: * Usually <code>false</code> is the best choice, so
106: * prepared <code>ResultSet</code> objects do not have
107: * to match exactly the current statements SQL string.
108: * The current SQL string just has to contain the SQL string
109: * for the prepared prepared <code>ResultSet</code>.
110: * Please note that this method controls SQL statement
111: * matching for prepared results and update counts, i.e. what
112: * statements the tested application has to execute to receive
113: * a specified result. Unlike {@link JDBCTestModule#setExactMatch(boolean)}
114: * it does not control the statement matching of {@link JDBCTestModule}
115: * methods.
116: * @param exactMatch enable or disable exact matching
117: */
118: public void setExactMatch(boolean exactMatch) {
119: this .exactMatch = exactMatch;
120: }
121:
122: /**
123: * Set if regular expressions should be used when matching
124: * SQL statements. Irrelevant if <code>exactMatch</code> is
125: * <code>true</code>. Default is <code>false</code>, i.e. you
126: * cannot use regular expressions and matching is based
127: * on string comparison.
128: * Please note that this method controls SQL statement
129: * matching for prepared results and update counts, i.e. what
130: * statements the tested application has to execute to receive
131: * a specified result. Unlike {@link JDBCTestModule#setUseRegularExpressions(boolean)}
132: * it does not control the statement matching of {@link JDBCTestModule}
133: * methods.
134: * @param useRegularExpressions should regular expressions be used
135: */
136: public void setUseRegularExpressions(boolean useRegularExpressions) {
137: this .useRegularExpressions = useRegularExpressions;
138: }
139:
140: /**
141: * Set if batch processing should be continued if one of the commands
142: * in the batch fails. This behaviour is driver dependend. The default is
143: * <code>false</code>, i.e. if a command fails with an exception,
144: * batch processing will not continue and the remaining commands
145: * will not be executed.
146: * @param continueProcessingOnBatchFailure should batch processing be continued
147: */
148: public void setContinueProcessingOnBatchFailure(
149: boolean continueProcessingOnBatchFailure) {
150: this .continueProcessingOnBatchFailure = continueProcessingOnBatchFailure;
151: }
152:
153: /**
154: * Collects all SQL strings that were executed.
155: * @param sql the SQL string
156: */
157: public void addExecutedStatement(String sql) {
158: executedStatements.add(sql);
159: }
160:
161: /**
162: * Collects all <code>ResultSet</code> objects that were returned by
163: * a <code>Statement</code>, <code>PreparedStatement</code> or
164: * <code>CallableStatement</code>.
165: * @param resultSet the <code>ResultSet</code>
166: */
167: public void addReturnedResultSet(MockResultSet resultSet) {
168: if (null == resultSet)
169: return;
170: returnedResultSets.add(resultSet);
171: }
172:
173: /**
174: * Collects all <code>ResultSet[]</code> objects that were returned by
175: * a <code>Statement</code>, <code>PreparedStatement</code> or
176: * <code>CallableStatement</code>. Called if a statement returns
177: * multiple result sets.
178: * @param resultSets the <code>ResultSet[]</code>
179: */
180: public void addReturnedResultSets(MockResultSet[] resultSets) {
181: if (null == resultSets)
182: return;
183: returnedResultSets.add(resultSets);
184: }
185:
186: /**
187: * Returns the <code>List</code> of all executed SQL strings.
188: * @return the <code>List</code> of executed SQL strings
189: */
190: public List getExecutedStatements() {
191: return Collections.unmodifiableList(executedStatements);
192: }
193:
194: /**
195: * Returns the <code>List</code> of all returned <code>ResultSet</code>
196: * or <code>ResultSet[]</code> objects. The <code>List</code> contains
197: * arrays of result sets, if a query returned multiple result sets.
198: * If a query returned multiple result sets, the list will always contain
199: * the full array of <code>ResultSet</code> objects that were prepared, even
200: * if {@link com.mockrunner.mock.jdbc.MockStatement#getMoreResults()} was
201: * not called for all the result sets.
202: * @return the <code>List</code> of returned <code>ResultSet</code> or <code>ResultSet[]</code> objects
203: */
204: public List getReturnedResultSets() {
205: return Collections.unmodifiableList(returnedResultSets);
206: }
207:
208: /**
209: * Clears all prepared <code>ResultSet</code> objects.
210: */
211: public void clearResultSets() {
212: resultSetsForStatement.clear();
213: }
214:
215: /**
216: * Clears all prepared update counts.
217: */
218: public void clearUpdateCounts() {
219: updateCountForStatement.clear();
220: }
221:
222: /**
223: * Clears the definitions if statements return
224: * <code>ResultSet</code> objects or update counts.
225: */
226: public void clearReturnsResultSet() {
227: returnsResultSetMap.clear();
228: }
229:
230: /**
231: * Clears the list of statements that should throw an exception.
232: */
233: public void clearThrowsSQLException() {
234: throwsSQLException.clear();
235: }
236:
237: /**
238: * Clears the list of statements that return generated keys.
239: */
240: public void clearGeneratedKeys() {
241: generatedKeysForStatement.clear();
242: }
243:
244: /**
245: * Clears the prepared global <code>ResultSet</code>.
246: */
247: public void clearGlobalResultSet() {
248: this .globalResultSets = null;
249: }
250:
251: /**
252: * Clears the prepared global generated keys <code>ResultSet</code>.
253: */
254: public void clearGlobalGeneratedKeys() {
255: this .globalGeneratedKeys = null;
256: }
257:
258: /**
259: * Clears the prepared global update count.
260: */
261: public void clearGlobalUpdateCount() {
262: this .globalUpdateCounts = null;
263: }
264:
265: /**
266: * Returns the <code>Map</code> of all <code>ResultSet</code>
267: * objects, that were added with {@link #prepareResultSet(String, MockResultSet)}.
268: * The SQL strings map to the corresponding <code>ResultSet</code>.
269: * @return the <code>Map</code> of <code>ResultSet</code> objects
270: */
271: public Map getResultSetMap() {
272: return Collections.unmodifiableMap(resultSetsForStatement);
273: }
274:
275: /**
276: * Returns the <code>Map</code> of all update counts, that were added
277: * with {@link #prepareUpdateCount(String, int)}.
278: * The SQL strings map to the corresponding update count as
279: * <code>Integer</code> object.
280: * @return the <code>Map</code> of <code>ResultSet</code> objects
281: */
282: public Map getUpdateCountMap() {
283: return Collections.unmodifiableMap(updateCountForStatement);
284: }
285:
286: /**
287: * Returns the <code>Map</code> of all generated keys <code>ResultSet</code>
288: * objects, that were added with {@link #prepareGeneratedKeys(String, MockResultSet)}.
289: * The SQL strings map to the corresponding generated keys <code>ResultSet</code>.
290: * @return the <code>Map</code> of generated keys <code>ResultSet</code> objects
291: */
292: public Map getGeneratedKeysMap() {
293: return Collections.unmodifiableMap(generatedKeysForStatement);
294: }
295:
296: /**
297: * Returns the first <code>ResultSet</code> that matches the
298: * specified SQL string. If the specified SQL string was
299: * prepared to return multiple result sets, the first one will
300: * be returned.
301: * Please note that you can modify the match parameters with {@link #setCaseSensitive},
302: * {@link #setExactMatch} and {@link #setUseRegularExpressions}.
303: * @param sql the SQL string
304: * @return the corresponding {@link MockResultSet}
305: */
306: public MockResultSet getResultSet(String sql) {
307: Object resultSets = getMatchingResultSets(sql);
308: if (null == resultSets)
309: return null;
310: if (resultSets instanceof MockResultSet) {
311: return (MockResultSet) resultSets;
312: } else if (resultSets instanceof MockResultSet[]) {
313: MockResultSet[] actualResults = (MockResultSet[]) resultSets;
314: if (actualResults.length > 0) {
315: return actualResults[0];
316: }
317: }
318: return null;
319: }
320:
321: /**
322: * Returns the first <code>ResultSet[]</code> that matches the
323: * specified SQL string. If the specified SQL string was
324: * prepared to return one single result set, this <code>ResultSet</code>
325: * will be wrapped in an array with one element.
326: * Please note that you can modify the match parameters with {@link #setCaseSensitive},
327: * {@link #setExactMatch} and {@link #setUseRegularExpressions}.
328: * @param sql the SQL string
329: * @return the corresponding <code>MockResultSet[]</code>
330: */
331: public MockResultSet[] getResultSets(String sql) {
332: Object resultSets = getMatchingResultSets(sql);
333: if (null == resultSets)
334: return null;
335: if (resultSets instanceof MockResultSet) {
336: return new MockResultSet[] { (MockResultSet) resultSets };
337: } else if (resultSets instanceof MockResultSet[]) {
338: return (MockResultSet[]) resultSets;
339: }
340: return null;
341: }
342:
343: /**
344: * Returns the if the specified SQL string returns multiple result sets.
345: * Please note that you can modify the match parameters with {@link #setCaseSensitive},
346: * {@link #setExactMatch} and {@link #setUseRegularExpressions}.
347: * @param sql the SQL string
348: * @return <code>true</code> if the query returns multiple result sets,
349: * <code>false</code> otherwise
350: */
351: public boolean hasMultipleResultSets(String sql) {
352: Object resultSets = getMatchingResultSets(sql);
353: return (resultSets instanceof MockResultSet[]);
354: }
355:
356: private Object getMatchingResultSets(String sql) {
357: SQLStatementMatcher matcher = new SQLStatementMatcher(
358: getCaseSensitive(), getExactMatch(),
359: getUseRegularExpressions());
360: List list = matcher.getMatchingObjects(resultSetsForStatement,
361: sql, true, true);
362: if (null != list && list.size() > 0) {
363: return list.get(0);
364: }
365: return null;
366: }
367:
368: /**
369: * Returns the global <code>ResultSet</code>.
370: * If an array of global result sets was prepared, the first one will
371: * be returned.
372: * @return the global {@link MockResultSet}
373: */
374: public MockResultSet getGlobalResultSet() {
375: if (null == globalResultSets)
376: return null;
377: if (globalResultSets instanceof MockResultSet) {
378: return (MockResultSet) globalResultSets;
379: }
380: MockResultSet[] resultSets = getGlobalResultSets();
381: if (null != resultSets && resultSets.length > 0) {
382: return resultSets[0];
383: }
384: return null;
385: }
386:
387: /**
388: * Returns the global <code>ResultSet[]</code>.
389: * If one single <code>ResultSet</code> was prepared, this <code>ResultSet</code>
390: * will be wrapped in an array with one element.
391: * @return the global <code>MockResultSet[]</code>
392: */
393: public MockResultSet[] getGlobalResultSets() {
394: if (null == globalResultSets)
395: return null;
396: if (globalResultSets instanceof MockResultSet[]) {
397: return (MockResultSet[]) globalResultSets;
398: }
399: return new MockResultSet[] { (MockResultSet) globalResultSets };
400: }
401:
402: /**
403: * Returns if multiple global result sets have been prepared, i.e. if
404: * an array of global result sets was prepared.
405: * @return <code>true</code> if an array of global result sets was prepared,
406: * <code>false</code> otherwise
407: */
408: public boolean hasMultipleGlobalResultSets() {
409: return (globalResultSets instanceof MockResultSet[]);
410: }
411:
412: /**
413: * Returns the first update count that matches the
414: * specified SQL string. If the specified SQL string was
415: * prepared to return multiple update counts, the first one will
416: * be returned.
417: * Please note that you can modify the match parameters with {@link #setCaseSensitive},
418: * {@link #setExactMatch} and {@link #setUseRegularExpressions}.
419: * @param sql the SQL string
420: * @return the corresponding update count
421: */
422: public Integer getUpdateCount(String sql) {
423: Object updateCounts = getMatchingUpdateCounts(sql);
424: if (null == updateCounts)
425: return null;
426: if (updateCounts instanceof Integer) {
427: return (Integer) updateCounts;
428: } else if (updateCounts instanceof Integer[]) {
429: Integer[] actualUpdateCounts = (Integer[]) updateCounts;
430: if (actualUpdateCounts.length > 0) {
431: return actualUpdateCounts[0];
432: }
433: }
434: return null;
435: }
436:
437: /**
438: * Returns the first update count array that matches the
439: * specified SQL string. If the specified SQL string was
440: * prepared to return one update count, this value
441: * will be wrapped in an array with one element.
442: * Please note that you can modify the match parameters with {@link #setCaseSensitive},
443: * {@link #setExactMatch} and {@link #setUseRegularExpressions}.
444: * @param sql the SQL string
445: * @return the corresponding update count array
446: */
447: public Integer[] getUpdateCounts(String sql) {
448: Object updateCounts = getMatchingUpdateCounts(sql);
449: if (null == updateCounts)
450: return null;
451: if (updateCounts instanceof Integer) {
452: return new Integer[] { (Integer) updateCounts };
453: } else if (updateCounts instanceof Integer[]) {
454: return (Integer[]) updateCounts;
455: }
456: return null;
457: }
458:
459: /**
460: * Returns the if the specified SQL string returns multiple update counts.
461: * Please note that you can modify the match parameters with {@link #setCaseSensitive},
462: * {@link #setExactMatch} and {@link #setUseRegularExpressions}.
463: * @param sql the SQL string
464: * @return <code>true</code> if the SQL string returns multiple update counts,
465: * <code>false</code> otherwise
466: */
467: public boolean hasMultipleUpdateCounts(String sql) {
468: Object updateCounts = getMatchingUpdateCounts(sql);
469: return (updateCounts instanceof Integer[]);
470: }
471:
472: private Object getMatchingUpdateCounts(String sql) {
473: SQLStatementMatcher matcher = new SQLStatementMatcher(
474: getCaseSensitive(), getExactMatch(),
475: getUseRegularExpressions());
476: List list = matcher.getMatchingObjects(updateCountForStatement,
477: sql, true, true);
478: if (null != list && list.size() > 0) {
479: return list.get(0);
480: }
481: return null;
482: }
483:
484: /**
485: * Returns the global update count for <code>executeUpdate</code> calls.
486: * If an array of global update counts was prepared, the first one will
487: * be returned.
488: * @return the global update count
489: */
490: public int getGlobalUpdateCount() {
491: if (null == globalUpdateCounts)
492: return 0;
493: if (globalUpdateCounts instanceof Integer) {
494: return ((Integer) globalUpdateCounts).intValue();
495: }
496: int[] updateCounts = getGlobalUpdateCounts();
497: if (null != updateCounts && updateCounts.length > 0) {
498: return updateCounts[0];
499: }
500: return 0;
501: }
502:
503: /**
504: * Returns the array of global update counts.
505: * If one single update count value was prepared, this value
506: * will be wrapped in an array with one element.
507: * @return the array of global update counts
508: */
509: public int[] getGlobalUpdateCounts() {
510: if (null == globalUpdateCounts)
511: return null;
512: if (globalUpdateCounts instanceof int[]) {
513: return (int[]) globalUpdateCounts;
514: }
515: return new int[] { ((Integer) globalUpdateCounts).intValue() };
516: }
517:
518: /**
519: * Returns if multiple global update counts have been prepared, i.e. if
520: * an array of global update counts was prepared.
521: * @return <code>true</code> if an array of global update counts was prepared,
522: * <code>false</code> otherwise
523: */
524: public boolean hasMultipleGlobalUpdateCounts() {
525: return (globalUpdateCounts instanceof int[]);
526: }
527:
528: /**
529: * Returns the first generated keys <code>ResultSet</code> that
530: * matches the specified SQL string. Please note that you can modify
531: * the match parameters with {@link #setCaseSensitive},
532: * {@link #setExactMatch} and {@link #setUseRegularExpressions}.
533: * @param sql the SQL string
534: * @return the corresponding generated keys {@link MockResultSet}
535: */
536: public MockResultSet getGeneratedKeys(String sql) {
537: SQLStatementMatcher matcher = new SQLStatementMatcher(
538: getCaseSensitive(), getExactMatch(),
539: getUseRegularExpressions());
540: List list = matcher.getMatchingObjects(
541: generatedKeysForStatement, sql, true, true);
542: if (null != list && list.size() > 0) {
543: return (MockResultSet) list.get(0);
544: }
545: return null;
546: }
547:
548: /**
549: * Returns the global generated keys <code>ResultSet</code>.
550: * @return the global generated keys {@link MockResultSet}
551: */
552: public MockResultSet getGlobalGeneratedKeys() {
553: return globalGeneratedKeys;
554: }
555:
556: /**
557: * Returns if the specified SQL string is a <i>select</i> that returns
558: * a <code>ResultSet</code>.
559: * Usually you do not have to specify this.
560: * It is assumed that an SQL string returns a <code>ResultSet</code>
561: * if it contains the string <i>select</i> (case insensitive).
562: * Please note that you can modify the match parameters with
563: * {@link #setCaseSensitive}, {@link #setExactMatch} and
564: * {@link #setUseRegularExpressions}.
565: * @param sql the SQL string
566: * @return <code>true</code> if the SQL string returns a <code>ResultSet</code>
567: */
568: public Boolean getReturnsResultSet(String sql) {
569: SQLStatementMatcher matcher = new SQLStatementMatcher(
570: getCaseSensitive(), getExactMatch(),
571: getUseRegularExpressions());
572: List list = matcher.getMatchingObjects(returnsResultSetMap,
573: sql, true, true);
574: if (null != list && list.size() > 0) {
575: return (Boolean) list.get(0);
576: }
577: return null;
578: }
579:
580: /**
581: * Returns if the specified SQL string should raise an exception.
582: * This can be used to simulate database exceptions.
583: * Please note that you can modify the match parameters with
584: * {@link #setCaseSensitive}, {@link #setExactMatch} and
585: * {@link #setUseRegularExpressions}.
586: * @param sql the SQL string
587: * @return <code>true</code> if the specified SQL string should raise an exception,
588: * <code>false</code> otherwise
589: */
590: public boolean getThrowsSQLException(String sql) {
591: return (getSQLException(sql) != null);
592: }
593:
594: /**
595: * Returns the <code>SQLException</code> the specified SQL string
596: * should throw. Returns <code>null</code> if the specified SQL string
597: * should not throw an exception.
598: * This can be used to simulate database exceptions.
599: * Please note that you can modify the match parameters with
600: * {@link #setCaseSensitive}, {@link #setExactMatch} and
601: * {@link #setUseRegularExpressions}.
602: * @param sql the SQL string
603: * @return the <code>SQLException</code> or <code>null</code>
604: */
605: public SQLException getSQLException(String sql) {
606: SQLStatementMatcher matcher = new SQLStatementMatcher(
607: getCaseSensitive(), getExactMatch(),
608: getUseRegularExpressions());
609: List list = matcher.getMatchingObjects(throwsSQLException, sql,
610: true, true);
611: if (null == list || list.size() == 0)
612: return null;
613: return (SQLException) list.get(0);
614: }
615:
616: /**
617: * Prepare a <code>ResultSet</code> for a specified SQL string.
618: * Please note that you can modify the match parameters with
619: * {@link #setCaseSensitive}, {@link #setExactMatch} and
620: * {@link #setUseRegularExpressions}.
621: * @param sql the SQL string
622: * @param resultSet the corresponding {@link MockResultSet}
623: */
624: public void prepareResultSet(String sql, MockResultSet resultSet) {
625: resultSetsForStatement.put(sql, resultSet);
626: }
627:
628: /**
629: * Prepare an array of <code>ResultSet</code> objects for a specified SQL string.
630: * This method can be used for queries that return multiple result sets.
631: * Please note that you can modify the match parameters with
632: * {@link #setCaseSensitive}, {@link #setExactMatch} and
633: * {@link #setUseRegularExpressions}.
634: * @param sql the SQL string
635: * @param resultSets the corresponding <code>MockResultSet[]</code>
636: */
637: public void prepareResultSets(String sql, MockResultSet[] resultSets) {
638: resultSetsForStatement.put(sql, resultSets.clone());
639: }
640:
641: /**
642: * Prepare the global <code>ResultSet</code>.
643: * @param resultSet the {@link MockResultSet}
644: */
645: public void prepareGlobalResultSet(MockResultSet resultSet) {
646: this .globalResultSets = resultSet;
647: }
648:
649: /**
650: * Prepare an array of global <code>ResultSet</code> objects.
651: * @param resultSets the corresponding <code>MockResultSet[]</code>
652: */
653: public void prepareGlobalResultSets(MockResultSet[] resultSets) {
654: this .globalResultSets = (MockResultSet[]) resultSets.clone();
655: }
656:
657: /**
658: * Prepare the update count for <code>executeUpdate</code> calls
659: * for a specified SQL string. Please note that you can modify
660: * the match parameters with {@link #setCaseSensitive},
661: * {@link #setExactMatch} and {@link #setUseRegularExpressions}.
662: * @param sql the SQL string
663: * @param updateCount the update count
664: */
665: public void prepareUpdateCount(String sql, int updateCount) {
666: updateCountForStatement.put(sql, new Integer(updateCount));
667: }
668:
669: /**
670: * Prepare an array update count values for <code>executeUpdate</code> calls
671: * for a specified SQL string. This method can be used if multiple update counts
672: * are returned.
673: * Please note that you can modify the match parameters with {@link #setCaseSensitive},
674: * {@link #setExactMatch} and {@link #setUseRegularExpressions}.
675: * @param sql the SQL string
676: * @param updateCounts the update count array
677: */
678: public void prepareUpdateCounts(String sql, int[] updateCounts) {
679: updateCountForStatement.put(sql, ArrayUtil
680: .convertToObjectArray(updateCounts));
681: }
682:
683: /**
684: * Prepare the global update count for <code>executeUpdate</code> calls.
685: * @param updateCount the update count
686: */
687: public void prepareGlobalUpdateCount(int updateCount) {
688: this .globalUpdateCounts = new Integer(updateCount);
689: }
690:
691: /**
692: * Prepare an array of global update count values for <code>executeUpdate</code> calls.
693: * @param updateCounts the update count array
694: */
695: public void prepareGlobalUpdateCounts(int[] updateCounts) {
696: this .globalUpdateCounts = (int[]) updateCounts.clone();
697: }
698:
699: /**
700: * Prepare the generated keys <code>ResultSet</code>
701: * for a specified SQL string. Please note that you can modify
702: * the match parameters with {@link #setCaseSensitive},
703: * {@link #setExactMatch} and {@link #setUseRegularExpressions}.
704: * @param sql the SQL string
705: * @param generatedKeysResult the generated keys {@link MockResultSet}
706: */
707: public void prepareGeneratedKeys(String sql,
708: MockResultSet generatedKeysResult) {
709: generatedKeysForStatement.put(sql, generatedKeysResult);
710: }
711:
712: /**
713: * Prepare the global generated keys <code>ResultSet</code>.
714: * @param generatedKeysResult the generated keys {@link MockResultSet}
715: */
716: public void prepareGlobalGeneratedKeys(
717: MockResultSet generatedKeysResult) {
718: this .globalGeneratedKeys = generatedKeysResult;
719: }
720:
721: /**
722: * Prepare if the specified SQL string is a <i>select</i> that returns
723: * a <code>ResultSet</code>. Usually you do not have to specify this.
724: * It is assumed that an SQL string returns a <code>ResultSet</code>
725: * if it contains the string <i>select</i> (case insensitive).
726: * Please note that you can modify the match parameters with
727: * {@link #setCaseSensitive}, {@link #setExactMatch} and
728: * {@link #setUseRegularExpressions}.
729: * @param sql the SQL string
730: * @param returnsResultSet specify if the SQL string returns a <code>ResultSet</code>
731: */
732: public void prepareReturnsResultSet(String sql,
733: boolean returnsResultSet) {
734: returnsResultSetMap.put(sql, new Boolean(returnsResultSet));
735: }
736:
737: /**
738: * Prepare that the specified SQL string should raise an exception.
739: * This can be used to simulate database exceptions. This method
740: * creates an <code>SQLException</code> and will throw this exception.
741: * With {@link #prepareThrowsSQLException(String, SQLException)} you
742: * can specify the exception.
743: * Please note that you can modify the match parameters with
744: * {@link #setCaseSensitive}, {@link #setExactMatch} and
745: * {@link #setUseRegularExpressions}.
746: * @param sql the SQL string
747: */
748: public void prepareThrowsSQLException(String sql) {
749: throwsSQLException.put(sql, new SQLException("Statement " + sql
750: + " was specified to throw an exception"));
751: }
752:
753: /**
754: * Prepare that the specified SQL string should raise an exception.
755: * This can be used to simulate database exceptions. This method
756: * takes an exception object that will be thrown.
757: * Please note that you can modify the match parameters with
758: * {@link #setCaseSensitive}, {@link #setExactMatch} and
759: * {@link #setUseRegularExpressions}.
760: * @param sql the SQL string
761: * @param exc the <code>SQLException</code> that should be thrown
762: */
763: public void prepareThrowsSQLException(String sql, SQLException exc) {
764: throwsSQLException.put(sql, exc);
765: }
766:
767: /**
768: * Returns if specified SQL strings should be handled case sensitive.
769: * @return is case sensitivity enabled or disabled
770: */
771: protected boolean getCaseSensitive() {
772: return caseSensitive;
773: }
774:
775: /**
776: * Returns if specified SQL statements must match exactly.
777: * @return is exact matching enabled or disabled
778: */
779: protected boolean getExactMatch() {
780: return exactMatch;
781: }
782:
783: /**
784: * Returns if regular expression matching is enabled
785: * @return if regular expression matching is enabled
786: */
787: protected boolean getUseRegularExpressions() {
788: return useRegularExpressions;
789: }
790:
791: /**
792: * Returns if batch processing should be continued if one of
793: * the commands in the batch fails.
794: * @return if batch processing should be continued
795: */
796: public boolean getContinueProcessingOnBatchFailure() {
797: return continueProcessingOnBatchFailure;
798: }
799: }
|