KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > alfresco > filesys > util > WildCard


1 /*
2  * Copyright (C) 2005 Alfresco, Inc.
3  *
4  * Licensed under the Mozilla Public License version 1.1
5  * with a permitted attribution clause. You may obtain a
6  * copy of the License at
7  *
8  * http://www.alfresco.org/legal/license.txt
9  *
10  * Unless required by applicable law or agreed to in writing,
11  * software distributed under the License is distributed on an
12  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13  * either express or implied. See the License for the specific
14  * language governing permissions and limitations under the
15  * License.
16  */

17 package org.alfresco.filesys.util;
18
19 /**
20  * Wildcard Utility Class.
21  * <p>
22  * The WildCard class may be used to check Strings against a wildcard pattern using the SMB/CIFS
23  * wildcard rules.
24  * <p>
25  * A number of static convenience methods are also provided.
26  *
27  * @author GKSpencer
28  */

29 public final class WildCard
30 {
31
32     // Multiple character wildcard
33

34     public static final int MULTICHAR_WILDCARD = '*';
35
36     // Single character wildcard
37

38     public static final int SINGLECHAR_WILDCARD = '?';
39
40     // Unicode wildcards
41
//
42
// The spec states :-
43
// translate '?' to '>'
44
// translate '.' to '"' if followed by a '?' or '*'
45
// translate '*' to '<' if followed by a '.'
46

47     public static final int SINGLECHAR_UNICODE_WILDCARD = '>';
48     public static final int DOT_UNICODE_WILDCARD = '"';
49     public static final int MULTICHAR_UNICODE_WILDCARD = '<';
50
51     // Wildcard types
52

53     public static final int WILDCARD_NONE = 0; // no wildcard characters present in pattern
54
public static final int WILDCARD_ALL = 1; // '*.*' and '*'
55
public static final int WILDCARD_NAME = 2; // '*.ext'
56
public static final int WILDCARD_EXT = 3; // 'name.*'
57
public static final int WILDCARD_COMPLEX = 4; // complex wildcard
58

59     public static final int WILDCARD_INVALID = -1;
60
61     // Wildcard pattern and type
62

63     private String JavaDoc m_pattern;
64     private int m_type;
65
66     // Start/end string to match for name/extension matching
67

68     private String JavaDoc m_matchPart;
69     private boolean m_caseSensitive;
70
71     // Complex wildcard pattern
72

73     private char[] m_patternChars;
74
75     /**
76      * Default constructor
77      */

78     public WildCard()
79     {
80         setType(WILDCARD_INVALID);
81     }
82
83     /**
84      * Class constructor
85      *
86      * @param pattern String
87      * @param caseSensitive boolean
88      */

89     public WildCard(String JavaDoc pattern, boolean caseSensitive)
90     {
91         setPattern(pattern, caseSensitive);
92     }
93
94     /**
95      * Return the wildcard pattern type
96      *
97      * @return int
98      */

99     public final int isType()
100     {
101         return m_type;
102     }
103
104     /**
105      * Check if case sensitive matching is enabled
106      *
107      * @return boolean
108      */

109     public final boolean isCaseSensitive()
110     {
111         return m_caseSensitive;
112     }
113
114     /**
115      * Return the wildcard pattern string
116      *
117      * @return String
118      */

119     public final String JavaDoc getPattern()
120     {
121         return m_pattern;
122     }
123
124     /**
125      * Return the match part for wildcard name and wildcard extension type patterns
126      *
127      * @return String
128      */

129     public final String JavaDoc getMatchPart()
130     {
131         return m_matchPart;
132     }
133
134     /**
135      * Determine if the string matches the wildcard pattern
136      *
137      * @param str String
138      * @return boolean
139      */

140     public final boolean matchesPattern(String JavaDoc str)
141     {
142
143         // Check the pattern type and compare the string
144

145         boolean sts = false;
146
147         switch (isType())
148         {
149
150         // Match all wildcard
151

152         case WILDCARD_ALL:
153             sts = true;
154             break;
155
156         // Match any name
157

158         case WILDCARD_NAME:
159             if (isCaseSensitive())
160             {
161
162                 // Check if the string ends with the required file extension
163

164                 sts = str.endsWith(m_matchPart);
165             }
166             else
167             {
168
169                 // Normalize the string and compare
170

171                 String JavaDoc upStr = str.toUpperCase();
172                 sts = upStr.endsWith(m_matchPart);
173             }
174             break;
175
176         // Match any file extension
177

178         case WILDCARD_EXT:
179             if (isCaseSensitive())
180             {
181
182                 // Check if the string starts with the required file name
183

184                 sts = str.startsWith(m_matchPart);
185             }
186             else
187             {
188
189                 // Normalize the string and compare
190

191                 String JavaDoc upStr = str.toUpperCase();
192                 sts = upStr.startsWith(m_matchPart);
193             }
194             break;
195
196         // Complex wildcard matching
197

198         case WILDCARD_COMPLEX:
199             if (isCaseSensitive())
200                 sts = matchComplexWildcard(str);
201             else
202             {
203
204                 // Normalize the string and compare
205

206                 String JavaDoc upStr = str.toUpperCase();
207                 sts = matchComplexWildcard(upStr);
208             }
209             break;
210
211         // No wildcard characters in pattern, compare strings
212

213         case WILDCARD_NONE:
214             if (isCaseSensitive())
215             {
216                 if (str.compareTo(m_pattern) == 0)
217                     sts = true;
218             }
219             else if (str.equalsIgnoreCase(m_pattern))
220                 sts = true;
221             break;
222         }
223
224         // Return the wildcard match status
225

226         return sts;
227     }
228
229     /**
230      * Match a complex wildcard pattern with the specified string
231      *
232      * @param str String
233      * @return boolean
234      */

235     protected final boolean matchComplexWildcard(String JavaDoc str)
236     {
237
238         // Convert the string to a char array for matching
239

240         char[] strChars = str.toCharArray();
241
242         // Compare the string to the wildcard pattern
243

244         int wpos = 0;
245         int wlen = m_patternChars.length;
246
247         int spos = 0;
248         int slen = strChars.length;
249
250         char patChar;
251         boolean matchFailed = false;
252
253         while (matchFailed == false && wpos < m_patternChars.length)
254         {
255
256             // Match the current pattern character
257

258             patChar = m_patternChars[wpos++];
259
260             switch (patChar)
261             {
262
263             // Match single character
264

265             case SINGLECHAR_WILDCARD:
266                 if (spos < slen)
267                     spos++;
268                 else
269                     matchFailed = true;
270                 break;
271
272             // Match zero or more characters
273

274             case MULTICHAR_WILDCARD:
275
276                 // Check if there is another character in the wildcard pattern
277

278                 if (wpos < wlen)
279                 {
280
281                     // Check if the character is not a wildcard character
282

283                     patChar = m_patternChars[wpos];
284                     if (patChar != SINGLECHAR_WILDCARD && patChar != MULTICHAR_WILDCARD)
285                     {
286
287                         // Find the required character in the string
288

289                         while (spos < slen && strChars[spos] != patChar)
290                             spos++;
291                         if (spos >= slen)
292                             matchFailed = true;
293                     }
294                 }
295                 else
296                 {
297
298                     // Multi character wildcard at the end of the pattern, match all remaining
299
// characters
300

301                     spos = slen;
302                 }
303                 break;
304
305             // Match the pattern and string character
306

307             default:
308                 if (spos >= slen || strChars[spos] != patChar)
309                     matchFailed = true;
310                 else
311                     spos++;
312                 break;
313             }
314         }
315
316         // Check if the match was successul and return status
317

318         if (matchFailed == false && spos == slen)
319             return true;
320         return false;
321     }
322
323     /**
324      * Set the wildcard pattern string
325      *
326      * @param pattern String
327      * @param caseSensitive boolean
328      */

329     public final void setPattern(String JavaDoc pattern, boolean caseSensitive)
330     {
331
332         // Save the pattern string and case sensitive flag
333

334         m_pattern = pattern;
335         m_caseSensitive = caseSensitive;
336
337         setType(WILDCARD_INVALID);
338
339         // Check if the pattern string is valid
340

341         if (pattern == null || pattern.length() == 0)
342             return;
343
344         // Check for the match all wildcard
345

346         if (pattern.compareTo("*.*") == 0 || pattern.compareTo("*") == 0)
347         {
348             setType(WILDCARD_ALL);
349             return;
350         }
351
352         // Check for a name wildcard, ie. '*.ext'
353

354         if (pattern.startsWith("*."))
355         {
356
357             // Split the string to get the extension string
358

359             if (pattern.length() > 2)
360                 m_matchPart = pattern.substring(1);
361             else
362                 m_matchPart = "";
363
364             // If matching is case insensitive then normalize the string
365

366             if (isCaseSensitive() == false)
367                 m_matchPart = m_matchPart.toUpperCase();
368
369             // If the file extension contains wildcards we will need to use a regular expression
370

371             if (containsWildcards(m_matchPart) == false)
372             {
373                 setType(WILDCARD_NAME);
374                 return;
375             }
376         }
377
378         // Check for a file extension wildcard
379

380         if (pattern.endsWith(".*"))
381         {
382
383             // Split the string to get the name string
384

385             if (pattern.length() > 2)
386                 m_matchPart = pattern.substring(0, pattern.length() - 2);
387             else
388                 m_matchPart = "";
389
390             // If matching is case insensitive then normalize the string
391

392             if (isCaseSensitive() == false)
393                 m_matchPart = m_matchPart.toUpperCase();
394
395             // If the file name contains wildcards we will need to use a regular expression
396

397             if (containsWildcards(m_matchPart) == false)
398             {
399                 setType(WILDCARD_EXT);
400                 return;
401             }
402         }
403
404         // Save the complex wildcard pattern as a char array for later pattern matching
405

406         if (isCaseSensitive() == false)
407             m_patternChars = m_pattern.toUpperCase().toCharArray();
408         else
409             m_patternChars = m_pattern.toCharArray();
410
411         setType(WILDCARD_COMPLEX);
412     }
413
414     /**
415      * Set the wildcard type
416      *
417      * @param typ int
418      */

419     private final void setType(int typ)
420     {
421         m_type = typ;
422     }
423
424     /**
425      * Return the wildcard as a string
426      *
427      * @return String
428      */

429     public String JavaDoc toString()
430     {
431         StringBuffer JavaDoc str = new StringBuffer JavaDoc();
432         str.append("[");
433         str.append(getPattern());
434         str.append(",");
435         str.append(isType());
436         str.append(",");
437
438         if (m_matchPart != null)
439             str.append(m_matchPart);
440
441         if (isCaseSensitive())
442             str.append(",Case");
443         else
444             str.append(",NoCase");
445         str.append("]");
446
447         return str.toString();
448     }
449
450     /**
451      * Check if the string contains any wildcard characters.
452      *
453      * @return boolean
454      * @param str java.lang.String
455      */

456     public final static boolean containsWildcards(String JavaDoc str)
457     {
458
459         // Check the string for wildcard characters
460

461         if (str.indexOf(MULTICHAR_WILDCARD) != -1)
462             return true;
463
464         if (str.indexOf(SINGLECHAR_WILDCARD) != -1)
465             return true;
466
467         // No wildcards found in the string
468

469         return false;
470     }
471
472     /**
473      * Check if a string contains any of the Unicode wildcard characters
474      *
475      * @param str String
476      * @return boolean
477      */

478     public final static boolean containsUnicodeWildcard(String JavaDoc str)
479     {
480
481         // Check if the string contains any of the Unicode wildcards
482

483         if (str.indexOf(SINGLECHAR_UNICODE_WILDCARD) != -1 || str.indexOf(MULTICHAR_UNICODE_WILDCARD) != -1
484                 || str.indexOf(DOT_UNICODE_WILDCARD) != -1)
485             return true;
486         return false;
487     }
488
489     /**
490      * Convert the Unicode wildcard string to a standard DOS wildcard string
491      *
492      * @param str String
493      * @return String
494      */

495     public final static String JavaDoc convertUnicodeWildcardToDOS(String JavaDoc str)
496     {
497
498         // Create a buffer for the new wildcard string
499

500         StringBuffer JavaDoc newStr = new StringBuffer JavaDoc(str.length());
501
502         // Convert the Unicode wildcard string to a DOS wildcard string
503

504         for (int i = 0; i < str.length(); i++)
505         {
506
507             // Get the current character
508

509             char ch = str.charAt(i);
510
511             // Check for a Unicode wildcard character
512

513             if (ch == SINGLECHAR_UNICODE_WILDCARD)
514             {
515
516                 // Translate to the DOS single character wildcard character
517

518                 ch = SINGLECHAR_WILDCARD;
519             }
520             else if (ch == MULTICHAR_UNICODE_WILDCARD)
521             {
522
523                 // Check if the current character is followed by a '.', if so then translate to the
524
// DOS multi character
525
// wildcard
526

527                 if (i < (str.length() - 1) && str.charAt(i + 1) == '.')
528                     ch = MULTICHAR_WILDCARD;
529             }
530             else if (ch == DOT_UNICODE_WILDCARD)
531             {
532
533                 // Check if the current character is followed by a DOS single/multi character
534
// wildcard
535

536                 if (i < (str.length() - 1))
537                 {
538                     char nextCh = str.charAt(i + 1);
539                     if (nextCh == SINGLECHAR_WILDCARD || nextCh == MULTICHAR_WILDCARD
540                             || nextCh == SINGLECHAR_UNICODE_WILDCARD)
541                         ch = '.';
542                 }
543             }
544
545             // Append the character to the translated wildcard string
546

547             newStr.append(ch);
548         }
549
550         // Return the translated wildcard string
551

552         return newStr.toString();
553     }
554
555     /**
556      * Convert a wildcard string to a regular expression
557      *
558      * @param path String
559      * @return String
560      */

561     public final static String JavaDoc convertToRegexp(String JavaDoc path)
562     {
563
564         // Convert the path to characters, check if the wildcard string ends with a single character
565
// wildcard
566

567         char[] smbPattern = path.toCharArray();
568         boolean endsWithQ = smbPattern[smbPattern.length - 1] == '?';
569
570         // Build up the regular expression
571

572         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
573         sb.append('^');
574
575         for (int i = 0; i < smbPattern.length; i++)
576         {
577
578             // Process the current character
579

580             switch (smbPattern[i])
581             {
582
583             // Multi character wildcard
584

585             case '*':
586                 sb.append(".*");
587                 break;
588
589             // Single character wildcard
590

591             case '?':
592                 if (endsWithQ)
593                 {
594                     boolean restQ = true;
595                     for (int j = i + 1; j < smbPattern.length; j++)
596                     {
597                         if (smbPattern[j] != '?')
598                         {
599                             restQ = false;
600                             break;
601                         }
602                     }
603                     if (restQ)
604                         sb.append(".?");
605                     else
606                         sb.append('.');
607                 }
608                 else
609                     sb.append('.');
610                 break;
611
612             // Escape regular expression special characters
613

614             case '.':
615             case '+':
616             case '\\':
617             case '[':
618             case ']':
619             case '^':
620             case '$':
621             case '(':
622             case ')':
623                 sb.append('\\');
624                 sb.append(smbPattern[i]);
625                 break;
626
627             // Normal characters, just pass through
628

629             default:
630                 sb.append(smbPattern[i]);
631                 break;
632             }
633         }
634         sb.append('$');
635
636         // Return the regular expression string
637

638         return sb.toString();
639     }
640 }
Popular Tags