001 package com.mockrunner.jdbc;
002
003 import java.util.ArrayList;
004 import java.util.Collection;
005 import java.util.Iterator;
006 import java.util.List;
007 import java.util.Map;
008
009 import com.mockrunner.util.common.StringUtil;
010
011 /**
012 * Helper class for finding matching SQL statements based on various
013 * search parameters. The search parameters are:
014 * <br>
015 * <code>caseSensitive</code> do a case sensitive match (default is <code>false</code>)
016 * <br>
017 * <code>exactMatch</code> the strings must match exactly, the parameter <code>caseSensitive</code>
018 * is recognized, but <code>useRegularExpression</code> is irrelevant,
019 * if <code>exactMatch</code> is <code>true</code> (default is <code>false</code>)
020 * <br>
021 * <code>useRegularExpression</code> use regular expressions for matching, if this parameter is
022 * <code>false</code>, strings match, if one string starts with the other
023 * (default is <code>false</code>)
024 */
025 public class SQLStatementMatcher
026 {
027 private boolean caseSensitive = false;
028 private boolean exactMatch = false;
029 private boolean useRegularExpressions = false;
030
031 public SQLStatementMatcher(boolean caseSensitive, boolean exactMatch)
032 {
033 this(caseSensitive, exactMatch, false);
034 }
035
036 public SQLStatementMatcher(boolean caseSensitive, boolean exactMatch, boolean useRegularExpressions)
037 {
038 this.caseSensitive = caseSensitive;
039 this.exactMatch = exactMatch;
040 this.useRegularExpressions = useRegularExpressions;
041 }
042
043 /**
044 * Compares all keys in the specified <code>Map</code> with the
045 * specified query string using the method {@link #doStringsMatch}.
046 * If the strings match, the corresponding object from the <code>Map</code>
047 * is added to the resulting <code>List</code>.
048 * @param dataMap the source <code>Map</code>
049 * @param query the query string that must match the keys in <i>dataMap</i>
050 * @param queryContainsMapData only matters if <i>isExactMatch</i> is <code>false</code>,
051 * specifies if query must be contained in the <code>Map</code> keys (<code>false</code>)
052 * or if query must contain the <code>Map</code> keys (<code>true</code>)
053 * @return the result <code>List</code>
054 */
055 public List getMatchingObjects(Map dataMap, String query, boolean resolveCollection, boolean queryContainsMapData)
056 {
057 if(null == query) query = "";
058 Iterator iterator = dataMap.keySet().iterator();
059 ArrayList resultList = new ArrayList();
060 while(iterator.hasNext())
061 {
062 String nextKey = (String)iterator.next();
063 String source, currentQuery;
064 if(queryContainsMapData)
065 {
066 source = query;
067 currentQuery = nextKey;
068 }
069 else
070 {
071 source = nextKey;
072 currentQuery = query;
073 }
074 if(doStringsMatch(source, currentQuery))
075 {
076 Object matchingObject = dataMap.get(nextKey);
077 if(resolveCollection && (matchingObject instanceof Collection))
078 {
079 resultList.addAll((Collection)matchingObject);
080 }
081 else
082 {
083 resultList.add(dataMap.get(nextKey));
084 }
085 }
086 }
087 return resultList;
088 }
089
090 /**
091 * Compares all elements in the specified <code>Collection</code> with the
092 * specified query string using the method {@link #doStringsMatch}.
093 * @param col the <code>Collections</code>
094 * @param query the query string that must match the keys in <i>col</i>
095 * @param queryContainsData only matters if <i>exactMatch</i> is <code>false</code>,
096 * specifies if query must be contained in the <code>Collection</code> data (<code>false</code>)
097 * or if query must contain the <code>Collection</code> data (<code>true</code>)
098 * @return <code>true</code> if <i>col</i> contains <i>query</i>, false otherwise
099 */
100 public boolean contains(Collection col, String query, boolean queryContainsData)
101 {
102 Iterator iterator = col.iterator();
103 while(iterator.hasNext())
104 {
105 String nextKey = (String)iterator.next();
106 String source, currentQuery;
107 if(queryContainsData)
108 {
109 source = query;
110 currentQuery = nextKey;
111 }
112 else
113 {
114 source = nextKey;
115 currentQuery = query;
116 }
117 if(doStringsMatch(source, currentQuery)) return true;
118 }
119 return false;
120 }
121
122 /**
123 * Compares two strings and returns if they match.
124 * @param query the query string that must match source
125 * @param source the source string
126 * @return <code>true</code> of the strings match, <code>false</code> otherwise
127 */
128 public boolean doStringsMatch(String source, String query)
129 {
130 if(null == source) source = "";
131 if(null == query) query = "";
132 if(useRegularExpressions && !exactMatch)
133 {
134 return doPerl5Match(source, query);
135 }
136 else
137 {
138 return doSimpleMatch(source, query);
139 }
140 }
141
142 private boolean doSimpleMatch(String source, String query)
143 {
144 if(exactMatch)
145 {
146 return StringUtil.matchesExact(source, query, caseSensitive);
147 }
148 else
149 {
150 return StringUtil.matchesContains(source, query, caseSensitive);
151 }
152 }
153
154 private boolean doPerl5Match(String source, String query)
155 {
156 return StringUtil.matchesPerl5(source, query, caseSensitive);
157 }
158 }