1 11 package org.eclipse.ui.dialogs; 12 13 import org.eclipse.ui.internal.misc.StringMatcher; 14 15 26 public class SearchPattern { 27 28 34 public static final int RULE_EXACT_MATCH = 0; 35 36 39 public static final int RULE_PREFIX_MATCH = 0x0001; 40 41 47 public static final int RULE_PATTERN_MATCH = 0x0002; 48 49 54 public static final int RULE_CASE_SENSITIVE = 0x0008; 55 56 59 public static final int RULE_BLANK_MATCH = 0x0020; 60 61 87 public static final int RULE_CAMELCASE_MATCH = 0x0080; 88 89 private int matchRule; 90 91 private String stringPattern; 92 93 private String initialPattern; 94 95 private StringMatcher stringMatcher; 96 97 private static final char END_SYMBOL = '<'; 98 99 private static final char ANY_STRING = '*'; 100 101 private static final char BLANK = ' '; 102 103 private int allowedRules; 104 105 111 public SearchPattern() { 112 this(RULE_EXACT_MATCH | RULE_PREFIX_MATCH | RULE_PATTERN_MATCH 113 | RULE_CAMELCASE_MATCH | RULE_BLANK_MATCH); 114 } 115 116 135 public SearchPattern(int allowedRules) { 136 this.allowedRules = allowedRules; 137 } 138 139 144 public String getPattern() { 145 return this.stringPattern; 146 } 147 148 152 public void setPattern(String stringPattern) { 153 this.initialPattern = stringPattern; 154 this.stringPattern = stringPattern; 155 initializePatternAndMatchRule(stringPattern); 156 matchRule = matchRule & this.allowedRules; 157 if (matchRule == RULE_PATTERN_MATCH) { 158 stringMatcher = new StringMatcher(this.stringPattern, true, false); 159 } 160 } 161 162 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 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 303 private boolean camelCaseMatch(String pattern, String name) { 304 if (pattern == null) 305 return true; if (name == null) 307 return false; 309 return camelCaseMatch(pattern, 0, pattern.length(), name, 0, name 310 .length()); 311 } 312 313 419 private boolean camelCaseMatch(String pattern, int patternStart, 420 int patternEnd, String name, int nameStart, int nameEnd) { 421 if (name == null) 422 return false; if (pattern == null) 424 return true; 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 if (name.charAt(nameStart) != pattern.charAt(patternStart)) { 436 return false; 438 } 439 440 int patternLength = patternEnd; 441 442 if (pattern.charAt(patternEnd - 1) == END_SYMBOL || pattern.charAt(patternEnd - 1) == BLANK ) 443 patternLength = patternEnd - 1; 444 445 446 char patternChar, nameChar; 447 int iPattern = patternStart; 448 int iName = nameStart; 449 450 while (true) { 452 453 iPattern++; 454 iName++; 455 456 if (iPattern == patternEnd) { 457 return true; 459 } 460 461 if (iName == nameEnd) { 462 if (iPattern == patternLength) 463 return true; 464 return false; 466 } 467 468 if ((patternChar = pattern.charAt(iPattern)) == name.charAt(iName)) { 471 continue; 472 } 473 474 if (!isPatternCharAllowed(patternChar)) 477 return false; 478 479 while (true) { 482 if (iName == nameEnd) { 483 if ((iPattern == patternLength) && (patternChar == END_SYMBOL || patternChar == BLANK)) 484 return true; 485 return false; 486 } 487 488 nameChar = name.charAt(iName); 489 490 if ((iPattern == patternLength) && (patternChar == END_SYMBOL || patternChar == BLANK)) { 491 if (isNameCharAllowed(nameChar)) { 492 return false; 493 } 494 iName++; 495 continue; 496 } 497 498 if (!isNameCharAllowed(nameChar)) { 499 iName++; 501 } else if (patternChar != nameChar) { 503 return false; 505 } else { 506 break; 508 } 509 } 510 } 514 } 515 516 523 protected boolean isPatternCharAllowed(char patternChar) { 524 return Character.isUpperCase(patternChar) || patternChar == END_SYMBOL 525 || patternChar == BLANK; 526 } 527 528 536 protected boolean isNameCharAllowed(char nameChar) { 537 return Character.isUpperCase(nameChar); 538 } 539 540 551 public final int getMatchRule() { 552 return this.matchRule; 553 } 554 555 586 private int validateMatchRule(String stringPattern, int matchRule) { 587 588 int starIndex = stringPattern.indexOf('*'); 590 int questionIndex = stringPattern.indexOf('?'); 591 if (starIndex < 0 && questionIndex < 0) { 592 matchRule &= ~RULE_PATTERN_MATCH; 594 } else { 595 matchRule |= RULE_PATTERN_MATCH; 597 } 598 if ((matchRule & RULE_PATTERN_MATCH) != 0) { 599 matchRule &= ~RULE_CAMELCASE_MATCH; 601 matchRule &= ~RULE_PREFIX_MATCH; 602 } 603 604 if ((matchRule & RULE_CAMELCASE_MATCH) != 0) { 606 int length = stringPattern.length(); 608 boolean validCamelCase = true; 609 for (int i = 0; i < length && validCamelCase; i++) { 610 char ch = stringPattern.charAt(i); 611 validCamelCase = isValidCamelCaseChar(ch); 612 } 613 validCamelCase = validCamelCase && Character.isUpperCase(stringPattern.charAt(0)); 614 if (validCamelCase) { 616 if ((matchRule & RULE_PREFIX_MATCH) != 0) { 617 if ((matchRule & RULE_CASE_SENSITIVE) != 0) { 618 matchRule &= ~RULE_PREFIX_MATCH; 620 matchRule &= ~RULE_CASE_SENSITIVE; 621 } 622 } 623 } else { 624 matchRule &= ~RULE_CAMELCASE_MATCH; 625 if ((matchRule & RULE_PREFIX_MATCH) == 0) { 626 matchRule |= RULE_PREFIX_MATCH; 627 matchRule |= RULE_CASE_SENSITIVE; 628 } 629 } 630 } 631 return matchRule; 632 } 633 634 641 protected boolean isValidCamelCaseChar(char ch) { 642 return true; 643 } 644 645 652 public boolean equalsPattern(SearchPattern pattern) { 653 return trimWildcardCharacters(pattern.initialPattern).equals( 654 trimWildcardCharacters(this.initialPattern)); 655 } 656 657 665 public boolean isSubPattern(SearchPattern pattern) { 666 return trimWildcardCharacters(pattern.initialPattern).startsWith( 667 trimWildcardCharacters(this.initialPattern)); 668 } 669 670 677 private String trimWildcardCharacters(String pattern) { 678 return pattern.replaceAll("\\*+", "\\*"); } 680 681 } 682 | Popular Tags |