1 24 25 package com.mckoi.database; 26 27 import com.mckoi.database.global.Types; 28 import com.mckoi.util.IntegerVector; 29 import com.mckoi.util.BlockIntegerList; 30 import com.mckoi.util.IntegerIterator; 31 32 33 54 55 public final class PatternSearch { 56 57 60 private final static char ZERO_OR_MORE_CHARS = '%'; 61 private final static char ONE_CHAR = '_'; 62 63 64 public static boolean testSearch(String pattern, String expression, 65 boolean result) { 66 System.out.print("Pattern: "); 67 System.out.println("'" + pattern + "'"); 68 System.out.print("Expression: "); 69 System.out.println("'" + expression + "'"); 70 71 boolean tested_as = fullPatternMatch(pattern, expression, '\\'); 72 System.out.print("Result: "); 73 System.out.print(tested_as); 74 if (tested_as != result) { 75 System.out.println(" *** FAILED, Expected: " + result + " ***"); 76 } 77 else { 78 System.out.println(); 79 } 80 return tested_as; 81 } 82 83 public static void main(String [] args) { 84 testSearch("", "abc", false); 86 testSearch("%", "abc", true); 87 testSearch("a%", "abc", true); 88 testSearch("ab%", "abc", true); 89 testSearch("abc%", "abc", true); 90 testSearch("abcd%", "abc", false); 91 testSearch("abcd", "abc", false); 92 testSearch("abc", "abc", true); 93 testSearch("ab", "abc", false); 94 testSearch("a", "abc", false); 95 testSearch("a_", "abc", false); 96 testSearch("ab_", "abc", true); 97 testSearch("abc_", "abc", false); 98 testSearch("a_c", "abc", true); 99 testSearch("a%bc", "abc", true); 100 testSearch("a%c", "abc", true); 101 testSearch("%c", "abc", true); 102 testSearch("a_bc", "abc", false); 103 testSearch("__c", "abc", true); 104 testSearch("a__", "abc", true); 105 106 testSearch("a\\_\\_", "a__", true); 107 testSearch("a\\__", "a__", true); 108 testSearch("a\\__", "a_b", true); 109 testSearch("\\___", "_ab", true); 110 testSearch("\\_\\__", "_ab", false); 111 testSearch("\\_\\__", "__b", true); 112 113 testSearch("\\%ab", "%ab", true); 114 testSearch("ab\\%", "ab%", true); 115 testSearch("cab\\%", "cab", false); 116 testSearch("cab%", "cab", true); 117 118 } 119 120 121 124 private static boolean isWildCard(char ch) { 125 return (ch == ONE_CHAR || ch == ZERO_OR_MORE_CHARS); 126 } 127 128 133 public static boolean fullPatternMatch(String pattern, final String str, 134 char escape_char) { 135 StringBuffer start = new StringBuffer (); 136 String rezt = null; 137 int len = pattern.length(); 138 int i = 0; 139 boolean last_escape_char = false; 140 for (; i < len && rezt == null; ++i) { 141 char c = pattern.charAt(i); 142 if (last_escape_char) { 143 last_escape_char = false; 144 start.append(c); 145 } 146 else if (c == escape_char) { 147 last_escape_char = true; 148 } 149 else if (isWildCard(c)) { 150 rezt = pattern.substring(i); 151 } 152 else { 153 start.append(c); 154 } 155 } 156 157 if (rezt == null) { 158 rezt = ""; 159 } 160 161 String st = new String (start); 162 163 167 if (str.startsWith(st)) { 168 String str_rezt = str.substring(st.length()); 170 if (rezt.length() > 0) { 171 return patternMatch(rezt, str_rezt, escape_char); 172 } 173 else { 174 return str_rezt.length() == 0; 175 } 176 } 177 else { 178 return false; 179 } 180 181 } 182 183 202 public static boolean patternMatch(String pattern, String expression, 203 char escape_char) { 204 205 208 if (pattern.charAt(0) == ONE_CHAR) { 209 210 214 int i = 1; 215 boolean finished = (i >= pattern.length() || expression.length() < 1); 216 boolean last_was_escape = false; 217 int checked = 0; 218 while (!finished) { 219 char c = pattern.charAt(i); 220 if (!last_was_escape && c == escape_char) { 221 last_was_escape = true; 222 if (i >= expression.length()) { 223 return false; 224 } 225 ++i; 226 } 227 else if (last_was_escape || !isWildCard(c)) { 228 last_was_escape = false; 229 if (i >= expression.length() || c != expression.charAt(i)) { 232 return false; 233 } 234 ++i; 235 ++checked; 236 } 237 else { 238 return patternMatch(pattern.substring(i), expression.substring(i), 240 escape_char); 241 } 242 243 finished = (i >= pattern.length()); 244 } 245 246 int real_pattern_length = 0; 248 int sz = pattern.length(); 249 for (int n = 0; n < sz; ++n) { 250 if (pattern.charAt(n) != escape_char) { 251 ++real_pattern_length; 252 } 253 else { 254 ++n; 255 } 256 } 257 258 261 return real_pattern_length == expression.length(); 262 263 } 264 265 267 271 if (pattern.length() == 1) { 272 return true; 273 } 274 275 278 StringBuffer next_string = new StringBuffer (); 279 int i = 1; 280 boolean finished = (i >= pattern.length()); 281 boolean last_was_escape = false; 282 while (!finished) { 283 char next_char = pattern.charAt(i); 284 if (!last_was_escape && next_char == escape_char) { 285 last_was_escape = true; 286 ++i; 287 if (i >= pattern.length()) { 288 finished = true; 289 } 290 } 291 else if (last_was_escape || !isWildCard(next_char)) { 292 last_was_escape = false; 293 next_string.append(next_char); 294 ++i; 295 if (i >= pattern.length()) { 296 finished = true; 297 } 298 } 299 else { 300 finished = true; 301 } 302 } 303 304 String find_string = new String (next_string); 305 306 311 if (i >= pattern.length()) { 312 return (expression.endsWith(find_string)); 313 } 314 315 319 int find_str_length = find_string.length(); 320 int str_index = expression.indexOf(find_string, 0); 321 322 while (str_index != -1) { 323 324 boolean matched = patternMatch( 325 pattern.substring(1 + find_str_length), 326 expression.substring(str_index + find_str_length), 327 escape_char); 328 329 if (matched) { 330 return true; 331 } 332 333 str_index = expression.indexOf(find_string, str_index + 1); 334 } 335 336 return false; 337 338 } 339 340 350 static IntegerVector search(Table table, int column, String pattern) { 351 return search(table, column, pattern, '\\'); 352 } 353 354 364 static IntegerVector search(Table table, int column, String pattern, 365 char escape_char) { 366 367 TType col_type = table.getDataTableDef().columnAt(column).getTType(); 369 370 if (!(col_type instanceof TStringType)) { 372 throw new Error ("Unable to perform a pattern search " + 373 "on a non-String type column."); 374 } 375 TStringType col_string_type = (TStringType) col_type; 376 377 379 383 StringBuffer pre_pattern = new StringBuffer (); 384 int i = 0; 385 boolean finished = i >= pattern.length(); 386 boolean last_is_escape = false; 387 388 while (!finished) { 389 char c = pattern.charAt(i); 390 if (last_is_escape) { 391 last_is_escape = true; 392 pre_pattern.append(c); 393 } 394 else if (c == escape_char) { 395 last_is_escape = true; 396 } 397 else if (!isWildCard(c)) { 398 pre_pattern.append(c); 399 400 ++i; 401 if (i >= pattern.length()) { 402 finished = true; 403 } 404 405 } 406 else { 407 finished = true; 408 } 409 } 410 411 String post_pattern; 413 414 IntegerVector search_case; 417 418 if (i >= pattern.length()) { 419 422 TObject cell = new TObject(col_type, pattern); 423 return table.selectRows(column, Operator.get("="), cell); 424 425 } 427 else if (pre_pattern.length() == 0 || 428 col_string_type.getLocale() != null) { 429 430 435 search_case = table.selectAll(column); 436 post_pattern = pattern; 437 438 } 439 else { 440 441 444 448 String lower_bounds = new String (pre_pattern); 449 int next_char = pre_pattern.charAt(i - 1) + 1; 450 pre_pattern.setCharAt(i - 1, (char) next_char); 451 String upper_bounds = new String (pre_pattern); 452 453 post_pattern = pattern.substring(i); 454 455 TObject cell_lower = new TObject(col_type, lower_bounds); 456 TObject cell_upper = new TObject(col_type, upper_bounds); 457 458 460 search_case = table.selectRows(column, cell_lower, cell_upper); 461 462 } 463 464 466 475 int pre_index = i; 476 477 484 BlockIntegerList i_list = new BlockIntegerList(search_case); 485 IntegerIterator iterator = i_list.iterator(0, i_list.size() - 1); 486 487 while (iterator.hasNext()) { 488 489 491 boolean pattern_matches = false; 492 TObject cell = table.getCellContents(column, iterator.next()); 493 if (!cell.isNull()) { 495 String expression = cell.getObject().toString(); 496 expression = expression.substring(pre_index); 499 pattern_matches = patternMatch(post_pattern, expression, escape_char); 500 } 501 if (!pattern_matches) { 502 iterator.remove(); 504 } 505 506 } 507 508 return new IntegerVector(i_list); 509 510 } 511 512 514 518 static boolean regexMatch(TransactionSystem system, 519 String pattern, String value) { 520 if (pattern.startsWith("/")) { 523 int end = pattern.lastIndexOf('/'); 524 String pat = pattern.substring(1, end); 525 String ops = pattern.substring(end + 1); 526 return system.getRegexLibrary().regexMatch(pat, ops, value); 527 } 528 else { 529 return system.getRegexLibrary().regexMatch(pattern, "", value); 531 } 532 } 533 534 539 static IntegerVector regexSearch(Table table, int column, String pattern) { 540 if (pattern.startsWith("/")) { 543 int end = pattern.lastIndexOf('/'); 544 String pat = pattern.substring(1, end); 545 String ops = pattern.substring(end + 1); 546 return table.getDatabase().getSystem().getRegexLibrary().regexSearch( 547 table, column, pat, ops); 548 } 549 else { 550 return table.getDatabase().getSystem().getRegexLibrary().regexSearch( 552 table, column, pattern, ""); 553 } 554 } 555 556 } 557 | Popular Tags |