X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.browsing.ui.common%2Fsrc%2Forg%2Fsimantics%2Fbrowsing%2Fui%2Fcommon%2Fviews%2FDefaultFilterStrategy.java;h=df5ddac53696a1c62f86fd91ed48c4bf915c74f0;hp=eeecfdc30dfbd4ee729913c557e6fa23e95f02a3;hb=0ae2b770234dfc3cbb18bd38f324125cf0faca07;hpb=24e2b34260f219f0d1644ca7a138894980e25b14 diff --git a/bundles/org.simantics.browsing.ui.common/src/org/simantics/browsing/ui/common/views/DefaultFilterStrategy.java b/bundles/org.simantics.browsing.ui.common/src/org/simantics/browsing/ui/common/views/DefaultFilterStrategy.java index eeecfdc30..df5ddac53 100644 --- a/bundles/org.simantics.browsing.ui.common/src/org/simantics/browsing/ui/common/views/DefaultFilterStrategy.java +++ b/bundles/org.simantics.browsing.ui.common/src/org/simantics/browsing/ui/common/views/DefaultFilterStrategy.java @@ -1,247 +1,247 @@ -/******************************************************************************* - * Copyright (c) 2007, 2010 Association for Decentralized Information Management - * in Industry THTH ry. - * 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: - * VTT Technical Research Centre of Finland - initial API and implementation - *******************************************************************************/ -package org.simantics.browsing.ui.common.views; - -import java.nio.CharBuffer; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Default implementation of IFilterStrategy. - * - *

- * It implements simple search semantics with only the special wildcard - * characters '*' ( 0 to n any characters) and '?' (any one character) - * recognized. In order to allow the filter to pass arbitrary prefixes, the - * client has to give a '*' prefix in the filter string. On the contrary, the - * client does not have to specify a '*' in order to pass arbitrary suffixes - - * arbitrary suffixes are allowed by default by this strategy. - * - *

- * This strategy forces the filter string to lowercase. - * - * TODO: implement case-insensitiveness properly, not by forcing the search string into lower case. Also Fix FilterSelectionRequestQueryProcessor after doing this. - * - * @author Tuukka Lehtonen - */ -public class DefaultFilterStrategy implements IFilterStrategy { - - private static final boolean DEBUG = false; - - boolean implicitPreAsterisk = true; - - public DefaultFilterStrategy() { - this(true); - } - - public DefaultFilterStrategy(boolean implicitPreAsterisk) { - this.implicitPreAsterisk = implicitPreAsterisk; - } - - private static StringBuilder addSearchWord(StringBuilder sb, String pattern) { - if (DEBUG) - System.out.println("addSearchWord(" + pattern + ") to '" + sb.toString() + "'"); - - if (pattern == null || pattern.isEmpty()) - return sb; - if (sb.length() > 0) - sb.append('|'); - sb.append('('); - sb.append(pattern); - sb.append(')'); - return sb; - } - - private static String toString(CharBuffer cb) { - cb.limit(cb.position()); - cb.reset(); - if (DEBUG) - System.out.println("toString(" + cb + ")"); - String result = cb.toString(); - cb.limit(cb.capacity()); - return result; - } - - public static String toSinglePatternString(String filter, boolean implicitPreAsterisk) { - if (!filter.isEmpty()) { - // Force searching in lowercase. - filter = filter.toLowerCase(); - - // Construct a regular expression from the specified text. - String regExFilter = filter - .replace("\\", "\\\\") // \ -> \\ - .replace(".", "\\.") // . -> \. - .replace("*", ".*") // * -> Any 0..n characters - .replace("?", ".") // ? -> Any single character - .replace("+", "\\+") // + -> \+ - .replace("(", "\\(") // ( -> \( - .replace(")", "\\)") // ) -> \) - .replace("[", "\\[") // [ -> \[ - .replace("]", "\\]") // ] -> \] - .replace("{", "\\{") // { -> \{ - .replace("}", "\\}") // } -> \} - .replace("^", "\\^") // ^ -> \^ - .replace("$", "\\$") // $ -> \$ - .replace("|", ".*|") // $ -> \$ - //.replace("|", "\\|") // | -> \| - .replace("&&", "\\&&") // && -> \&& - ; - - if (implicitPreAsterisk) - if (!regExFilter.startsWith(".*")) - regExFilter = ".*" + regExFilter ; - if (!regExFilter.endsWith(".*")) - regExFilter += ".*" ; - - return regExFilter; - } - return null; - } - - public static String defaultToPatternString(String filter, boolean implicitPreAsterisk) { - if (filter.isEmpty()) - return null; - - CharBuffer buf = CharBuffer.allocate(filter.length()*2); - buf.mark(); - StringBuilder sb = new StringBuilder(filter.length()*2); - boolean inQuote = false; - int len = filter.length(); - for (int i = 0; i < len;) { - char ch = filter.charAt(i); - if (DEBUG) - System.out.println("char[" + i + "]: '" + ch + "'"); - - if (ch == '"') { - if (!inQuote) { - if (DEBUG) - System.out.println("begin quoted text"); - inQuote = true; - } else { - if (DEBUG) - System.out.println("end quoted text"); - inQuote = false; - addSearchWord(sb, toSinglePatternString( toString(buf), implicitPreAsterisk )); - } - ++i; - continue; - } else if (ch == '\\') { - // Next character is escaped, i.e. taken as is. - ++i; - if (i >= len) - // Unexpected end-of-string - break; - - ch = filter.charAt(i); - if (DEBUG) - System.out.println("append escaped character '" + ch + "'"); - - buf.append(ch); - ++i; - break; - } else if (ch == ' ') { - if (inQuote) { - if (DEBUG) - System.out.println("append char '" + ch + "'"); - buf.append(ch); - ++i; - } else { - if (buf.position() > 0) { - addSearchWord(sb, toSinglePatternString( toString(buf), implicitPreAsterisk )); - } - ++i; - } - } else { - if (DEBUG) - System.out.println("append char '" + ch + "'"); - buf.append(ch); - ++i; - } - } - if (buf.position() > 0) { - addSearchWord(sb, toSinglePatternString( toString(buf), implicitPreAsterisk )); - } - - //sb.append(".*"); - - return sb.toString(); - } - - @Override - public String toPatternString(String filter) { - return defaultToPatternString(filter, implicitPreAsterisk); - } - - public static Pattern compilePattern(String s) { - IFilterStrategy st = new DefaultFilterStrategy(true); - System.out.println("compilePattern(" + s + ")"); - String regex = st.toPatternString(s); - System.out.println(s + " -> " + regex); - Pattern p = Pattern.compile(regex); - return p; - } - - public static void test(String pattern, String... testStrings) { - Pattern p = compilePattern(pattern); - for (String test : testStrings) { - System.out.print("\ttesting '" + test + "'"); - Matcher m = p.matcher(test); - if (m.matches()) { - System.out.println(" - MATCHES"); - } else { - System.out.println(" - NO MATCH"); - } - } - } - - static String[] TEST = { - "foo bar baz biz boz", - "biz bar baz foo boz", - "foo", - "bar", - " foo bar ", - "quux", - " quux ", - " quux foo", - }; - - public static void main(String[] args) { - test("foo$"); - test("."); - test("*"); - test("?"); - test("+"); - test("^"); - test("&"); - test("&&"); - test("&&&"); - test("|"); - test("("); - test(")"); - test("["); - test("]"); - test("{"); - test("}"); - test("()"); - test("[]"); - test("{}"); - test("\\\\"); - test("\\"); - - test("foo bar", TEST); - test("\"foo bar\"", TEST); - test("\"foo bar\" quux", TEST); - test("*\"foo bar\" *quux", TEST); - test("\"*foo bar\" *quux", TEST); - } - -} +/******************************************************************************* + * Copyright (c) 2007, 2010 Association for Decentralized Information Management + * in Industry THTH ry. + * 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: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.browsing.ui.common.views; + +import java.nio.CharBuffer; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Default implementation of IFilterStrategy. + * + *

+ * It implements simple search semantics with only the special wildcard + * characters '*' ( 0 to n any characters) and '?' (any one character) + * recognized. In order to allow the filter to pass arbitrary prefixes, the + * client has to give a '*' prefix in the filter string. On the contrary, the + * client does not have to specify a '*' in order to pass arbitrary suffixes - + * arbitrary suffixes are allowed by default by this strategy. + * + *

+ * This strategy forces the filter string to lowercase. + * + * TODO: implement case-insensitiveness properly, not by forcing the search string into lower case. Also Fix FilterSelectionRequestQueryProcessor after doing this. + * + * @author Tuukka Lehtonen + */ +public class DefaultFilterStrategy implements IFilterStrategy { + + private static final boolean DEBUG = false; + + boolean implicitPreAsterisk = true; + + public DefaultFilterStrategy() { + this(true); + } + + public DefaultFilterStrategy(boolean implicitPreAsterisk) { + this.implicitPreAsterisk = implicitPreAsterisk; + } + + private static StringBuilder addSearchWord(StringBuilder sb, String pattern) { + if (DEBUG) + System.out.println("addSearchWord(" + pattern + ") to '" + sb.toString() + "'"); + + if (pattern == null || pattern.isEmpty()) + return sb; + if (sb.length() > 0) + sb.append('|'); + sb.append('('); + sb.append(pattern); + sb.append(')'); + return sb; + } + + private static String toString(CharBuffer cb) { + cb.limit(cb.position()); + cb.reset(); + if (DEBUG) + System.out.println("toString(" + cb + ")"); + String result = cb.toString(); + cb.limit(cb.capacity()); + return result; + } + + public static String toSinglePatternString(String filter, boolean implicitPreAsterisk) { + if (!filter.isEmpty()) { + // Force searching in lowercase. + filter = filter.toLowerCase(); + + // Construct a regular expression from the specified text. + String regExFilter = filter + .replace("\\", "\\\\") // \ -> \\ + .replace(".", "\\.") // . -> \. + .replace("*", ".*") // * -> Any 0..n characters + .replace("?", ".") // ? -> Any single character + .replace("+", "\\+") // + -> \+ + .replace("(", "\\(") // ( -> \( + .replace(")", "\\)") // ) -> \) + .replace("[", "\\[") // [ -> \[ + .replace("]", "\\]") // ] -> \] + .replace("{", "\\{") // { -> \{ + .replace("}", "\\}") // } -> \} + .replace("^", "\\^") // ^ -> \^ + .replace("$", "\\$") // $ -> \$ + .replace("|", ".*|") // $ -> \$ + //.replace("|", "\\|") // | -> \| + .replace("&&", "\\&&") // && -> \&& + ; + + if (implicitPreAsterisk) + if (!regExFilter.startsWith(".*")) + regExFilter = ".*" + regExFilter ; + if (!regExFilter.endsWith(".*")) + regExFilter += ".*" ; + + return regExFilter; + } + return null; + } + + public static String defaultToPatternString(String filter, boolean implicitPreAsterisk) { + if (filter.isEmpty()) + return null; + + CharBuffer buf = CharBuffer.allocate(filter.length()*2); + buf.mark(); + StringBuilder sb = new StringBuilder(filter.length()*2); + boolean inQuote = false; + int len = filter.length(); + for (int i = 0; i < len;) { + char ch = filter.charAt(i); + if (DEBUG) + System.out.println("char[" + i + "]: '" + ch + "'"); + + if (ch == '"') { + if (!inQuote) { + if (DEBUG) + System.out.println("begin quoted text"); + inQuote = true; + } else { + if (DEBUG) + System.out.println("end quoted text"); + inQuote = false; + addSearchWord(sb, toSinglePatternString( toString(buf), implicitPreAsterisk )); + } + ++i; + continue; + } else if (ch == '\\') { + // Next character is escaped, i.e. taken as is. + ++i; + if (i >= len) + // Unexpected end-of-string + break; + + ch = filter.charAt(i); + if (DEBUG) + System.out.println("append escaped character '" + ch + "'"); + + buf.append(ch); + ++i; + break; + } else if (ch == ' ') { + if (inQuote) { + if (DEBUG) + System.out.println("append char '" + ch + "'"); + buf.append(ch); + ++i; + } else { + if (buf.position() > 0) { + addSearchWord(sb, toSinglePatternString( toString(buf), implicitPreAsterisk )); + } + ++i; + } + } else { + if (DEBUG) + System.out.println("append char '" + ch + "'"); + buf.append(ch); + ++i; + } + } + if (buf.position() > 0) { + addSearchWord(sb, toSinglePatternString( toString(buf), implicitPreAsterisk )); + } + + //sb.append(".*"); + + return sb.toString(); + } + + @Override + public String toPatternString(String filter) { + return defaultToPatternString(filter, implicitPreAsterisk); + } + + public static Pattern compilePattern(String s) { + IFilterStrategy st = new DefaultFilterStrategy(true); + System.out.println("compilePattern(" + s + ")"); + String regex = st.toPatternString(s); + System.out.println(s + " -> " + regex); + Pattern p = Pattern.compile(regex); + return p; + } + + public static void test(String pattern, String... testStrings) { + Pattern p = compilePattern(pattern); + for (String test : testStrings) { + System.out.print("\ttesting '" + test + "'"); + Matcher m = p.matcher(test); + if (m.matches()) { + System.out.println(" - MATCHES"); + } else { + System.out.println(" - NO MATCH"); + } + } + } + + static String[] TEST = { + "foo bar baz biz boz", + "biz bar baz foo boz", + "foo", + "bar", + " foo bar ", + "quux", + " quux ", + " quux foo", + }; + + public static void main(String[] args) { + test("foo$"); + test("."); + test("*"); + test("?"); + test("+"); + test("^"); + test("&"); + test("&&"); + test("&&&"); + test("|"); + test("("); + test(")"); + test("["); + test("]"); + test("{"); + test("}"); + test("()"); + test("[]"); + test("{}"); + test("\\\\"); + test("\\"); + + test("foo bar", TEST); + test("\"foo bar\"", TEST); + test("\"foo bar\" quux", TEST); + test("*\"foo bar\" *quux", TEST); + test("\"*foo bar\" *quux", TEST); + } + +}