1 /*******************************************************************************
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.browsing.ui.common.views;
14 import java.nio.CharBuffer;
15 import java.util.regex.Matcher;
16 import java.util.regex.Pattern;
19 * Default implementation of IFilterStrategy.
22 * It implements simple search semantics with only the special wildcard
23 * characters '*' ( 0 to n any characters) and '?' (any one character)
24 * recognized. In order to allow the filter to pass arbitrary prefixes, the
25 * client has to give a '*' prefix in the filter string. On the contrary, the
26 * client does not have to specify a '*' in order to pass arbitrary suffixes -
27 * arbitrary suffixes are allowed by default by this strategy.
30 * This strategy forces the filter string to lowercase.
32 * TODO: implement case-insensitiveness properly, not by forcing the search string into lower case. Also Fix FilterSelectionRequestQueryProcessor after doing this.
34 * @author Tuukka Lehtonen
36 public class DefaultFilterStrategy implements IFilterStrategy {
38 private static final boolean DEBUG = false;
40 boolean implicitPreAsterisk = true;
42 public DefaultFilterStrategy() {
46 public DefaultFilterStrategy(boolean implicitPreAsterisk) {
47 this.implicitPreAsterisk = implicitPreAsterisk;
50 private static StringBuilder addSearchWord(StringBuilder sb, String pattern) {
52 System.out.println("addSearchWord(" + pattern + ") to '" + sb.toString() + "'");
54 if (pattern == null || pattern.isEmpty())
64 private static String toString(CharBuffer cb) {
65 cb.limit(cb.position());
68 System.out.println("toString(" + cb + ")");
69 String result = cb.toString();
70 cb.limit(cb.capacity());
74 public static String toSinglePatternString(String filter, boolean implicitPreAsterisk) {
75 if (!filter.isEmpty()) {
76 // Force searching in lowercase.
77 filter = filter.toLowerCase();
79 // Construct a regular expression from the specified text.
80 String regExFilter = filter
81 .replace("\\", "\\\\") // \ -> \\
82 .replace(".", "\\.") // . -> \.
83 .replace("*", ".*") // * -> Any 0..n characters
84 .replace("?", ".") // ? -> Any single character
85 .replace("+", "\\+") // + -> \+
86 .replace("(", "\\(") // ( -> \(
87 .replace(")", "\\)") // ) -> \)
88 .replace("[", "\\[") // [ -> \[
89 .replace("]", "\\]") // ] -> \]
90 .replace("{", "\\{") // { -> \{
91 .replace("}", "\\}") // } -> \}
92 .replace("^", "\\^") // ^ -> \^
93 .replace("$", "\\$") // $ -> \$
94 .replace("|", ".*|") // $ -> \$
95 //.replace("|", "\\|") // | -> \|
96 .replace("&&", "\\&&") // && -> \&&
99 if (implicitPreAsterisk)
100 if (!regExFilter.startsWith(".*"))
101 regExFilter = ".*" + regExFilter ;
102 if (!regExFilter.endsWith(".*"))
103 regExFilter += ".*" ;
110 public static String defaultToPatternString(String filter, boolean implicitPreAsterisk) {
111 if (filter.isEmpty())
114 CharBuffer buf = CharBuffer.allocate(filter.length()*2);
116 StringBuilder sb = new StringBuilder(filter.length()*2);
117 boolean inQuote = false;
118 int len = filter.length();
119 for (int i = 0; i < len;) {
120 char ch = filter.charAt(i);
122 System.out.println("char[" + i + "]: '" + ch + "'");
127 System.out.println("begin quoted text");
131 System.out.println("end quoted text");
133 addSearchWord(sb, toSinglePatternString( toString(buf), implicitPreAsterisk ));
137 } else if (ch == '\\') {
138 // Next character is escaped, i.e. taken as is.
141 // Unexpected end-of-string
144 ch = filter.charAt(i);
146 System.out.println("append escaped character '" + ch + "'");
151 } else if (ch == ' ') {
154 System.out.println("append char '" + ch + "'");
158 if (buf.position() > 0) {
159 addSearchWord(sb, toSinglePatternString( toString(buf), implicitPreAsterisk ));
165 System.out.println("append char '" + ch + "'");
170 if (buf.position() > 0) {
171 addSearchWord(sb, toSinglePatternString( toString(buf), implicitPreAsterisk ));
176 return sb.toString();
180 public String toPatternString(String filter) {
181 return defaultToPatternString(filter, implicitPreAsterisk);
184 public static Pattern compilePattern(String s) {
185 IFilterStrategy st = new DefaultFilterStrategy(true);
186 System.out.println("compilePattern(" + s + ")");
187 String regex = st.toPatternString(s);
188 System.out.println(s + " -> " + regex);
189 Pattern p = Pattern.compile(regex);
193 public static void test(String pattern, String... testStrings) {
194 Pattern p = compilePattern(pattern);
195 for (String test : testStrings) {
196 System.out.print("\ttesting '" + test + "'");
197 Matcher m = p.matcher(test);
199 System.out.println(" - MATCHES");
201 System.out.println(" - NO MATCH");
206 static String[] TEST = {
207 "foo bar baz biz boz",
208 "biz bar baz foo boz",
217 public static void main(String[] args) {
240 test("foo bar", TEST);
241 test("\"foo bar\"", TEST);
242 test("\"foo bar\" quux", TEST);
243 test("*\"foo bar\" *quux", TEST);
244 test("\"*foo bar\" *quux", TEST);