KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > dbunit > dataset > filter > PatternMatcher


1 /*
2  *
3  * The DbUnit Database Testing Framework
4  * Copyright (C)2002-2004, DbUnit.org
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  */

21 package org.dbunit.dataset.filter;
22
23 import java.util.Set JavaDoc;
24 import java.util.HashSet JavaDoc;
25 import java.util.Iterator JavaDoc;
26
27 /**
28  * @author Manuel Laflamme
29  * @since Apr 17, 2004
30  * @version $Revision: 1.1 $
31  */

32 class PatternMatcher
33 {
34     private final Set JavaDoc _acceptedNames = new HashSet JavaDoc();
35     private final Set JavaDoc _acceptedPatterns = new HashSet JavaDoc();
36
37     /**
38      * Add a new accepted pattern.
39      * The following wildcard characters are supported:
40      * '*' matches zero or more characters,
41      * '?' matches one character.
42      */

43     public void addPattern(String JavaDoc patternName)
44     {
45         if (patternName.indexOf("*") != -1 || patternName.indexOf("?") != -1)
46         {
47             _acceptedPatterns.add(patternName);
48         }
49         else
50         {
51             _acceptedNames.add(patternName.toUpperCase());
52         }
53     }
54
55     public boolean isEmpty()
56     {
57         if (_acceptedNames.isEmpty() && _acceptedPatterns.isEmpty())
58         {
59             return true;
60         }
61
62         return false;
63     }
64
65     public boolean accept(String JavaDoc name)
66     {
67         if (_acceptedNames.contains(name.toUpperCase()))
68         {
69             return true;
70         }
71
72         if (_acceptedPatterns.size() > 0)
73         {
74             for (Iterator JavaDoc it = _acceptedPatterns.iterator(); it.hasNext();)
75             {
76                 String JavaDoc pattern = (String JavaDoc)it.next();
77                 if (match(pattern, name, false))
78                 {
79                     return true;
80                 }
81             }
82         }
83
84         return false;
85     }
86
87     /**
88      * Matches a string against a pattern. The pattern contains two special
89      * characters:
90      * '*' which means zero or more characters,
91      * '?' which means one and only one character.
92      *
93      * @param pattern the (non-null) pattern to match against
94      * @param str the (non-null) string that must be matched against the
95      * pattern
96      *
97      * @return <code>true</code> when the string matches against the pattern,
98      * <code>false</code> otherwise.
99      */

100     private boolean match(String JavaDoc pattern, String JavaDoc str, boolean isCaseSensitive)
101     {
102         /* Following pattern matching code taken from the Apache Ant project. */
103
104         char[] patArr = pattern.toCharArray();
105         char[] strArr = str.toCharArray();
106         int patIdxStart = 0;
107         int patIdxEnd = patArr.length - 1;
108         int strIdxStart = 0;
109         int strIdxEnd = strArr.length - 1;
110         char ch;
111
112         boolean containsStar = false;
113         for (int i = 0; i < patArr.length; i++)
114         {
115             if (patArr[i] == '*')
116             {
117                 containsStar = true;
118                 break;
119             }
120         }
121
122         if (!containsStar)
123         {
124             // No '*'s, so we make a shortcut
125
if (patIdxEnd != strIdxEnd)
126             {
127                 return false; // Pattern and string do not have the same size
128
}
129             for (int i = 0; i <= patIdxEnd; i++)
130             {
131                 ch = patArr[i];
132                 if (ch != '?')
133                 {
134                     if (isCaseSensitive && ch != strArr[i])
135                     {
136                         return false;// Character mismatch
137
}
138                     if (!isCaseSensitive && Character.toUpperCase(ch) !=
139                             Character.toUpperCase(strArr[i]))
140                     {
141                         return false; // Character mismatch
142
}
143                 }
144             }
145             return true; // String matches against pattern
146
}
147
148         if (patIdxEnd == 0)
149         {
150             return true; // Pattern contains only '*', which matches anything
151
}
152
153         // Process characters before first star
154
while ((ch = patArr[patIdxStart]) != '*' && strIdxStart <= strIdxEnd)
155         {
156             if (ch != '?')
157             {
158                 if (isCaseSensitive && ch != strArr[strIdxStart])
159                 {
160                     return false;// Character mismatch
161
}
162                 if (!isCaseSensitive && Character.toUpperCase(ch) !=
163                         Character.toUpperCase(strArr[strIdxStart]))
164                 {
165                     return false;// Character mismatch
166
}
167             }
168             patIdxStart++;
169             strIdxStart++;
170         }
171         if (strIdxStart > strIdxEnd)
172         {
173             // All characters in the string are used. Check if only '*'s are
174
// left in the pattern. If so, we succeeded. Otherwise failure.
175
for (int i = patIdxStart; i <= patIdxEnd; i++)
176             {
177                 if (patArr[i] != '*')
178                 {
179                     return false;
180                 }
181             }
182             return true;
183         }
184
185         // Process characters after last star
186
while ((ch = patArr[patIdxEnd]) != '*' && strIdxStart <= strIdxEnd)
187         {
188             if (ch != '?')
189             {
190                 if (isCaseSensitive && ch != strArr[strIdxEnd])
191                 {
192                     return false;// Character mismatch
193
}
194                 if (!isCaseSensitive && Character.toUpperCase(ch) !=
195                         Character.toUpperCase(strArr[strIdxEnd]))
196                 {
197                     return false;// Character mismatch
198
}
199             }
200             patIdxEnd--;
201             strIdxEnd--;
202         }
203         if (strIdxStart > strIdxEnd)
204         {
205             // All characters in the string are used. Check if only '*'s are
206
// left in the pattern. If so, we succeeded. Otherwise failure.
207
for (int i = patIdxStart; i <= patIdxEnd; i++)
208             {
209                 if (patArr[i] != '*')
210                 {
211                     return false;
212                 }
213             }
214             return true;
215         }
216
217         // process pattern between stars. padIdxStart and patIdxEnd point
218
// always to a '*'.
219
while (patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd)
220         {
221             int patIdxTmp = -1;
222             for (int i = patIdxStart + 1; i <= patIdxEnd; i++)
223             {
224                 if (patArr[i] == '*')
225                 {
226                     patIdxTmp = i;
227                     break;
228                 }
229             }
230             if (patIdxTmp == patIdxStart + 1)
231             {
232                 // Two stars next to each other, skip the first one.
233
patIdxStart++;
234                 continue;
235             }
236             // Find the pattern between padIdxStart & padIdxTmp in str between
237
// strIdxStart & strIdxEnd
238
int patLength = (patIdxTmp - patIdxStart - 1);
239             int strLength = (strIdxEnd - strIdxStart + 1);
240             int foundIdx = -1;
241             strLoop:
242             for (int i = 0; i <= strLength - patLength; i++)
243             {
244                 for (int j = 0; j < patLength; j++)
245                 {
246                     ch = patArr[patIdxStart + j + 1];
247                     if (ch != '?')
248                     {
249                         if (isCaseSensitive && ch != strArr[strIdxStart + i + j])
250                         {
251                             continue strLoop;
252                         }
253                         if (!isCaseSensitive && Character.toUpperCase(ch) !=
254                                 Character.toUpperCase(strArr[strIdxStart + i + j]))
255                         {
256                             continue strLoop;
257                         }
258                     }
259                 }
260
261                 foundIdx = strIdxStart + i;
262                 break;
263             }
264
265             if (foundIdx == -1)
266             {
267                 return false;
268             }
269
270             patIdxStart = patIdxTmp;
271             strIdxStart = foundIdx + patLength;
272         }
273
274         // All characters in the string are used. Check if only '*'s are left
275
// in the pattern. If so, we succeeded. Otherwise failure.
276
for (int i = patIdxStart; i <= patIdxEnd; i++)
277         {
278             if (patArr[i] != '*')
279             {
280                 return false;
281             }
282         }
283         return true;
284     }
285
286 }
287
Popular Tags