Source Code Cross Referenced for SearchPattern.java in  » IDE-Eclipse » ui-workbench » org » eclipse » ui » dialogs » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE Eclipse » ui workbench » org.eclipse.ui.dialogs 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*******************************************************************************
002:         * Copyright (c) 2000, 2007 IBM Corporation and others.
003:         * All rights reserved. This program and the accompanying materials
004:         * are made available under the terms of the Eclipse Public License v1.0
005:         * which accompanies this distribution, and is available at
006:         * http://www.eclipse.org/legal/epl-v10.html
007:         *
008:         * Contributors:
009:         *     IBM Corporation - initial API and implementation
010:         *******************************************************************************/package org.eclipse.ui.dialogs;
011:
012:        import org.eclipse.ui.internal.misc.StringMatcher;
013:
014:        /**
015:         * A search pattern defines how search results are found.
016:         * 
017:         * <p>
018:         * This class is intended to be subclassed by clients. A default behavior is
019:         * provided for each of the methods above, that clients can ovveride if they
020:         * wish.
021:         * </p>
022:         * 
023:         * @since 3.3
024:         */
025:        public class SearchPattern {
026:
027:            // Rules for pattern matching: (exact, prefix, pattern) [ | case sensitive]
028:            /**
029:             * Match rule: The search pattern matches exactly the search result, that
030:             * is, the source of the search result equals the search pattern. Search pattern
031:             * should start from lowerCase char.
032:             */
033:            public static final int RULE_EXACT_MATCH = 0;
034:
035:            /**
036:             * Match rule: The search pattern is a prefix of the search result.
037:             */
038:            public static final int RULE_PREFIX_MATCH = 0x0001;
039:
040:            /**
041:             * Match rule: The search pattern contains one or more wild cards ('*' or
042:             * '?'). A '*' wild-card can replace 0 or more characters in the search
043:             * result. A '?' wild-card replaces exactly 1 character in the search
044:             * result.
045:             */
046:            public static final int RULE_PATTERN_MATCH = 0x0002;
047:
048:            /**
049:             * Match rule: The search pattern matches the search result only if cases
050:             * are the same. Can be combined to previous rules, e.g.
051:             * {@link #RULE_EXACT_MATCH} | {@link #RULE_CASE_SENSITIVE}
052:             */
053:            public static final int RULE_CASE_SENSITIVE = 0x0008;
054:
055:            /**
056:             * Match rule: The search pattern is blank.
057:             */
058:            public static final int RULE_BLANK_MATCH = 0x0020;
059:
060:            /**
061:             * Match rule: The search pattern contains a Camel Case expression. <br>
062:             * Examples:
063:             * <ul>
064:             * <li><code>NPE</code> type string pattern will match
065:             * <code>NullPointerException</code> and
066:             * <code>NpPermissionException</code> types,</li>
067:             * <li><code>NuPoEx</code> type string pattern will only match
068:             * <code>NullPointerException</code> type.</li>
069:             * </ul>
070:             * 
071:             * 
072:             * <br>
073:             * Can be combined to {@link #RULE_PREFIX_MATCH} match rule. For example,
074:             * when prefix match rule is combined with Camel Case match rule,
075:             * <code>"nPE"</code> pattern will match <code>nPException</code>. <br>
076:             * Match rule {@link #RULE_PATTERN_MATCH} may also be combined but both
077:             * rules will not be used simultaneously as they are mutually exclusive.
078:             * Used match rule depends on whether string pattern contains specific
079:             * pattern characters (e.g. '*' or '?') or not. If it does, then only
080:             * Pattern match rule will be used, otherwise only Camel Case match will be
081:             * used. For example, with <code>"NPE"</code> string pattern, search will
082:             * only use Camel Case match rule, but with <code>N*P*E*</code> string
083:             * pattern, it will use only Pattern match rule.
084:             * 
085:             */
086:            public static final int RULE_CAMELCASE_MATCH = 0x0080;
087:
088:            private int matchRule;
089:
090:            private String stringPattern;
091:
092:            private String initialPattern;
093:
094:            private StringMatcher stringMatcher;
095:
096:            private static final char END_SYMBOL = '<';
097:
098:            private static final char ANY_STRING = '*';
099:
100:            private static final char BLANK = ' ';
101:
102:            private int allowedRules;
103:
104:            /**
105:             * Creates new instance of SearchPattern Default allowedRules for it is
106:             * result of belong logic operation: ( RULE_EXACT_MATCH | RULE_PREFIX_MATCH |
107:             * RULE_PATTERN_MATCH | RULE_CAMELCASE_MATCH )
108:             * 
109:             */
110:            public SearchPattern() {
111:                this (RULE_EXACT_MATCH | RULE_PREFIX_MATCH | RULE_PATTERN_MATCH
112:                        | RULE_CAMELCASE_MATCH | RULE_BLANK_MATCH);
113:            }
114:
115:            /**
116:             * Creates a search pattern with the rule to apply for matching index keys.
117:             * It can be exact match, prefix match, pattern match or camelCase match.
118:             * Rule can also be combined with a case sensitivity flag.
119:             * 
120:             * @param allowedRules
121:             *            one of {@link #RULE_EXACT_MATCH}, {@link #RULE_PREFIX_MATCH},
122:             *            {@link #RULE_PATTERN_MATCH}, {@link #RULE_CASE_SENSITIVE},
123:             *            {@link #RULE_CAMELCASE_MATCH} combined with one of following
124:             *            values: {@link #RULE_EXACT_MATCH}, {@link #RULE_PREFIX_MATCH},
125:             *            {@link #RULE_PATTERN_MATCH} or {@link #RULE_CAMELCASE_MATCH}.
126:             *            e.g. {@link #RULE_EXACT_MATCH} | {@link #RULE_CASE_SENSITIVE}
127:             *            if an exact and case sensitive match is requested,
128:             *            {@link #RULE_PREFIX_MATCH} if a prefix non case sensitive
129:             *            match is requested or {@link #RULE_EXACT_MATCH} if a non case
130:             *            sensitive and erasure match is requested.<br>
131:             *            Note also that default behavior for generic types/methods
132:             *            search is to find exact matches.
133:             */
134:            public SearchPattern(int allowedRules) {
135:                this .allowedRules = allowedRules;
136:            }
137:
138:            /**
139:             * Gets string pattern used by matcher
140:             * 
141:             * @return pattern
142:             */
143:            public String getPattern() {
144:                return this .stringPattern;
145:            }
146:
147:            /**
148:             * @param stringPattern
149:             *            The stringPattern to set.
150:             */
151:            public void setPattern(String stringPattern) {
152:                this .initialPattern = stringPattern;
153:                this .stringPattern = stringPattern;
154:                initializePatternAndMatchRule(stringPattern);
155:                matchRule = matchRule & this .allowedRules;
156:                if (matchRule == RULE_PATTERN_MATCH) {
157:                    stringMatcher = new StringMatcher(this .stringPattern, true,
158:                            false);
159:                }
160:            }
161:
162:            /**
163:             * Matches text with pattern. matching is determine by matchKind.
164:             * 
165:             * @param text
166:             * @return true if search pattern was matched with text false in other way
167:             */
168:            public boolean matches(String text) {
169:                switch (matchRule) {
170:                case RULE_BLANK_MATCH:
171:                    return true;
172:                case RULE_PATTERN_MATCH:
173:                    return stringMatcher.match(text);
174:                case RULE_EXACT_MATCH:
175:                    return stringPattern.equalsIgnoreCase(text);
176:                case RULE_CAMELCASE_MATCH:
177:                    if (camelCaseMatch(stringPattern, text)) {
178:                        return true;
179:                    }
180:                default:
181:                    return startsWithIgnoreCase(text, stringPattern);
182:                }
183:            }
184:
185:            private void initializePatternAndMatchRule(String pattern) {
186:                int length = pattern.length();
187:                if (length == 0) {
188:                    matchRule = RULE_BLANK_MATCH;
189:                    stringPattern = pattern;
190:                    return;
191:                }
192:                char last = pattern.charAt(length - 1);
193:
194:                if (pattern.indexOf('*') != -1 || pattern.indexOf('?') != -1) {
195:                    matchRule = RULE_PATTERN_MATCH;
196:                    switch (last) {
197:                    case END_SYMBOL:
198:                    case BLANK:
199:                        stringPattern = pattern.substring(0, length - 1);
200:                        break;
201:                    case ANY_STRING:
202:                        stringPattern = pattern;
203:                        break;
204:                    default:
205:                        stringPattern = pattern + ANY_STRING;
206:                    }
207:                    return;
208:                }
209:
210:                if (validateMatchRule(pattern, RULE_CAMELCASE_MATCH) == RULE_CAMELCASE_MATCH) {
211:                    matchRule = RULE_CAMELCASE_MATCH;
212:                    stringPattern = pattern;
213:                    return;
214:                }
215:
216:                if (last == END_SYMBOL || last == BLANK) {
217:                    matchRule = RULE_EXACT_MATCH;
218:                    stringPattern = pattern.substring(0, length - 1);
219:                    return;
220:                }
221:
222:                matchRule = RULE_PREFIX_MATCH;
223:                stringPattern = pattern;
224:
225:            }
226:
227:            /**
228:             * @param text
229:             * @param prefix
230:             * @return true if text starts with given prefix, ignoring case false in
231:             *         other way
232:             */
233:            private boolean startsWithIgnoreCase(String text, String prefix) {
234:                int textLength = text.length();
235:                int prefixLength = prefix.length();
236:                if (textLength < prefixLength)
237:                    return false;
238:                for (int i = prefixLength - 1; i >= 0; i--) {
239:                    if (Character.toLowerCase(prefix.charAt(i)) != Character
240:                            .toLowerCase(text.charAt(i)))
241:                        return false;
242:                }
243:                return true;
244:            }
245:
246:            /**
247:             * Answers true if the pattern matches the given name using CamelCase rules,
248:             * or false otherwise. CamelCase matching does NOT accept explicit
249:             * wild-cards '*' and '?' and is inherently case sensitive. <br>
250:             * CamelCase denotes the convention of writing compound names without
251:             * spaces, and capitalizing every term. This function recognizes both upper
252:             * and lower CamelCase, depending whether the leading character is
253:             * capitalized or not. The leading part of an upper CamelCase pattern is
254:             * assumed to contain a sequence of capitals which are appearing in the
255:             * matching name; e.g. 'NPE' will match 'NullPointerException', but not
256:             * 'NewPerfData'. A lower CamelCase pattern uses a lowercase first
257:             * character. In Java, type names follow the upper CamelCase convention,
258:             * whereas method or field names follow the lower CamelCase convention. <br>
259:             * The pattern may contain lowercase characters, which will be match in a
260:             * case sensitive way. These characters must appear in sequence in the name.
261:             * For instance, 'NPExcep' will match 'NullPointerException', but not
262:             * 'NullPointerExCEPTION' or 'NuPoEx' will match 'NullPointerException', but
263:             * not 'NoPointerException'. <br>
264:             * <br>
265:             * Examples:
266:             * <ol>
267:             * <li>
268:             * 
269:             * <pre>
270:             *                 pattern = &quot;NPE&quot;
271:             *                 name = NullPointerException / NoPermissionException
272:             *                 result =&gt; true
273:             * </pre>
274:             * 
275:             * </li>
276:             * <li>
277:             * 
278:             * <pre>
279:             *                 pattern = &quot;NuPoEx&quot;
280:             *                 name = NullPointerException
281:             *                 result =&gt; true
282:             * </pre>
283:             * 
284:             * </li>
285:             * <li>
286:             * 
287:             * <pre>
288:             *                 pattern = &quot;npe&quot;
289:             *                 name = NullPointerException
290:             *                 result =&gt; false
291:             * </pre>
292:             * 
293:             * </li>
294:             * </ol>
295:             * 
296:             * @param pattern
297:             *            the given pattern
298:             * @param name
299:             *            the given name
300:             * @return true if the pattern matches the given name, false otherwise
301:             * 
302:             */
303:            private boolean camelCaseMatch(String pattern, String name) {
304:                if (pattern == null)
305:                    return true; // null pattern is equivalent to '*'
306:                if (name == null)
307:                    return false; // null name cannot match
308:
309:                return camelCaseMatch(pattern, 0, pattern.length(), name, 0,
310:                        name.length());
311:            }
312:
313:            /**
314:             * Answers true if a sub-pattern matches the subpart of the given name using
315:             * CamelCase rules, or false otherwise. CamelCase matching does NOT accept
316:             * explicit wild-cards '*' and '?' and is inherently case sensitive. Can
317:             * match only subset of name/pattern, considering end positions as
318:             * non-inclusive. The subpattern is defined by the patternStart and
319:             * patternEnd positions. <br>
320:             * CamelCase denotes the convention of writing compound names without
321:             * spaces, and capitalizing every term. This function recognizes both upper
322:             * and lower CamelCase, depending whether the leading character is
323:             * capitalized or not. The leading part of an upper CamelCase pattern is
324:             * assumed to contain a sequence of capitals which are appearing in the
325:             * matching name; e.g. 'NPE' will match 'NullPointerException', but not
326:             * 'NewPerfData'. A lower CamelCase pattern uses a lowercase first
327:             * character. In Java, type names follow the upper CamelCase convention,
328:             * whereas method or field names follow the lower CamelCase convention. <br>
329:             * The pattern may contain lowercase characters, which will be match in a
330:             * case sensitive way. These characters must appear in sequence in the name.
331:             * For instance, 'NPExcep' will match 'NullPointerException', but not
332:             * 'NullPointerExCEPTION' or 'NuPoEx' will match 'NullPointerException', but
333:             * not 'NoPointerException'. <br>
334:             * <br>
335:             * Examples:
336:             * <ol>
337:             * <li>
338:             * 
339:             * <pre>
340:             *                 pattern = &quot;NPE&quot;
341:             *                 patternStart = 0
342:             *                 patternEnd = 3
343:             *                 name = NullPointerException
344:             *                 nameStart = 0
345:             *                 nameEnd = 20
346:             *                 result =&gt; true
347:             * </pre>
348:             * 
349:             * </li>
350:             * <li>
351:             * 
352:             * <pre>
353:             *                 pattern = &quot;NPE&quot;
354:             *                 patternStart = 0
355:             *                 patternEnd = 3
356:             *                 name = NoPermissionException
357:             *                 nameStart = 0
358:             *                 nameEnd = 21
359:             *                 result =&gt; true
360:             * </pre>
361:             * 
362:             * </li>
363:             * <li>
364:             * 
365:             * <pre>
366:             *                 pattern = &quot;NuPoEx&quot;
367:             *                 patternStart = 0
368:             *                 patternEnd = 6
369:             *                 name = NullPointerException
370:             *                 nameStart = 0
371:             *                 nameEnd = 20
372:             *                 result =&gt; true
373:             * </pre>
374:             * 
375:             * </li>
376:             * <li>
377:             * 
378:             * <pre>
379:             *                 pattern = &quot;NuPoEx&quot;
380:             *                 patternStart = 0
381:             *                 patternEnd = 6
382:             *                 name = NoPermissionException
383:             *                 nameStart = 0
384:             *                 nameEnd = 21
385:             *                 result =&gt; false
386:             * </pre>
387:             * 
388:             * </li>
389:             * <li>
390:             * 
391:             * <pre>
392:             *                 pattern = &quot;npe&quot;
393:             *                 patternStart = 0
394:             *                 patternEnd = 3
395:             *                 name = NullPointerException
396:             *                 nameStart = 0
397:             *                 nameEnd = 20
398:             *                 result =&gt; false
399:             * </pre>
400:             * 
401:             * </li>
402:             * </ol>
403:             * 
404:             * @param pattern
405:             *            the given pattern
406:             * @param patternStart
407:             *            the start index of the pattern, inclusive
408:             * @param patternEnd
409:             *            the end index of the pattern, exclusive
410:             * @param name
411:             *            the given name
412:             * @param nameStart
413:             *            the start index of the name, inclusive
414:             * @param nameEnd
415:             *            the end index of the name, exclusive
416:             * @return true if a sub-pattern matches the subpart of the given name,
417:             *         false otherwise
418:             */
419:            private boolean camelCaseMatch(String pattern, int patternStart,
420:                    int patternEnd, String name, int nameStart, int nameEnd) {
421:                if (name == null)
422:                    return false; // null name cannot match
423:                if (pattern == null)
424:                    return true; // null pattern is equivalent to '*'
425:                if (patternEnd < 0)
426:                    patternEnd = pattern.length();
427:                if (nameEnd < 0)
428:                    nameEnd = name.length();
429:
430:                if (patternEnd <= patternStart)
431:                    return nameEnd <= nameStart;
432:                if (nameEnd <= nameStart)
433:                    return false;
434:                // check first pattern char
435:                if (name.charAt(nameStart) != pattern.charAt(patternStart)) {
436:                    // first char must strictly match (upper/lower)
437:                    return false;
438:                }
439:
440:                int patternLength = patternEnd;
441:
442:                if (pattern.charAt(patternEnd - 1) == END_SYMBOL
443:                        || pattern.charAt(patternEnd - 1) == BLANK)
444:                    patternLength = patternEnd - 1;
445:
446:                char patternChar, nameChar;
447:                int iPattern = patternStart;
448:                int iName = nameStart;
449:
450:                // Main loop is on pattern characters
451:                while (true) {
452:
453:                    iPattern++;
454:                    iName++;
455:
456:                    if (iPattern == patternEnd) {
457:                        // We have exhausted pattern, so it's a match
458:                        return true;
459:                    }
460:
461:                    if (iName == nameEnd) {
462:                        if (iPattern == patternLength)
463:                            return true;
464:                        // We have exhausted name (and not pattern), so it's not a match
465:                        return false;
466:                    }
467:
468:                    // For as long as we're exactly matching, bring it on (even if it's
469:                    // a lower case character)
470:                    if ((patternChar = pattern.charAt(iPattern)) == name
471:                            .charAt(iName)) {
472:                        continue;
473:                    }
474:
475:                    // If characters are not equals, then it's not a match if
476:                    // patternChar is lowercase
477:                    if (!isPatternCharAllowed(patternChar))
478:                        return false;
479:
480:                    // patternChar is uppercase, so let's find the next uppercase in
481:                    // name
482:                    while (true) {
483:                        if (iName == nameEnd) {
484:                            if ((iPattern == patternLength)
485:                                    && (patternChar == END_SYMBOL || patternChar == BLANK))
486:                                return true;
487:                            return false;
488:                        }
489:
490:                        nameChar = name.charAt(iName);
491:
492:                        if ((iPattern == patternLength)
493:                                && (patternChar == END_SYMBOL || patternChar == BLANK)) {
494:                            if (isNameCharAllowed(nameChar)) {
495:                                return false;
496:                            }
497:                            iName++;
498:                            continue;
499:                        }
500:
501:                        if (!isNameCharAllowed(nameChar)) {
502:                            // nameChar is lowercase
503:                            iName++;
504:                            // nameChar is uppercase...
505:                        } else if (patternChar != nameChar) {
506:                            // .. and it does not match patternChar, so it's not a match
507:                            return false;
508:                        } else {
509:                            // .. and it matched patternChar. Back to the big loop
510:                            break;
511:                        }
512:                    }
513:                    // At this point, either name has been exhausted, or it is at an
514:                    // uppercase letter.
515:                    // Since pattern is also at an uppercase letter
516:                }
517:            }
518:
519:            /**
520:             * Checks pattern's character is allowed for specified set. It could be
521:             * override if you want change logic of camelCaseMatch methods.
522:             * 
523:             * @param patternChar
524:             * @return true if patternChar is in set of allowed characters for pattern
525:             */
526:            protected boolean isPatternCharAllowed(char patternChar) {
527:                return Character.isUpperCase(patternChar)
528:                        || patternChar == END_SYMBOL || patternChar == BLANK;
529:            }
530:
531:            /**
532:             * Checks character of element's name is allowed for specified set. It could
533:             * be override if you want change logic of camelCaseMatch methods.
534:             * 
535:             * @param nameChar -
536:             *            name of searched element
537:             * @return if nameChar is in set of allowed characters for name of element
538:             */
539:            protected boolean isNameCharAllowed(char nameChar) {
540:                return Character.isUpperCase(nameChar);
541:            }
542:
543:            /**
544:             * Returns the rule to apply for matching keys. Can be exact match, prefix
545:             * match, pattern match or camelcase match. Rule can also be combined with a
546:             * case sensitivity flag.
547:             * 
548:             * @return one of RULE_EXACT_MATCH, RULE_PREFIX_MATCH, RULE_PATTERN_MATCH,
549:             *         RULE_CAMELCASE_MATCH, combined with RULE_CASE_SENSITIVE, e.g.
550:             *         RULE_EXACT_MATCH | RULE_CASE_SENSITIVE if an exact and case
551:             *         sensitive match is requested, or RULE_PREFIX_MATCH if a prefix
552:             *         non case sensitive match is requested.
553:             */
554:            public final int getMatchRule() {
555:                return this .matchRule;
556:            }
557:
558:            /**
559:             * Validate compatibility between given string pattern and match rule. <br>
560:             * Optimized (ie. returned match rule is modified) combinations are:
561:             * <ul>
562:             * <li>{@link #RULE_PATTERN_MATCH} without any '*' or '?' in string
563:             * pattern: pattern match bit is unset, </li>
564:             * <li>{@link #RULE_PATTERN_MATCH} and {@link #RULE_PREFIX_MATCH} bits
565:             * simultaneously set: prefix match bit is unset, </li>
566:             * <li>{@link #RULE_PATTERN_MATCH} and {@link #RULE_CAMELCASE_MATCH} bits
567:             * simultaneously set: camel case match bit is unset, </li>
568:             * <li>{@link #RULE_CAMELCASE_MATCH} with invalid combination of uppercase
569:             * and lowercase characters: camel case match bit is unset and replaced with
570:             * prefix match pattern, </li>
571:             * <li>{@link #RULE_CAMELCASE_MATCH} combined with
572:             * {@link #RULE_PREFIX_MATCH} and {@link #RULE_CASE_SENSITIVE} bits is
573:             * reduced to only {@link #RULE_CAMELCASE_MATCH} as Camel Case search is
574:             * already prefix and case sensitive, </li>
575:             * </ul>
576:             * <br>
577:             * Rejected (ie. returned match rule -1) combinations are:
578:             * <ul>
579:             * <li>{@link #RULE_REGEXP_MATCH} with any other match mode bit set, </li>
580:             * </ul>
581:             * 
582:             * @param stringPattern
583:             *            The string pattern
584:             * @param matchRule
585:             *            The match rule
586:             * @return Optimized valid match rule or -1 if an incompatibility was
587:             *         detected.
588:             */
589:            private int validateMatchRule(String stringPattern, int matchRule) {
590:
591:                // Verify Pattern match rule
592:                int starIndex = stringPattern.indexOf('*');
593:                int questionIndex = stringPattern.indexOf('?');
594:                if (starIndex < 0 && questionIndex < 0) {
595:                    // reset pattern match bit if any
596:                    matchRule &= ~RULE_PATTERN_MATCH;
597:                } else {
598:                    // force Pattern rule
599:                    matchRule |= RULE_PATTERN_MATCH;
600:                }
601:                if ((matchRule & RULE_PATTERN_MATCH) != 0) {
602:                    // remove Camel Case and Prefix match bits if any
603:                    matchRule &= ~RULE_CAMELCASE_MATCH;
604:                    matchRule &= ~RULE_PREFIX_MATCH;
605:                }
606:
607:                // Verify Camel Case match rule
608:                if ((matchRule & RULE_CAMELCASE_MATCH) != 0) {
609:                    // Verify sting pattern validity
610:                    int length = stringPattern.length();
611:                    boolean validCamelCase = true;
612:                    for (int i = 0; i < length && validCamelCase; i++) {
613:                        char ch = stringPattern.charAt(i);
614:                        validCamelCase = isValidCamelCaseChar(ch);
615:                    }
616:                    validCamelCase = validCamelCase
617:                            && Character.isUpperCase(stringPattern.charAt(0));
618:                    // Verify bits compatibility
619:                    if (validCamelCase) {
620:                        if ((matchRule & RULE_PREFIX_MATCH) != 0) {
621:                            if ((matchRule & RULE_CASE_SENSITIVE) != 0) {
622:                                // This is equivalent to Camel Case match rule
623:                                matchRule &= ~RULE_PREFIX_MATCH;
624:                                matchRule &= ~RULE_CASE_SENSITIVE;
625:                            }
626:                        }
627:                    } else {
628:                        matchRule &= ~RULE_CAMELCASE_MATCH;
629:                        if ((matchRule & RULE_PREFIX_MATCH) == 0) {
630:                            matchRule |= RULE_PREFIX_MATCH;
631:                            matchRule |= RULE_CASE_SENSITIVE;
632:                        }
633:                    }
634:                }
635:                return matchRule;
636:            }
637:
638:            /**
639:             * Check if character is valid camelCase character
640:             * 
641:             * @param ch
642:             *            character to be validated
643:             * @return true if character is valid
644:             */
645:            protected boolean isValidCamelCaseChar(char ch) {
646:                return true;
647:            }
648:
649:            /**
650:             * Tells whether the given <code>SearchPattern</code> equals this pattern.
651:             * 
652:             * @param pattern
653:             *            pattern to be checked
654:             * @return true if the given pattern equals this search pattern
655:             */
656:            public boolean equalsPattern(SearchPattern pattern) {
657:                return trimWildcardCharacters(pattern.initialPattern).equals(
658:                        trimWildcardCharacters(this .initialPattern));
659:            }
660:
661:            /**
662:             * Tells whether the given <code>SearchPattern</code> is a subpattern of
663:             * this pattern.
664:             * 
665:             * @param pattern
666:             *            pattern to be checked
667:             * @return true if the given pattern is a sub pattern of this search pattern
668:             */
669:            public boolean isSubPattern(SearchPattern pattern) {
670:                return trimWildcardCharacters(pattern.initialPattern)
671:                        .startsWith(trimWildcardCharacters(this .initialPattern));
672:            }
673:
674:            /**
675:             * Trims sequences of '*' characters
676:             * 
677:             * @param pattern
678:             *            string to be trimmed
679:             * @return trimmed pattern
680:             */
681:            private String trimWildcardCharacters(String pattern) {
682:                return pattern.replaceAll("\\*+", "\\*"); //$NON-NLS-1$ //$NON-NLS-2$		}
683:            }
684:
685:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.