| //------------------------------------------------------------------------------ |
| // Copyright (c) 2005, 2006 IBM Corporation and others. |
| // All rights reserved. This program and the accompanying materials |
| // are made available under the terms of the Eclipse Public License v1.0 |
| // which accompanies this distribution, and is available at |
| // http://www.eclipse.org/legal/epl-v10.html |
| // |
| // Contributors: |
| // IBM Corporation - initial implementation |
| //------------------------------------------------------------------------------ |
| package org.eclipse.epf.persistence.util; |
| |
| import java.util.regex.Pattern; |
| import java.util.regex.PatternSyntaxException; |
| |
| /** |
| * Utility class with static methods to create search pattern |
| * |
| * @author Phong Nguyen Le |
| * @since 1.0 |
| */ |
| public class PatternConstructor { |
| |
| private PatternConstructor() { |
| // don't instantiate |
| } |
| |
| public static Pattern createPattern(String pattern, |
| boolean isCaseSensitive, boolean isRegex) |
| throws PatternSyntaxException { |
| return createPattern(pattern, isRegex, true, isCaseSensitive, false); |
| } |
| |
| /** |
| * Creates a pattern element from the pattern string which is either a |
| * reg-ex expression or in our old 'StringMatcher' format. |
| * |
| * @param pattern |
| * The search pattern |
| * @param isRegex |
| * <code>true</code> if the passed string already is a reg-ex |
| * pattern |
| * @param isStringMatcher |
| * <code>true</code> if the passed string is in the |
| * StringMatcher format. |
| * @param isCaseSensitive |
| * Set to <code>true</code> to create a case insensitive |
| * pattern |
| * @param isWholeWord |
| * <code>true</code> to create a pattern that requires a word |
| * boundary at the beginning and the end. |
| * @return The created pattern |
| * @throws PatternSyntaxException |
| */ |
| public static Pattern createPattern(String pattern, boolean isRegex, |
| boolean isStringMatcher, boolean isCaseSensitive, |
| boolean isWholeWord) throws PatternSyntaxException { |
| if (isRegex) { |
| if (isWholeWord) { |
| StringBuffer buffer = new StringBuffer(pattern.length() + 10); |
| buffer.append("\\b(?:").append(pattern).append(")\\b"); //$NON-NLS-1$ //$NON-NLS-2$ |
| pattern = buffer.toString(); |
| } |
| } else { |
| int len = pattern.length(); |
| StringBuffer buffer = new StringBuffer(len + 10); |
| // don't add a word boundary if the search text does not start with |
| // a word char. (this works around a user input error). |
| if (isWholeWord && len > 0 && isWordChar(pattern.charAt(0))) { |
| buffer.append("\\b"); //$NON-NLS-1$ |
| } |
| appendAsRegEx(isStringMatcher, pattern, buffer); |
| if (isWholeWord && len > 0 && isWordChar(pattern.charAt(len - 1))) { |
| buffer.append("\\b"); //$NON-NLS-1$ |
| } |
| pattern = buffer.toString(); |
| } |
| |
| int regexOptions = Pattern.MULTILINE; |
| if (!isCaseSensitive) { |
| regexOptions |= Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE; |
| } |
| return Pattern.compile(pattern, regexOptions); |
| } |
| |
| private static boolean isWordChar(char c) { |
| return Character.isLetterOrDigit(c); |
| } |
| |
| /** |
| * Creates a pattern element from an array of patterns in the old |
| * 'StringMatcher' format. |
| * |
| * @param patterns |
| * The search patterns |
| * @param isCaseSensitive |
| * Set to <code>true</code> to create a case insensitive |
| * pattern |
| * @return The created pattern |
| * @throws PatternSyntaxException |
| */ |
| public static Pattern createPattern(String[] patterns, |
| boolean isCaseSensitive) throws PatternSyntaxException { |
| StringBuffer pattern = new StringBuffer(); |
| for (int i = 0; i < patterns.length; i++) { |
| if (i > 0) { |
| // note that this works only as we know that the operands of the |
| // or expression will be simple and need no brackets. |
| pattern.append('|'); |
| } |
| appendAsRegEx(true, patterns[i], pattern); |
| } |
| return createPattern(pattern.toString(), true, true, isCaseSensitive, |
| false); |
| } |
| |
| public static StringBuffer appendAsRegEx(boolean isStringMatcher, |
| String pattern, StringBuffer buffer) { |
| boolean isEscaped = false; |
| for (int i = 0; i < pattern.length(); i++) { |
| char c = pattern.charAt(i); |
| switch (c) { |
| // the backslash |
| case '\\': |
| // the backslash is escape char in string matcher |
| if (isStringMatcher && !isEscaped) { |
| isEscaped = true; |
| } else { |
| buffer.append("\\\\"); //$NON-NLS-1$ |
| isEscaped = false; |
| } |
| break; |
| // characters that need to be escaped in the regex. |
| case '(': |
| case ')': |
| case '{': |
| case '}': |
| case '.': |
| case '[': |
| case ']': |
| case '$': |
| case '^': |
| case '+': |
| case '|': |
| if (isEscaped) { |
| buffer.append("\\\\"); //$NON-NLS-1$ |
| isEscaped = false; |
| } |
| buffer.append('\\'); |
| buffer.append(c); |
| break; |
| case '?': |
| if (isStringMatcher && !isEscaped) { |
| buffer.append('.'); |
| } else { |
| buffer.append('\\'); |
| buffer.append(c); |
| isEscaped = false; |
| } |
| break; |
| case '*': |
| if (isStringMatcher && !isEscaped) { |
| buffer.append(".*"); //$NON-NLS-1$ |
| } else { |
| buffer.append('\\'); |
| buffer.append(c); |
| isEscaped = false; |
| } |
| break; |
| default: |
| if (isEscaped) { |
| buffer.append("\\\\"); //$NON-NLS-1$ |
| isEscaped = false; |
| } |
| buffer.append(c); |
| break; |
| } |
| } |
| if (isEscaped) { |
| buffer.append("\\\\"); //$NON-NLS-1$ |
| isEscaped = false; |
| } |
| return buffer; |
| } |
| |
| } |