You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@chemistry.apache.org by fg...@apache.org on 2010/01/19 18:22:44 UTC

svn commit: r900853 - in /incubator/chemistry/trunk/chemistry: chemistry-commons/src/main/antlr3/org/apache/chemistry/cmissql/ chemistry-commons/src/main/antlr3/org/apache/chemistry/impl/simple/ chemistry-commons/src/main/java/org/apache/chemistry/impl...

Author: fguillaume
Date: Tue Jan 19 17:22:43 2010
New Revision: 900853

URL: http://svn.apache.org/viewvc?rev=900853&view=rev
Log:
fixed CMISQL parser for functions and boolean expressions; implemented CONTAINS, IN_TREE, IN_FOLDER for Simple

Added:
    incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleFulltext.java   (with props)
    incubator/chemistry/trunk/chemistry/chemistry-commons/src/test/java/org/apache/chemistry/impl/simple/TestSimpleFulltext.java   (with props)
Modified:
    incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/antlr3/org/apache/chemistry/cmissql/CmisSqlParser.g
    incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/antlr3/org/apache/chemistry/impl/simple/CmisSqlSimpleWalker.g
    incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleConnection.java
    incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleData.java
    incubator/chemistry/trunk/chemistry/chemistry-commons/src/test/gunit/org/apache/chemistry/cmissql/CmisSql.testsuite
    incubator/chemistry/trunk/chemistry/chemistry-tests/src/main/java/org/apache/chemistry/test/BasicTestCase.java

Modified: incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/antlr3/org/apache/chemistry/cmissql/CmisSqlParser.g
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/antlr3/org/apache/chemistry/cmissql/CmisSqlParser.g?rev=900853&r1=900852&r2=900853&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/antlr3/org/apache/chemistry/cmissql/CmisSqlParser.g (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/antlr3/org/apache/chemistry/cmissql/CmisSqlParser.g Tue Jan 19 17:22:43 2010
@@ -130,19 +130,17 @@
 where_clause: WHERE^ search_condition;
 
 search_condition:
-    // not a BIN_OP
-    boolean_term ( OR^ boolean_term )*;
+    boolean_term ( OR boolean_term )*;
 
 boolean_term:
-    // not a BIN_OP
-    boolean_factor ( AND^ boolean_factor )*;
+    boolean_factor ( AND boolean_factor )*;
 
 boolean_factor:
-    NOT^?  boolean_test;
+    NOT? boolean_test;
 
 boolean_test:
       predicate
-    | LPAR! search_condition RPAR!
+    | LPAR search_condition RPAR
     ;
 
 predicate:
@@ -212,7 +210,9 @@
     ;
 
 text_search_predicate:
-    CONTAINS^ LPAR! (qualifier COMMA!)? text_search_expression RPAR!;
+    CONTAINS LPAR (qualifier COMMA)? text_search_expression RPAR
+      -> ^(FUNC CONTAINS qualifier? text_search_expression)
+    ;
 
 folder_predicate:
     ( f=IN_FOLDER | f=IN_TREE ) LPAR (qualifier COMMA)? folder_id RPAR

Modified: incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/antlr3/org/apache/chemistry/impl/simple/CmisSqlSimpleWalker.g
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/antlr3/org/apache/chemistry/impl/simple/CmisSqlSimpleWalker.g?rev=900853&r1=900852&r2=900853&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/antlr3/org/apache/chemistry/impl/simple/CmisSqlSimpleWalker.g (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/antlr3/org/apache/chemistry/impl/simple/CmisSqlSimpleWalker.g Tue Jan 19 17:22:43 2010
@@ -53,11 +53,23 @@
 
 @members {
     public SimpleData data;
+    public SimpleConnection connection;
+
+    public String errorMessage;
+
+    @Override
+    public void displayRecognitionError(String[] tokenNames,
+            RecognitionException e) {
+        if (errorMessage == null) {
+            errorMessage = getErrorMessage(e, tokenNames);
+        }
+    }
 }
 
-query [SimpleData d] returns [String tableName, boolean matches]
+query [SimpleData d, SimpleConnection conn] returns [String tableName, boolean matches]
 @init {
     data = $d;
+    connection = $conn;
 }:
     ^(SELECT select_list from_clause where_clause order_by_clause?)
     {
@@ -90,7 +102,7 @@
       {
           String col = $column_name.start.getText();
           // TODO should use query name
-          $value = data.get(col); // TODO error if unknown prop
+          $value = data.getIgnoreCase(col); // TODO error if unknown prop
       }
     ;
 
@@ -144,67 +156,31 @@
     ;
 
 search_condition returns [boolean matches]:
-      boolean_term
-        {
-            $matches = $boolean_term.matches;
-        }
-    | ^(OR (list+=boolean_term)+)
-        {
-            $matches = false;
-            for (boolean_term_return t : (List<boolean_term_return>) $list) {
-                if (t.matches) {
-                    $matches = true;
-                    break;
-                }
-            }
-        }
+    b1=boolean_term { $matches = $b1.matches; }
+    (OR b2=boolean_term { $matches |= $b2.matches; })*
     ;
 
 boolean_term returns [boolean matches]:
-      boolean_factor
-        {
-            $matches = $boolean_factor.matches;
-        }
-    | ^(AND (list+=boolean_factor)+)
-        {
-            $matches = true;
-            for (boolean_factor_return t : (List<boolean_factor_return>) $list) {
-                if (t.matches) {
-                    $matches = false;
-                    break;
-                }
-            }
-        }
+    b1=boolean_factor { $matches = $b1.matches; }
+    (AND b2=boolean_factor { $matches &= $b2.matches; })*
     ;
 
 boolean_factor returns [boolean matches]:
-      boolean_test
-        {
-            $matches = $boolean_test.matches;
-        }
-    | ^(NOT boolean_test)
-        {
-            $matches = ! $boolean_test.matches;
-        }
+      b=boolean_test { $matches = $b.matches; }
+    | NOT b=boolean_test { $matches = ! $b.matches; }
     ;
 
 boolean_test returns [boolean matches]:
-      predicate
-        {
-            $matches = $predicate.matches;
-        }
-//    | search_condition
+      predicate { $matches = $predicate.matches; }
+    | LPAR search_condition RPAR { $matches = $search_condition.matches; }
     ;
 
-predicate returns [boolean matches]:
-      ^(UN_OP IS_NULL un_arg)
-        {
-            $matches = $un_arg.value == null;
-        }
-    | ^(UN_OP IS_NOT_NULL un_arg)
-        {
-            $matches = $un_arg.value != null;
-        }
+predicate returns [boolean matches]
+@init {
+    List<Object> literals = new ArrayList<Object>();
+}:
+      ^(UN_OP IS_NULL un_arg) { $matches = $un_arg.value == null; }
+    | ^(UN_OP IS_NOT_NULL un_arg) { $matches = $un_arg.value != null; }
     | ^(BIN_OP bin_op arg1=bin_arg arg2=bin_arg)
         {
             int token = $bin_op.start.getType();
@@ -221,8 +197,24 @@
                     throw new UnwantedTokenException(token, input);
             }
         }
-//    | text_search_predicate
-//    | folder_predicate
+    | ^(FUNC func_name (literal { literals.add($literal.value); })*)
+        {
+            int func = $func_name.start.getType();
+            switch (func) {
+                case IN_FOLDER:
+                    $matches = connection.isInFolder(data, literals.get(0));
+                    break;
+                case IN_TREE:
+                    $matches = connection.isInTree(data, literals.get(0));
+                    break;
+                case CONTAINS:
+                    $matches = connection.fulltextContains(data, literals);
+                    break;
+                case ID:
+                default:
+                    throw new UnwantedTokenException(Token.INVALID_TOKEN_TYPE, input);
+            }
+        }
     ;
 
 un_arg returns [Object value]:
@@ -235,7 +227,10 @@
 bin_op:
     EQ | NEQ | LT | GT | LTEQ | GTEQ | LIKE | NOT_LIKE;
 
-bin_arg returns [Object value]:
+bin_arg returns [Object value]
+@init {
+    List<Object> literals = new ArrayList<Object>();
+}:
       value_expression
         {
             $value = $value_expression.value;
@@ -244,16 +239,15 @@
         {
             $value = $literal.value;
         }
-    | ^(LIST (list+=literal)+)
+    | ^(LIST (literal { literals.add($literal.value); })+)
         {
-            List<Object> ret = new ArrayList<Object>($list.size());
-            for (literal_return l : (List<literal_return>) $list) {
-                ret.add(l.value);
-            }
-            $value = ret;
+            $value = literals;
         }
     ;
 
+func_name:
+    IN_FOLDER | IN_TREE | CONTAINS | ID;
+
 literal returns [Object value]:
       NUM_LIT
         {

Modified: incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleConnection.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleConnection.java?rev=900853&r1=900852&r2=900853&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleConnection.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleConnection.java Tue Jan 19 17:22:43 2010
@@ -23,8 +23,10 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Queue;
 import java.util.Set;
 
 import javax.xml.namespace.QName;
@@ -41,6 +43,7 @@
 import org.apache.chemistry.ACLPropagation;
 import org.apache.chemistry.BaseType;
 import org.apache.chemistry.CMISObject;
+import org.apache.chemistry.CMISRuntimeException;
 import org.apache.chemistry.Connection;
 import org.apache.chemistry.ConstraintViolationException;
 import org.apache.chemistry.ContentStream;
@@ -66,6 +69,7 @@
 import org.apache.chemistry.VersioningState;
 import org.apache.chemistry.cmissql.CmisSqlLexer;
 import org.apache.chemistry.cmissql.CmisSqlParser;
+import org.apache.chemistry.impl.simple.CmisSqlSimpleWalker.query_return;
 import org.apache.chemistry.util.GregorianCalendar;
 
 public class SimpleConnection implements Connection, SPI {
@@ -781,12 +785,69 @@
             CommonTree tree = (CommonTree) new CmisSqlParser(tokens).query().getTree();
             CommonTreeNodeStream nodes = new CommonTreeNodeStream(tree);
             nodes.setTokenStream(tokens);
-            return new CmisSqlSimpleWalker(nodes).query(data);
+            CmisSqlSimpleWalker walker = new CmisSqlSimpleWalker(nodes);
+            query_return res = walker.query(data, this);
+            if (walker.errorMessage != null) {
+                throw new CMISRuntimeException("Cannot parse query: "
+                        + statement + " (" + walker.errorMessage + ")");
+            }
+            return res;
         } catch (IOException e) {
-            throw new RuntimeException(e.getMessage(), e);
+            throw new CMISRuntimeException(e.getMessage(), e);
         } catch (RecognitionException e) {
-            throw new RuntimeException("Cannot parse query: " + statement, e);
+            throw new CMISRuntimeException("Cannot parse query: " + statement,
+                    e);
+        }
+    }
+
+    // IN_FOLDER
+    protected boolean isInFolder(SimpleData data, Object folderId) {
+        if (!(folderId instanceof String)) {
+            throw new IllegalArgumentException(folderId.toString());
+        }
+        Set<String> children = repository.children.get(folderId);
+        if (children == null) {
+            return false; // no such id
+        }
+        return children.contains(data.get(Property.ID));
+    }
+
+    // IN_TREE
+    protected boolean isInTree(SimpleData data, Object folderId) {
+        if (!(folderId instanceof String)) {
+            throw new IllegalArgumentException(folderId.toString());
+        }
+        String id = (String) data.get(Property.ID);
+        if (id == null) {
+            return false; // no such id
+        }
+        Queue<String> todo = new LinkedList<String>(Collections.singleton(id));
+        while (!todo.isEmpty()) {
+            String cur = todo.remove();
+            Set<String> parents = repository.parents.get(cur);
+            for (String pid : parents) {
+                if (pid.equals(folderId)) {
+                    return true;
+                }
+            }
+            todo.addAll(parents);
+        }
+        return false;
+    }
+
+    // CONTAINS
+    protected boolean fulltextContains(SimpleData data, List<Object> args) {
+        // String qual;
+        String query;
+        if (args.size() == 2) {
+            // qual = (String) args.get(0);
+            query = (String) args.get(1);
+        } else {
+            // qual = null;
+            query = (String) args.get(0);
         }
+        Set<String> words = SimpleFulltext.parseFulltext(data);
+        return SimpleFulltext.matchesFullText(words, query);
     }
 
     public Collection<CMISObject> query(String statement,

Modified: incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleData.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleData.java?rev=900853&r1=900852&r2=900853&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleData.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleData.java Tue Jan 19 17:22:43 2010
@@ -41,4 +41,27 @@
         }
     }
 
+    /**
+     * Returns the value to which the specified key is mapped, or {@code null}
+     * if this map contains no mapping for the key.
+     * <p>
+     * Key comparison is done case insensitively.
+     *
+     * @throws NullPointerException if the specified key is {@code null}
+     * @see ConcurrentHashMap#get(Object)
+     */
+    public Serializable getIgnoreCase(String key) {
+        // shortcut for exact case match
+        if (contains(key)) {
+            return get(key);
+        }
+        // try all keys
+        for (String k : keySet()) {
+            if (key.equalsIgnoreCase(k)) {
+                return get(k);
+            }
+        }
+        return null;
+    }
+
 }

Added: incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleFulltext.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleFulltext.java?rev=900853&view=auto
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleFulltext.java (added)
+++ incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleFulltext.java Tue Jan 19 17:22:43 2010
@@ -0,0 +1,155 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Authors:
+ *     Florent Guillaume, Nuxeo
+ */
+package org.apache.chemistry.impl.simple;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
+import java.util.regex.Pattern;
+
+/**
+ * Simple utility class that does basic and naive fulltext match.
+ */
+public class SimpleFulltext {
+
+    private SimpleFulltext() {
+    }
+
+    /**
+     * Extracts the words from a SimpleData for fulltext indexing.
+     */
+    protected static Set<String> parseFulltext(Map<String, Serializable> data) {
+        Set<String> set = new HashSet<String>();
+        for (Entry<String, Serializable> es : data.entrySet()) {
+            Object value = es.getValue();
+            if (value instanceof String) {
+                parseFullText((String) value, set);
+            } else if (value instanceof String[]) {
+                for (String v : (String[]) value) {
+                    parseFullText(v, set);
+                }
+            }
+        }
+        return set;
+    }
+
+    protected static void parseFullText(String string, Set<String> set) {
+        if (string == null) {
+            return;
+        }
+        for (String word : wordPattern.split(string)) {
+            String w = parseWord(word);
+            if (w != null) {
+                set.add(w);
+            }
+        }
+    }
+
+    /**
+     * Checks if the passed query expression matches the fulltext.
+     */
+    // TODO XXX implement actual CMIS 1.0 language
+    protected static boolean matchesFullText(Set<String> fulltextWords,
+            String query) {
+        if (fulltextWords == null || query == null) {
+            return false;
+        }
+        Set<String> queryWords = split(query, ' ');
+        if (queryWords.isEmpty()) {
+            return false;
+        }
+        for (String word : queryWords) {
+            if (!fulltextWords.contains(word)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    // ----- simple parsing, don't try to be exhaustive -----
+
+    private static final Pattern wordPattern = Pattern.compile("[\\s\\p{Punct}]+");
+
+    private static final String UNACCENTED = "aaaaaaaceeeeiiii\u00f0nooooo\u00f7ouuuuy\u00fey";
+
+    private static final String STOPWORDS = "a an are and as at be by for from how "
+            + "i in is it of on or that the this to was what when where who will with "
+            + "car donc est il ils je la le les mais ni nous or ou pour tu un une vous "
+            + "www com net org";
+
+    private static final Set<String> stopWords = new HashSet<String>(split(
+            STOPWORDS, ' '));
+
+    protected static final String parseWord(String string) {
+        int len = string.length();
+        if (len < 3) {
+            return null;
+        }
+        StringBuilder buf = new StringBuilder(len);
+        for (int i = 0; i < len; i++) {
+            char c = Character.toLowerCase(string.charAt(i));
+            if (c == '\u00e6') {
+                buf.append("ae");
+            } else if (c >= '\u00e0' && c <= '\u00ff') {
+                buf.append(UNACCENTED.charAt((c) - 0xe0));
+            } else if (c == '\u0153') {
+                buf.append("oe");
+            } else {
+                buf.append(c);
+            }
+        }
+        // simple heuristic to remove plurals
+        int l = buf.length();
+        if (l > 3 && buf.charAt(l - 1) == 's') {
+            buf.setLength(l - 1);
+        }
+        String word = buf.toString();
+        if (stopWords.contains(word)) {
+            return null;
+        }
+        return word;
+    }
+
+    protected static Set<String> split(String string, char sep) {
+        int len = string.length();
+        if (len == 0) {
+            return Collections.emptySet();
+        }
+        int end = string.indexOf(sep);
+        if (end == -1) {
+            return Collections.singleton(string);
+        }
+        Set<String> set = new HashSet<String>();
+        int start = 0;
+        do {
+            String segment = string.substring(start, end);
+            set.add(segment);
+            start = end + 1;
+            end = string.indexOf(sep, start);
+        } while (end != -1);
+        if (start < len) {
+            set.add(string.substring(start));
+        } else {
+            set.add("");
+        }
+        return set;
+    }
+
+}

Propchange: incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleFulltext.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleFulltext.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: incubator/chemistry/trunk/chemistry/chemistry-commons/src/test/gunit/org/apache/chemistry/cmissql/CmisSql.testsuite
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-commons/src/test/gunit/org/apache/chemistry/cmissql/CmisSql.testsuite?rev=900853&r1=900852&r2=900853&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-commons/src/test/gunit/org/apache/chemistry/cmissql/CmisSql.testsuite (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-commons/src/test/gunit/org/apache/chemistry/cmissql/CmisSql.testsuite Tue Jan 19 17:22:43 2010
@@ -113,12 +113,12 @@
 "IN_TREE('ID123')" -> (FUNC IN_TREE 'ID123')
 
 text_search_predicate:
-"CONTAINS('foo')" -> (CONTAINS 'foo')
-"CONTAINS(bar, 'foo')" -> (CONTAINS bar 'foo')
+"CONTAINS('foo')" -> (FUNC CONTAINS 'foo')
+"CONTAINS(bar, 'foo')" -> (FUNC CONTAINS bar 'foo')
 
-search_condition:
-"foo = 1" -> (BIN_OP = (COL foo) 1)
-"a = 1 AND b <> 2 OR c >= 3 AND NOT d <= 4" -> (OR (AND (BIN_OP = (COL a) 1) (BIN_OP <> (COL b) 2)) (AND (BIN_OP >= (COL c) 3) (NOT (BIN_OP <= (COL d) 4))))
+where_clause:
+"WHERE foo = 1" -> (WHERE (BIN_OP = (COL foo) 1))
+"WHERE a = 1 AND b <> 2 OR c >= 3 AND NOT d <= 4" -> (WHERE (BIN_OP = (COL a) 1) AND (BIN_OP <> (COL b) 2) OR (BIN_OP >= (COL c) 3) AND NOT (BIN_OP <= (COL d) 4))
 
 query:
 "SELECT * FROM Document" -> (SELECT * (FROM (TABLE Document)))
@@ -132,7 +132,7 @@
 SELECT TITLE, AUTHORS, DATE
 FROM WHITE_PAPER
 WHERE ( IN_TREE('ID00093854763') ) AND ( 'SMITH' = ANY AUTHORS )
->> -> (SELECT (LIST (COL TITLE) (COL AUTHORS) (COL DATE)) (FROM (TABLE WHITE_PAPER)) (WHERE (AND (FUNC IN_TREE 'ID00093854763') (BIN_OP_ANY = 'SMITH' (COL AUTHORS)))))
+>> -> (SELECT (LIST (COL TITLE) (COL AUTHORS) (COL DATE)) (FROM (TABLE WHITE_PAPER)) (WHERE ( (FUNC IN_TREE 'ID00093854763') ) AND ( (BIN_OP_ANY = 'SMITH' (COL AUTHORS)) )))
 
 <<
 SELECT OBJECT_ID, SCORE() AS X, DESTINATION, DEPARTURE_DATES

Added: incubator/chemistry/trunk/chemistry/chemistry-commons/src/test/java/org/apache/chemistry/impl/simple/TestSimpleFulltext.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-commons/src/test/java/org/apache/chemistry/impl/simple/TestSimpleFulltext.java?rev=900853&view=auto
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-commons/src/test/java/org/apache/chemistry/impl/simple/TestSimpleFulltext.java (added)
+++ incubator/chemistry/trunk/chemistry/chemistry-commons/src/test/java/org/apache/chemistry/impl/simple/TestSimpleFulltext.java Tue Jan 19 17:22:43 2010
@@ -0,0 +1,72 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Authors:
+ *     Florent Guillaume, Nuxeo
+ *     Amelie Avramo, EntropySoft
+ */
+package org.apache.chemistry.impl.simple;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+public class TestSimpleFulltext extends TestCase {
+
+    public static void checkSplit(String string, String... expected) {
+        assertEquals(new HashSet<String>(Arrays.asList(expected)),
+                SimpleFulltext.split(string, ' '));
+    }
+
+    public static void checkSplit(char sep, String string, String... expected) {
+        assertEquals(new HashSet<String>(Arrays.asList(expected)),
+                SimpleFulltext.split(string, sep));
+    }
+
+    public void testSplit() {
+        checkSplit("", new String[0]);
+        checkSplit("A", "A");
+        checkSplit("A B C", "A", "B", "C");
+        checkSplit("A  B", "A", "B", "");
+        checkSplit(" A B C", "A", "B", "C", "");
+        checkSplit("A B C ", "A", "B", "C", "");
+        checkSplit("  ", "");
+        checkSplit('-', "A-B-C", "A", "B", "C");
+    }
+
+    public void testParse() {
+        assertNull(SimpleFulltext.parseWord("gr"));
+        assertNull(SimpleFulltext.parseWord("are"));
+        assertNull(SimpleFulltext.parseWord("THE"));
+        assertEquals("foo", SimpleFulltext.parseWord("foo"));
+        assertEquals("foo", SimpleFulltext.parseWord("fOoS"));
+    }
+
+    protected static void checkParseFullText(String expected, String text) {
+        Set<String> set = new HashSet<String>();
+        SimpleFulltext.parseFullText(text, set);
+        assertEquals(new HashSet<String>(Arrays.asList(expected.split(" "))),
+                set);
+    }
+
+    public void testParseFullText() throws Exception {
+        checkParseFullText("brown dog fail fox jump lazy over quick",
+                "The quick brown fox jumps over the lazy dog -- and fails!");
+        checkParseFullText("aime cafe jure pas",
+                "J'aime PAS le caf\u00e9, je te jure.");
+        checkParseFullText("007 bond jame thx1138", "James Bond 007 && THX1138");
+    }
+
+}

Propchange: incubator/chemistry/trunk/chemistry/chemistry-commons/src/test/java/org/apache/chemistry/impl/simple/TestSimpleFulltext.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/chemistry/trunk/chemistry/chemistry-commons/src/test/java/org/apache/chemistry/impl/simple/TestSimpleFulltext.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: incubator/chemistry/trunk/chemistry/chemistry-tests/src/main/java/org/apache/chemistry/test/BasicTestCase.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-tests/src/main/java/org/apache/chemistry/test/BasicTestCase.java?rev=900853&r1=900852&r2=900853&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-tests/src/main/java/org/apache/chemistry/test/BasicTestCase.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-tests/src/main/java/org/apache/chemistry/test/BasicTestCase.java Tue Jan 19 17:22:43 2010
@@ -252,11 +252,65 @@
     }
 
     public void testQuery() {
-        Collection<CMISObject> res = conn.query("SELECT * FROM doc", false);
+        String rootId = spi.getRepository().getInfo().getRootFolderId().getId();
+        String folder1Id = spi.getObjectByPath("/folder 1", null).getId();
+        String folder2Id = spi.getObjectByPath("/folder 1/folder 2", null).getId();
+        Collection<CMISObject> res;
+
+        res = conn.query("SELECT * FROM doc", false);
+        assertNotNull(res);
+        assertEquals(4, res.size());
+        res = conn.query("SELECT * FROM cmis:document", false);
         assertNotNull(res);
         assertEquals(4, res.size());
+        ObjectEntry doc = spi.getObjectByPath("/folder 1/folder 2/doc 2", null);
+        res = conn.query(String.format(
+                "SELECT * FROM cmis:document WHERE cmis:objectId = '%s'",
+                doc.getId()), false);
+        assertEquals(1, res.size());
+
         res = conn.query("SELECT * FROM fold", false);
         assertEquals(2, res.size());
+        res = conn.query("SELECT * FROM cmis:folder", false);
+        assertEquals(3, res.size()); // root as well
+        res = conn.query(String.format(
+                "SELECT * FROM cmis:folder WHERE cmis:objectId = '%s'",
+                folder2Id), false);
+        assertEquals(1, res.size());
+        res = conn.query(String.format(
+                "SELECT * FROM cmis:folder WHERE cmis:objectId = '%s'"
+                        + " AND cmis:name = 'folder 2'"
+                        + " AND title <> 'blarg'", //
+                folder2Id), false);
+        assertEquals(1, res.size());
+
+        // IN_FOLDER
+        String sqlpat = "SELECT * FROM cmis:document WHERE IN_FOLDER('%s')";
+        res = conn.query(String.format(sqlpat, folder2Id), false);
+        assertEquals(3, res.size());
+        sqlpat = "SELECT * FROM cmis:folder WHERE IN_FOLDER('%s')";
+        res = conn.query(String.format(sqlpat, folder1Id), false);
+        assertEquals(1, res.size());
+
+        // IN_TREE
+        sqlpat = "SELECT * FROM cmis:document WHERE IN_TREE('%s')";
+        res = conn.query(String.format(sqlpat, folder2Id), false);
+        assertEquals(3, res.size());
+        sqlpat = "SELECT * FROM cmis:document WHERE IN_TREE('%s')";
+        res = conn.query(String.format(sqlpat, folder1Id), false);
+        assertEquals(4, res.size());
+        sqlpat = "SELECT * FROM cmis:folder WHERE IN_TREE('%s')";
+        res = conn.query(String.format(sqlpat, rootId), false);
+        assertEquals(2, res.size());
+
+        // CONTAINS
+        res = conn.query(
+                "SELECT * FROM cmis:folder WHERE CONTAINS('description')",
+                false);
+        assertEquals(2, res.size());
+        res = conn.query("SELECT * FROM cmis:document WHERE CONTAINS('small')",
+                false);
+        assertEquals(1, res.size());
     }
 
     public void testGetObjectByPath() {