You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@chemistry.apache.org by je...@apache.org on 2010/07/12 08:41:50 UTC

svn commit: r963193 [2/3] - in /incubator/chemistry/opencmis/trunk/chemistry-opencmis-server: chemistry-opencmis-server-inmemory/ chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/ chemistry-opencmis-server-inmemor...

Added: incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/antlr3/org/apache/chemistry/opencmis/server/support/query/CmisQlStrictParser.g
URL: http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/antlr3/org/apache/chemistry/opencmis/server/support/query/CmisQlStrictParser.g?rev=963193&view=auto
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/antlr3/org/apache/chemistry/opencmis/server/support/query/CmisQlStrictParser.g (added)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/antlr3/org/apache/chemistry/opencmis/server/support/query/CmisQlStrictParser.g Mon Jul 12 06:41:49 2010
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ *
+*/
+
+parser grammar CmisQlStrictParser;
+
+// Note: ANTLR is very sensitive to compilation errors, you must
+// have first options, then import and then @header.
+// @header must only be in derived grammars not in base grammars
+// no package declarations in base grammars
+
+
+options {
+    tokenVocab = CmisQlStrictLexer;
+    output = AST;
+}
+
+import CmisBaseGrammar;
+
+@header {
+/*
+ * THIS FILE IS AUTO-GENERATED, DO NOT EDIT.
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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:
+ *     Stefane Fermigier, Nuxeo
+ *     Florent Guillaume, Nuxeo
+ *
+ * THIS FILE IS AUTO-GENERATED, DO NOT EDIT.
+ */
+package org.apache.chemistry.opencmis.server.support.query;
+}
+
+@members {
+	protected void mismatch(IntStream input, int ttype, BitSet follow)
+		throws RecognitionException
+	{
+		throw new MismatchedTokenException(ttype, input);
+	}
+	
+	public void recoverFromMismatchedSet(IntStream input, RecognitionException e, antlr.collections.impl.BitSet follow)
+		throws RecognitionException
+	{
+		throw e;
+	}
+}
+
+@rulecatch {
+	catch (RecognitionException e) {
+		throw e;
+	}
+}
+
+  // Rules can't be empty so we have one dummy rule here
+root : query;

Added: incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/antlr3/org/apache/chemistry/opencmis/server/support/query/CmisQueryWalker.g
URL: http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/antlr3/org/apache/chemistry/opencmis/server/support/query/CmisQueryWalker.g?rev=963193&view=auto
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/antlr3/org/apache/chemistry/opencmis/server/support/query/CmisQueryWalker.g (added)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/antlr3/org/apache/chemistry/opencmis/server/support/query/CmisQueryWalker.g Mon Jul 12 06:41:49 2010
@@ -0,0 +1,328 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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
+ */
+/**
+ * CMISQL tree grammar, walker for the inmemory implementation.
+ * This aims at implementing proper semantics without any speed
+ * optimization.
+ */
+tree grammar CmisQueryWalker;
+
+options {
+    tokenVocab = CmisQlStrictLexer;
+    ASTLabelType = CommonTree;
+    output = AST;
+}
+
+@header {
+/*
+ * THIS FILE IS AUTO-GENERATED, DO NOT EDIT.
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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
+ *
+ * THIS FILE IS AUTO-GENERATED, DO NOT EDIT.
+ */
+package org.apache.chemistry.opencmis.server.support.query;
+
+import java.math.BigDecimal;
+
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.HashMap;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.chemistry.opencmis.server.support.query.*;
+}
+
+@members {
+    private static Log LOG = LogFactory.getLog(CmisQueryWalker.class);
+
+    public QueryObject queryObj;
+    public String errorMessage;
+
+    @Override
+    public void displayRecognitionError(String[] tokenNames,
+            RecognitionException e) {
+        if (errorMessage == null) {
+            String hdr = getErrorHeader(e);
+            String msg = getErrorMessage(e, tokenNames);
+            errorMessage = hdr + " " + msg;
+        }
+    }
+    
+    public String getErrorMessageString() {
+        return errorMessage;
+    }
+    
+	protected void mismatch(IntStream input, int ttype, BitSet follow)
+		throws RecognitionException
+	{
+		throw new MismatchedTokenException(ttype, input);
+	}
+	
+	public void recoverFromMismatchedSet(IntStream input, RecognitionException e, antlr.collections.impl.BitSet follow)
+		throws RecognitionException
+	{
+		throw e;
+	}
+}
+
+// For CMIS SQL it will be sufficient to stop on first error:
+@rulecatch {
+	catch (RecognitionException e) {
+		throw e;
+	}
+}
+
+query [QueryObject qo]
+	@init {
+		queryObj = qo;
+	}:
+    ^(SELECT select_list from_clause order_by_clause? where_clause)
+    {
+    	queryObj.resolveTypes();
+    	queryObj.processWhereClause($where_clause.tree);
+    }
+    ;
+
+select_list:
+      STAR
+      {
+      	  //queryObj.addSelectReference($STAR.getToken(), new ColumnReference($STAR.text));
+      	  // LOG.debug("Adding * to col refs: " + $STAR);
+      	  queryObj.addSelectReference($STAR, new ColumnReference($STAR.text));
+      }
+    | ^(SEL_LIST select_sublist+)
+    ;
+
+select_sublist
+	scope { String current; }
+	:
+      value_expression column_name? 
+      {
+          // add selector
+          queryObj.addSelectReference($value_expression.start, $value_expression.result);
+          // add alias for column
+          if ($column_name.text != null) {
+             queryObj.addAlias($column_name.text, $value_expression.result);
+          }
+	  }
+    | s=qualifier DOT STAR
+      {
+      	  // queryObj.addSelectReference($STAR.getToken(), new ColumnReference($qualifier.value, $STAR.text));
+      	  //  LOG.debug("Adding x.* to col refs: " + $s.start);
+      	  queryObj.addSelectReference($s.start, new ColumnReference($qualifier.value, $STAR.text));
+      }
+    ;
+    
+    
+value_expression returns [CmisSelector result]:
+      column_reference
+      {
+          $result = $column_reference.result;
+      }
+    | SCORE^
+        {
+            $result = new FunctionReference(FunctionReference.CmisQlFunction.SCORE);
+        }
+    ;
+
+column_reference returns [ColumnReference result]:
+    ^(COL qualifier? column_name)
+      {
+          $result = new ColumnReference($qualifier.value, $column_name.text);
+      }
+    ;
+
+// multi_valued_column_reference returns [Object value]:
+//    ^(COL qualifier? column_name)
+
+qualifier returns [String value]:
+      table_name
+//    | correlation_name
+    {
+      $value = $table_name.text;
+    }
+    ;
+
+from_clause:
+    ^(FROM table_reference)
+    ;
+
+table_reference:
+    one_table table_join*
+    ;
+
+table_join:
+    ^(JOIN join_kind one_table join_specification?)
+    ;
+
+one_table:
+    ^(TABLE table_name correlation_name?)
+      {
+          queryObj.addType($correlation_name.text, $table_name.text);
+      }
+    ;
+
+join_kind:
+    INNER | LEFT | OUTER;
+
+join_specification:
+    ^(ON cr1=column_reference EQ cr2=column_reference)
+    {
+          queryObj.addJoinReference($cr1.start, $cr1.result);
+          queryObj.addJoinReference($cr2.start, $cr2.result);
+    }
+    ;
+
+where_clause:
+      ^(WHERE search_condition)
+    | /* nothing */
+    ;
+
+search_condition
+@init {
+    List<Object> listLiterals;
+}:
+    ^(OR s1=search_condition s2=search_condition)
+    | ^(AND s1=search_condition s2=search_condition)
+    | ^(NOT search_condition)
+    | ^(EQ search_condition search_condition)
+    | ^(NEQ search_condition search_condition)
+    | ^(LT search_condition search_condition)
+    | ^(GT search_condition search_condition)
+    | ^(GTEQ search_condition search_condition)
+    | ^(LTEQ search_condition search_condition)
+    | ^(LIKE search_condition search_condition)
+    | ^(NOT_LIKE search_condition search_condition)
+    | ^(IS_NULL search_condition) 
+    | ^(IS_NOT_NULL search_condition) 
+    | ^(EQ_ANY literal column_reference)
+      {
+      	  queryObj.addSelectReference($column_reference.start, $column_reference.result);
+      }
+    | ^(IN_ANY search_condition in_value_list )
+    | ^(NOT_IN_ANY search_condition in_value_list)
+    | ^(CONTAINS qualifier? text_search_expression)
+    | ^(IN_FOLDER qualifier? search_condition)
+    | ^(IN_TREE qualifier? search_condition)
+    | ^(IN column_reference in_value_list)
+      {
+      	  queryObj.addSelectReference($column_reference.start, $column_reference.result);
+      }
+    | ^(NOT_IN column_reference in_value_list)
+      {
+      	  queryObj.addSelectReference($column_reference.start, $column_reference.result);
+      }
+    | value_expression
+      {
+          LOG.debug("  add node to where: " + $value_expression.start + " id: " + System.identityHashCode($value_expression.start));
+          queryObj.addWhereReference($value_expression.start, $value_expression.result);      
+      }
+    | literal
+    ;
+
+in_value_list returns [Object inList]
+@init {
+    List<Object> inLiterals = new ArrayList<Object>();
+}:
+    ^(IN_LIST (l=literal {inLiterals.add($l.value);})+ )
+    { 
+    	$inList = inLiterals; 
+    }
+    ;
+
+text_search_expression:
+    STRING_LIT; // TODO: extend grammar with full text part
+
+
+literal returns [Object value]:
+      NUM_LIT
+        {
+            try {
+                $value = Long.valueOf($NUM_LIT.text);
+            } catch (NumberFormatException e) {
+                $value = new BigDecimal($NUM_LIT.text);
+            }
+        }
+    | STRING_LIT
+        {
+            String s = $STRING_LIT.text;
+            $value = s.substring(1, s.length() - 1);
+        }
+    | TIME_LIT
+        {
+            String s = $TIME_LIT.text;
+            s = s.substring(s.indexOf('\'') + 1, s.length() - 1);
+            try {
+                // $value = CalendarHelper.fromString(s);
+            } catch (IllegalArgumentException e) {
+                throw new UnwantedTokenException(Token.INVALID_TOKEN_TYPE, input);
+            }
+        }
+    | BOOL_LIT
+        {
+            $value = Boolean.valueOf($BOOL_LIT.text);
+        }
+    ;
+
+order_by_clause:
+    ^(ORDER_BY sort_specification+)
+    ;
+
+sort_specification:
+    column_reference ASC 
+    {
+       queryObj.addSortCriterium($column_reference.start, $column_reference.result, true);
+    }
+    | column_reference DESC 
+    {
+       queryObj.addSortCriterium($column_reference.start, $column_reference.result, false);
+    }
+    ;
+
+correlation_name:
+    ID;
+
+table_name:
+    ID;
+
+column_name:
+    ID;

Added: incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/TypeManager.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/TypeManager.java?rev=963193&view=auto
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/TypeManager.java (added)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/TypeManager.java Mon Jul 12 06:41:49 2010
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.chemistry.opencmis.server.support;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
+import org.apache.chemistry.opencmis.commons.definitions.TypeDefinitionContainer;
+
+public interface TypeManager {
+
+    /**
+     * return a type definition from the type definition id
+     * 
+     * @param typeId
+     *            id of the type definition
+     * @return type definition for this id
+     */
+    public abstract TypeDefinitionContainer getTypeById(String typeId);
+
+    /**
+     * return a type definition from the type query name or null if not found
+     * 
+     * @param typeQueryName
+     *            query name of the type definition
+     * @return type definition for this query name
+     */
+    public abstract TypeDefinition getTypeByQueryName(String typeQueryName);
+
+    /**
+     * return a list of all types known in this repository
+     * 
+     * @return
+     */
+    public abstract Collection<TypeDefinitionContainer> getTypeDefinitionList();
+
+    /**
+     * return a list of the root types as defined in the CMIS spec (for
+     * document, folder, policy and relationship
+     * 
+     * @return
+     */
+    public abstract List<TypeDefinitionContainer> getRootTypes();
+
+    /**
+     * retrieve the property id from a type for a given property query name 
+     * 
+     * @param typeDefinition
+     *      type definition containing query name
+     * @param propQueryName
+     *      query name of property
+     * @return
+     *      property id of property or null if not found
+     */
+    public abstract String getPropertyIdForQueryName(TypeDefinition typeDefinition, String propQueryName);
+
+}
\ No newline at end of file

Added: incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/TypeValidator.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/TypeValidator.java?rev=963193&view=auto
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/TypeValidator.java (added)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/TypeValidator.java Mon Jul 12 06:41:49 2010
@@ -0,0 +1,424 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.chemistry.opencmis.server.support;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.chemistry.opencmis.commons.PropertyIds;
+import org.apache.chemistry.opencmis.commons.data.Properties;
+import org.apache.chemistry.opencmis.commons.data.PropertyData;
+import org.apache.chemistry.opencmis.commons.data.PropertyDecimal;
+import org.apache.chemistry.opencmis.commons.data.PropertyInteger;
+import org.apache.chemistry.opencmis.commons.definitions.Choice;
+import org.apache.chemistry.opencmis.commons.definitions.DocumentTypeDefinition;
+import org.apache.chemistry.opencmis.commons.definitions.PropertyDecimalDefinition;
+import org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition;
+import org.apache.chemistry.opencmis.commons.definitions.PropertyIntegerDefinition;
+import org.apache.chemistry.opencmis.commons.definitions.PropertyStringDefinition;
+import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
+import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
+import org.apache.chemistry.opencmis.commons.enums.Cardinality;
+import org.apache.chemistry.opencmis.commons.enums.VersioningState;
+import org.apache.chemistry.opencmis.commons.exceptions.CmisConstraintException;
+
+/**
+ * @author Jens
+ */
+public class TypeValidator {
+
+    public static void validateRequiredSystemProperties(Properties properties) {
+        if (properties == null || properties.getProperties() == null)
+            throw new RuntimeException("Cannot create object, no properties are given");
+
+        if (!properties.getProperties().containsKey(PropertyIds.OBJECT_TYPE_ID))
+            throw new RuntimeException("Cannot create object, type id is missing");
+
+    }
+
+    private static boolean isMandatorySystemProperty(String propertyId) {
+        // TODO Auto-generated method stub
+        return propertyId.equals(PropertyIds.OBJECT_TYPE_ID);
+    }
+
+    @SuppressWarnings("unchecked")
+    static <T> PropertyValidator<T> createPropertyValidator(PropertyDefinition<?> propDef) {
+        PropertyValidator<T> result = null;
+        if (propDef instanceof PropertyIntegerDefinition) {
+            result = (PropertyValidator<T>) new PropertyValidatorInteger();
+        } else if (propDef instanceof PropertyDecimalDefinition) {
+            result = (PropertyValidator<T>) new PropertyValidatorDecimal();
+        } else if (propDef instanceof PropertyStringDefinition) {
+            result = (PropertyValidator<T>) new PropertyValidatorString();
+        } else {
+            result = new PropertyValidator<T>();
+        }
+        return result;
+    }
+
+    /*
+     * property validations: not readonly, all required are given, all are known
+     * in type cardinality: no multi values for single value, def min max check
+     * for Integer and Decimal, choices and in list Strings, max length set
+     * default value for omitted properties
+     */
+    static class PropertyValidator<T> {
+
+        public void validate(PropertyDefinition<T> propDef, PropertyData<T> prop) {
+
+            // check general constraints for all property types
+            if (propDef.getCardinality() == Cardinality.SINGLE && prop.getValues().size() > 1)
+                throw new CmisConstraintException("The property with id " + propDef.getId()
+                        + " is single valued, but multiple values are passed " + prop.getValues());
+
+            if (propDef.getChoices() != null && propDef.getChoices().size() > 0) {
+                validateChoices(propDef, prop);
+            }
+        }
+
+        private void validateChoices(PropertyDefinition<T> propDef, PropertyData<T> prop) {
+            boolean isAllowedValue = true;
+            boolean hasMultiValueChoiceLists = false;
+            for (Choice<?> allowedValue : propDef.getChoices()) {
+                if (allowedValue.getValue() != null && allowedValue.getValue().size() > 1)
+                    hasMultiValueChoiceLists = true;
+            }
+
+            // check if value is in list
+            if (hasMultiValueChoiceLists) {
+                // do a complex check if this combination of actual values is
+                // allowed
+                // check if value is in list
+                isAllowedValue = false;
+                List<?> actualValues = prop.getValues();
+                for (Choice<?> allowedValue : propDef.getChoices()) {
+                    if (allowedValue.getValue().size() == actualValues.size()) {
+                        boolean listValuesAreEqual = true;
+                        Iterator<?> it = allowedValue.getValue().iterator();
+                        for (Object actualValue : actualValues) {
+                            if (!actualValue.equals(it.next())) {
+                                listValuesAreEqual = false;
+                                break;
+                            }
+                        }
+                        if (listValuesAreEqual) {
+                            isAllowedValue = true;
+                        }
+                    }
+
+                    if (isAllowedValue)
+                        break;
+                }
+
+            } else {
+                List<T> allowedValues = getAllowedValues(propDef.getChoices());
+                // do a simpler check if all values are choice elements
+
+                for (Object actualValue : prop.getValues()) {
+                    if (!allowedValues.contains(actualValue)) {
+                        isAllowedValue = false;
+                        break;
+                    }
+                }
+            }
+
+            if (!isAllowedValue)
+                throw new CmisConstraintException("The property with id " + propDef.getId()
+                        + " has a fixed set of values. Value(s) " + prop.getValues() + " are not listed.");
+        }
+
+        /**
+         * Calculate the list of allowed values for this property definition by
+         * recursively collecting all choice values from property definition
+         * 
+         * @param propDef
+         *            property definition
+         * @return list of possible values in complete hierarchy
+         */
+        private List<T> getAllowedValues(List<Choice<T>> choices) {
+            List<T> allowedValues = new ArrayList<T>(choices.size());
+            for (Choice<T> choice : choices) {
+                if (choice.getValue() != null)
+                    allowedValues.add(choice.getValue().get(0));
+                if (choice.getChoice() != null) {
+                    List<Choice<T>> x = choice.getChoice();
+                    allowedValues.addAll(getAllowedValues(x));
+                }
+            }
+            return allowedValues;
+        }
+    }
+
+    static class PropertyValidatorInteger extends PropertyValidator<BigInteger> {
+
+        public void validate(PropertyDefinition<BigInteger> propDef, PropertyData<BigInteger> property) {
+
+            super.validate(propDef, property);
+
+            BigInteger propVal = ((PropertyInteger) property).getFirstValue();
+            BigInteger minVal = ((PropertyIntegerDefinition) propDef).getMinValue();
+            BigInteger maxVal = ((PropertyIntegerDefinition) propDef).getMaxValue();
+
+            // check min and max
+            if (minVal != null && propVal != null && propVal.compareTo(minVal) == -1) {
+                throw new CmisConstraintException("For property with id " + propDef.getId() + " the value " + propVal
+                        + " is less than the minimum value " + minVal);
+            }
+            if (maxVal != null && propVal != null && propVal.compareTo(maxVal) == 1) {
+                throw new CmisConstraintException("For property with id " + propDef.getId() + " the value " + propVal
+                        + " is bigger than the maximum value " + maxVal);
+            }
+        }
+    }
+
+    static class PropertyValidatorDecimal extends PropertyValidator<BigDecimal> {
+
+        public void validate(PropertyDefinition<BigDecimal> propDef, PropertyData<BigDecimal> property) {
+
+            super.validate(propDef, property);
+
+            BigDecimal propVal = ((PropertyDecimal) property).getFirstValue();
+            BigDecimal minVal = ((PropertyDecimalDefinition) propDef).getMinValue();
+            BigDecimal maxVal = ((PropertyDecimalDefinition) propDef).getMaxValue();
+
+            // check min and max
+            if (minVal != null && propVal != null && propVal.compareTo(minVal) == -1) {
+                throw new CmisConstraintException("For property with id " + propDef.getId() + " the value " + propVal
+                        + " is less than the minimum value " + minVal);
+            }
+            if (maxVal != null && propVal != null && propVal.compareTo(maxVal) == 1) {
+                throw new CmisConstraintException("For property with id " + propDef.getId() + " the value " + propVal
+                        + " is bigger than the maximum value " + maxVal);
+            }
+        }
+    }
+
+    static class PropertyValidatorString extends PropertyValidator<String> {
+
+        public void validate(PropertyDefinition<String> propDef, PropertyData<String> property) {
+
+            super.validate(propDef, property);
+
+            long maxLen = ((PropertyStringDefinition) propDef).getMaxLength() == null ? -1
+                    : ((PropertyStringDefinition) propDef).getMaxLength().longValue();
+            long len = ((PropertyData<String>) property).getFirstValue() == null ? -1
+                    : ((PropertyData<String>) property).getFirstValue().length();
+
+            // check max length
+            if (maxLen >= 0 && len >= 0 && maxLen < len) {
+                throw new CmisConstraintException("For property with id " + propDef.getId() + " the length of " + len
+                        + "is bigger than the maximum allowed length  " + maxLen);
+            }
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <T> void validateProperties(TypeDefinition typeDef, Properties properties, boolean checkMandatory) {
+
+        List<String> propDefsRequired = getMandatoryPropDefs(typeDef.getPropertyDefinitions());
+
+        for (PropertyData<?> prop : properties.getProperties().values()) {
+            String propertyId = prop.getId();
+            BaseTypeId baseTypeId = typeDef.getBaseTypeId();
+
+            if (isSystemProperty(baseTypeId, propertyId))
+                continue; // ignore system properties for validation
+
+            // Check if all properties are known in the type
+            if (!typeContainsProperty(typeDef, propertyId)) {
+                throw new CmisConstraintException("Unknown property " + propertyId + " in type " + typeDef.getId());
+            }
+
+            // check that all mandatory attributes are present
+            if (checkMandatory && propDefsRequired.contains(propertyId))
+                propDefsRequired.remove(propertyId);
+
+            // check all type specific constraints:
+            PropertyDefinition<T> propDef = getPropertyDefinition(typeDef, propertyId);
+            PropertyValidator<T> validator = createPropertyValidator(propDef);
+            validator.validate(propDef, (PropertyData<T>) prop);
+        }
+
+        if (checkMandatory && !propDefsRequired.isEmpty())
+            throw new CmisConstraintException("The following mandatory properties are missing: " + propDefsRequired);
+    }
+
+    public static void validateVersionStateForCreate(DocumentTypeDefinition typeDef, VersioningState verState) {
+        if (null == verState)
+            return;
+        if (typeDef.isVersionable() && verState.equals(VersioningState.NONE) || !typeDef.isVersionable()
+                && !verState.equals(VersioningState.NONE)) {
+            throw new CmisConstraintException("The versioning state flag is imcompatible to the type definition.");
+        }
+
+    }
+
+    public static void validateAllowedChildObjectTypes(TypeDefinition childTypeDef, List<String> allowedChildTypes) {
+
+        if (null == allowedChildTypes)
+            return; // all types are allowed
+
+        for (String allowedChildType : allowedChildTypes) {
+            if (allowedChildType.equals(childTypeDef.getId()))
+                return;
+        }
+        throw new RuntimeException("The requested type " + childTypeDef.getId() + " is not allowed in this folder");
+    }
+
+    private static List<String> getMandatoryPropDefs(Map<String, PropertyDefinition<?>> propDefs) {
+        List<String> res = new ArrayList<String>();
+        if (null != propDefs) {
+            for (PropertyDefinition<?> propDef : propDefs.values()) {
+                if (propDef.isRequired() && !isMandatorySystemProperty(propDef.getId()))
+                    res.add(propDef.getId());
+            }
+        }
+        return res;
+    }
+
+    public static boolean typeContainsProperty(TypeDefinition typeDef, String propertyId) {
+
+        Map<String, PropertyDefinition<?>> propDefs = typeDef.getPropertyDefinitions();
+        if (null == propDefs)
+            return false;
+
+        PropertyDefinition<?> propDef = propDefs.get(propertyId);
+
+        if (null == propDef)
+            return false; // unknown property id in this type
+        else
+            return true;
+    }
+
+    public static boolean typeContainsPropertyWithQueryName(TypeDefinition typeDef, String propertyQueryName) {
+
+        Map<String, PropertyDefinition<?>> propDefs = typeDef.getPropertyDefinitions();
+        if (null == propDefs)
+            return false;
+
+        for (PropertyDefinition<?> propDef : propDefs.values()) {
+            if (propDef.getQueryName().equals(propertyQueryName))
+                return true;
+        }
+        
+        return false; // unknown property query name in this type
+    }
+
+    @SuppressWarnings("unchecked")
+    private static <T> PropertyDefinition<T> getPropertyDefinition(TypeDefinition typeDef, String propertyId) {
+
+        Map<String, PropertyDefinition<?>> propDefs = typeDef.getPropertyDefinitions();
+        if (null == propDefs)
+            return null;
+
+        PropertyDefinition<?> propDef = propDefs.get(propertyId);
+
+        if (null == propDef)
+            return null; // not found
+        else
+            return (PropertyDefinition<T>) propDef;
+    }
+
+    private static boolean isSystemProperty(BaseTypeId baseTypeId, String propertyId) {
+
+        if (propertyId.equals(PropertyIds.NAME)) {
+            return true;
+        } else if (propertyId.equals(PropertyIds.OBJECT_ID)) {
+            return true;
+        } else if (propertyId.equals(PropertyIds.OBJECT_TYPE_ID)) {
+            return true;
+        } else if (propertyId.equals(PropertyIds.BASE_TYPE_ID)) {
+            return true;
+        } else if (propertyId.equals(PropertyIds.CREATED_BY)) {
+            return true;
+        } else if (propertyId.equals(PropertyIds.CREATION_DATE)) {
+            return true;
+        } else if (propertyId.equals(PropertyIds.LAST_MODIFIED_BY)) {
+            return true;
+        } else if (propertyId.equals(PropertyIds.LAST_MODIFICATION_DATE)) {
+            return true;
+        } else if (propertyId.equals(PropertyIds.CHANGE_TOKEN)) {
+            return true;
+        }
+
+        if (baseTypeId.equals(BaseTypeId.CMIS_DOCUMENT)) {
+            if (propertyId.equals(PropertyIds.IS_IMMUTABLE)) {
+                return true;
+            } else if (propertyId.equals(PropertyIds.IS_LATEST_VERSION)) {
+                return true;
+            } else if (propertyId.equals(PropertyIds.IS_MAJOR_VERSION)) {
+                return true;
+            } else if (propertyId.equals(PropertyIds.VERSION_SERIES_ID)) {
+                return true;
+            } else if (propertyId.equals(PropertyIds.IS_LATEST_MAJOR_VERSION)) {
+                return true;
+            } else if (propertyId.equals(PropertyIds.VERSION_LABEL)) {
+                return true;
+            } else if (propertyId.equals(PropertyIds.VERSION_SERIES_ID)) {
+                return true;
+            } else if (propertyId.equals(PropertyIds.IS_VERSION_SERIES_CHECKED_OUT)) {
+                return true;
+            } else if (propertyId.equals(PropertyIds.VERSION_SERIES_CHECKED_OUT_BY)) {
+                return true;
+            } else if (propertyId.equals(PropertyIds.VERSION_SERIES_CHECKED_OUT_ID)) {
+                return true;
+            } else if (propertyId.equals(PropertyIds.CHECKIN_COMMENT)) {
+                return true;
+            } else if (propertyId.equals(PropertyIds.CONTENT_STREAM_LENGTH)) {
+                return true;
+            } else if (propertyId.equals(PropertyIds.CONTENT_STREAM_MIME_TYPE)) {
+                return true;
+            } else if (propertyId.equals(PropertyIds.CONTENT_STREAM_FILE_NAME)) {
+                return true;
+            } else if (propertyId.equals(PropertyIds.CONTENT_STREAM_ID)) {
+                return true;
+            } else {
+                return false;
+            }
+        } else if (baseTypeId.equals(BaseTypeId.CMIS_FOLDER)) {
+            if (propertyId.equals(PropertyIds.PARENT_ID)) {
+                return true;
+            } else if (propertyId.equals(PropertyIds.ALLOWED_CHILD_OBJECT_TYPE_IDS)) {
+                return true;
+            } else if (propertyId.equals(PropertyIds.PATH)) {
+                return true;
+            } else {
+                return false;
+            }
+        } else if (baseTypeId.equals(BaseTypeId.CMIS_POLICY)) {
+            if (propertyId.equals(PropertyIds.SOURCE_ID)) {
+                return true;
+            } else if (propertyId.equals(PropertyIds.TARGET_ID)) {
+                return true;
+            } else {
+                return false;
+            }
+        } else { // relationship
+            if (propertyId.equals(PropertyIds.POLICY_TEXT)) {
+                return true;
+            } else {
+                return false;
+            }
+        }
+    }
+}

Added: incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/AbstractQueryConditionProcessor.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/AbstractQueryConditionProcessor.java?rev=963193&view=auto
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/AbstractQueryConditionProcessor.java (added)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/AbstractQueryConditionProcessor.java Mon Jul 12 06:41:49 2010
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.chemistry.opencmis.server.support.query;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.GregorianCalendar;
+import java.util.List;
+
+import org.antlr.runtime.ANTLRInputStream;
+import org.antlr.runtime.CharStream;
+import org.antlr.runtime.CommonTokenStream;
+import org.antlr.runtime.RecognitionException;
+import org.antlr.runtime.TokenSource;
+import org.antlr.runtime.TokenStream;
+import org.antlr.runtime.tree.CommonTree;
+import org.antlr.runtime.tree.CommonTreeNodeStream;
+import org.antlr.runtime.tree.Tree;
+import org.apache.chemistry.opencmis.server.support.query.CmisQueryWalker;
+import org.apache.chemistry.opencmis.server.support.query.CmisQlStrictParser_CmisBaseGrammar.query_return;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+public abstract class AbstractQueryConditionProcessor implements QueryConditionProcessor {
+
+    private static Log LOG = LogFactory.getLog(AbstractQueryConditionProcessor.class);
+
+    abstract public void onStartProcessing(Tree whereNode);
+    abstract public void onStopProcessing();
+    
+    // Compare operators
+    abstract public void onEquals(Tree eqNode, Tree leftNode, Tree rightNode);
+    abstract public void onNotEquals(Tree neNode, Tree leftNode, Tree rightNode);
+    abstract public void onGreaterThan(Tree gtNode, Tree leftNode, Tree rightNode);
+    abstract public void onGreaterOrEquals(Tree geNode, Tree leftNode, Tree rightNode);
+    abstract public void onLessThan(Tree ltNode, Tree leftNode, Tree rightNode);
+    abstract public void onLessOrEquals(Tree leqNode, Tree leftNode, Tree rightNode);
+
+    // Boolean operators
+    abstract public void onNot(Tree opNode, Tree leftNode);
+    abstract public void onAnd(Tree opNode, Tree leftNode, Tree rightNode);
+    abstract public void onOr(Tree opNode, Tree leftNode, Tree rightNode);
+
+    // Multi-value:
+    abstract public void onIn(Tree node, Tree colNode, Tree listNode);
+    abstract public void onNotIn(Tree node, Tree colNode, Tree listNode);
+    abstract public void onInAny(Tree node, Tree colNode, Tree listNode);
+    abstract public void onNotInAny(Tree node, Tree colNode, Tree listNode);
+    abstract public void onEqAny(Tree node, Tree literalNode, Tree colNode);
+
+    // Null comparisons:
+    abstract public void onIsNull(Tree nullNode, Tree colNode);
+    abstract public void onIsNotNull(Tree notNullNode, Tree colNode);
+
+    // String matching:
+    abstract public void onIsLike(Tree node, Tree colNode, Tree stringNode);
+    abstract public void onIsNotLike(Tree node, Tree colNode, Tree stringNode);
+
+    // Functions:
+    abstract public void onContains(Tree node, Tree colNode, Tree paramNode);
+    abstract public void onInFolder(Tree node, Tree colNode, Tree paramNode);
+    abstract public void onInTree(Tree node, Tree colNode, Tree paramNode);
+    abstract public void onScore(Tree node, Tree paramNode);
+
+    // convenience method because everybody needs this piece of code
+    static public CmisQueryWalker getWalker(String statement) throws UnsupportedEncodingException, IOException, RecognitionException {
+        CharStream input = new ANTLRInputStream(new ByteArrayInputStream(statement.getBytes("UTF-8")));
+        TokenSource lexer = new CmisQlStrictLexer(input);
+        TokenStream tokens = new CommonTokenStream(lexer);
+        CmisQlStrictParser parser = new CmisQlStrictParser(tokens);
+        CommonTree parserTree; // the ANTLR tree after parsing phase
+
+        query_return parsedStatement = parser.query();
+//        if (parser.errorMessage != null) {
+//            throw new RuntimeException("Cannot parse query: " + statement + " (" + parser.errorMessage + ")");
+//        }
+        parserTree = (CommonTree) parsedStatement.getTree();            
+
+        CommonTreeNodeStream nodes = new CommonTreeNodeStream(parserTree);
+        nodes.setTokenStream(tokens);
+        CmisQueryWalker walker = new CmisQueryWalker(nodes);
+        return walker;
+    }
+
+    // helper functions that are needed by most query tree walkers
+    
+    protected Object onLiteral(Tree node) {
+        int type = node.getType();
+        String text = node.getText();
+        switch (type) {
+        case CmisQlStrictLexer.BOOL_LIT:
+            return Boolean.parseBoolean(node.getText());
+        case CmisQlStrictLexer.NUM_LIT:
+            if (text.contains(".") || text.contains("e") || text.contains("E"))
+                return Double.parseDouble(text);
+            else    
+                return Long.parseLong(text);
+        case CmisQlStrictLexer.STRING_LIT:
+            return text.substring(1, text.length()-1);
+        case CmisQlStrictLexer.TIME_LIT:
+            GregorianCalendar gc = CalendarHelper.fromString(text.substring(text.indexOf('\'')+1, text.lastIndexOf('\'')));
+            return gc; 
+        default:
+            throw new RuntimeException("Unknown literal. " + node);
+        }
+    }
+ 
+    protected List<Object> onLiteralList(Tree node) {
+        List<Object> res = new ArrayList<Object>(node.getChildCount());
+        for (int i=0; i<node.getChildCount(); i++) {
+            Tree literal =  node.getChild(i);
+            res.add(onLiteral(literal));
+        }
+        return res;
+    }
+    
+}

Added: incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/CmisSelector.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/CmisSelector.java?rev=963193&view=auto
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/CmisSelector.java (added)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/CmisSelector.java Mon Jul 12 06:41:49 2010
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.chemistry.opencmis.server.support.query;
+
+public abstract class CmisSelector {
+    private String aliasName;      // Alias name for a column (only in SELECT part set)
+
+    public void setAliasName(String alias) {
+        aliasName = alias;
+    }
+    
+    public String getAliasName() {
+        return aliasName;
+    }
+    public abstract String getName();
+}

Added: incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/ColumnReference.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/ColumnReference.java?rev=963193&view=auto
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/ColumnReference.java (added)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/ColumnReference.java Mon Jul 12 06:41:49 2010
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.chemistry.opencmis.server.support.query;
+
+import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
+
+public class ColumnReference extends CmisSelector {
+
+    private String typeQueryName;  // type query name coming from query statement
+    private String propQueryName;  // property query name coming from query statement
+    
+    // The following fields are set when the types are resolved:
+    private String propertyId; 
+    private TypeDefinition typeDef;  
+    
+    public ColumnReference(String typeQueryName, String propQueryName) {
+        this.typeQueryName = typeQueryName;
+        this.propQueryName = propQueryName;
+    }
+
+    public ColumnReference(String propQueryName) {
+        this.typeQueryName = null;
+        this.propQueryName = propQueryName;
+    }
+       
+    public String getTypeQueryName() {
+        return typeQueryName;
+    }
+    
+    public String getPropertyQueryName() {
+        return propQueryName;
+    }
+
+    @Override
+    public String getName() {
+        return propQueryName;
+    }
+    
+    void setTypeDefinition(String propertyId, TypeDefinition typeDef) {
+        this.typeDef = typeDef;
+        this.propertyId = propertyId;
+    }
+    
+    public TypeDefinition getTypeDefinition() {
+        return typeDef;
+    }
+    
+    public String getPropertyId() {
+        return propertyId;
+    }
+    
+    public String toString() {
+        return "Column Reference for column " + propQueryName + " in type " + typeQueryName;
+    }
+}

Added: incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/FunctionReference.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/FunctionReference.java?rev=963193&view=auto
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/FunctionReference.java (added)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/FunctionReference.java Mon Jul 12 06:41:49 2010
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.chemistry.opencmis.server.support.query;
+
+public class FunctionReference extends CmisSelector {
+
+    public enum CmisQlFunction { SCORE, };
+    
+    private CmisQlFunction function;
+
+    public FunctionReference(CmisQlFunction func) {
+        this.function = func;
+    }
+
+    public CmisQlFunction getFunction() {
+        return function;
+    }
+
+    public String toString() {
+        return "FunctionReference for " + function.toString();
+    }
+
+    @Override
+    public String getName() {
+        return function.toString();
+    }
+
+}

Added: incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/QueryConditionProcessor.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/QueryConditionProcessor.java?rev=963193&view=auto
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/QueryConditionProcessor.java (added)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/QueryConditionProcessor.java Mon Jul 12 06:41:49 2010
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.chemistry.opencmis.server.support.query;
+
+import org.antlr.runtime.tree.Tree;
+
+/**
+ * An interface used by the walker when traversing the AST from the grammar.
+ * The interface consists of callback methods that are called when a rule
+ * is processed (as part of the WHERE statement)
+ * @author Jens
+ *
+ */
+public interface QueryConditionProcessor {
+    
+    void onStartProcessing(Tree whereNode);
+    void onStopProcessing();
+    
+    // Compare operators
+    void onEquals(Tree eqNode, Tree leftNode, Tree rightNode);
+    void onNotEquals(Tree neNode, Tree leftNode, Tree rightNode);
+    void onGreaterThan(Tree gtNode, Tree leftNode, Tree rightNode);
+    void onGreaterOrEquals(Tree geNode, Tree leftNode, Tree rightNode);
+    void onLessThan(Tree ltNode, Tree leftNode, Tree rightNode);
+    void onLessOrEquals(Tree leqNode, Tree leftNode, Tree rightNode);
+
+    // Boolean operators
+    void onNot(Tree opNode, Tree leftNode);
+    void onAnd(Tree opNode, Tree leftNode, Tree rightNode);
+    void onOr(Tree opNode, Tree leftNode, Tree rightNode);
+
+    // Multi-value:
+    void onIn(Tree node, Tree colNode, Tree listNode);
+    void onNotIn(Tree node, Tree colNode, Tree listNode);
+    void onInAny(Tree node, Tree colNode, Tree listNode);
+    void onNotInAny(Tree node, Tree colNode, Tree listNode);
+    void onEqAny(Tree node, Tree literalNode, Tree colNode);
+
+    // Null comparisons:
+    public void onIsNull(Tree nullNode, Tree colNode);
+    public void onIsNotNull(Tree notNullNode, Tree colNode);
+
+    // String matching:
+    void onIsLike(Tree node, Tree colNode, Tree stringNode);
+    void onIsNotLike(Tree node, Tree colNode, Tree stringNode);
+
+    // Functions:
+    void onContains(Tree node, Tree colNode, Tree paramNode);
+    void onInFolder(Tree node, Tree colNode, Tree paramNode);
+    void onInTree(Tree node, Tree colNode, Tree paramNode);
+    void onScore(Tree node, Tree paramNode);
+}

Added: incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/QueryObject.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/QueryObject.java?rev=963193&view=auto
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/QueryObject.java (added)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/QueryObject.java Mon Jul 12 06:41:49 2010
@@ -0,0 +1,524 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.chemistry.opencmis.server.support.query;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.antlr.runtime.tree.Tree;
+import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
+import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
+import org.apache.chemistry.opencmis.server.support.TypeManager;
+import org.apache.chemistry.opencmis.server.support.TypeValidator;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * QueryObject is a class used to encapsulate a CMIS query. It is created from an ANTLR
+ * parser on an incoming query string. During parsing varoius informations are collected
+ * and stored in objects suitable for evaluating the query (like selected properties,
+ * effected types and order statements. A query evaluator can use this information to
+ * perform the query and build the result.  
+ *
+ */
+public class QueryObject {
+    
+    private static Log LOG = LogFactory.getLog(QueryObject.class);
+    
+    // For error handling see: http://www.antlr.org/pipermail/antlr-interest/2008-April/027600.html
+    // select part 
+    private TypeManager typeMgr;
+    private List<CmisSelector> selectReferences = new ArrayList<CmisSelector> ();
+    private List<CmisSelector> whereReferences = new ArrayList<CmisSelector> ();
+    private List<CmisSelector> joinReferences = new ArrayList<CmisSelector> (); // --> Join not implemented yet
+    private Map<String, CmisSelector> colOrFuncAlias = new HashMap<String, CmisSelector>();
+    private QueryConditionProcessor queryProcessor;
+    
+    // from part
+    /** 
+     * map from alias name to type query name
+     */
+    private Map<String,String> froms = new LinkedHashMap<String,String>();
+
+    // where part
+    private Map<Integer, CmisSelector> columnReferences = new HashMap<Integer, CmisSelector>(); 
+
+    // order by part
+    private List<SortSpec> sortSpecs = new ArrayList<SortSpec>();
+
+    public class SortSpec {
+        private  boolean ascending;
+        private Integer colRefKey; // key in columnReferencesMap point to column descriptions
+        
+        public SortSpec(Integer key, boolean ascending) {
+            this.colRefKey = key;
+            this.ascending = ascending;
+        }
+        
+        public CmisSelector getSelector() {
+            return columnReferences.get(colRefKey);
+        }
+        
+        public boolean isAscending() {
+            return ascending;
+        }
+    };
+    
+    public QueryObject() {
+    }
+    
+    public QueryObject(TypeManager tm, QueryConditionProcessor wp) {
+        typeMgr = tm;        
+        queryProcessor = wp;
+    }
+    
+    public Map<Integer, CmisSelector> getColumnReferences() {
+        return Collections.unmodifiableMap(columnReferences);
+    }
+    
+    public CmisSelector getColumnReference (Integer token) {
+        return columnReferences.get(token);
+    }
+    
+    /////////////////////////////////////////////////////////
+    // SELECT part
+    
+    // public accessor methods
+    public List<CmisSelector> getSelectReferences() {
+        return selectReferences;
+    }
+
+    void addSelectReference(Object node, CmisSelector selRef) {
+        selectReferences.add(selRef);        
+        columnReferences.put(((Tree)node).getTokenStartIndex(), selRef);
+    }
+
+    void addAlias(String aliasName, CmisSelector aliasRef) {
+        LOG.debug("add alias: " + aliasName + " for: " + aliasRef);
+        if (colOrFuncAlias.containsKey(aliasName)) {
+            throw new CmisInvalidArgumentException("You cannot use name " + aliasName + " more than once as alias in a select.");
+        } else {
+            aliasRef.setAliasName(aliasName);
+            colOrFuncAlias.put(aliasName, aliasRef);
+        }
+    }
+    
+    CmisSelector getSelectAlias(String aliasName) {
+        return colOrFuncAlias.get(aliasName);
+    }
+
+    /////////////////////////////////////////////////////////
+    // FROM part
+
+    void addType(String aliasName, String typeQueryName) {
+        LOG.debug("add alias: " + aliasName + " for: " + typeQueryName);
+        if (froms.containsKey(aliasName)) {
+            throw new CmisInvalidArgumentException ("You cannot use name " + aliasName + " more than once as alias in a from part.");
+        } else {
+            if (null != aliasName)
+                froms.put(aliasName, typeQueryName);
+            else
+                froms.put(typeQueryName, typeQueryName);
+        }
+    }
+
+    public Map<String,String> getTypes() {
+        return Collections.unmodifiableMap(froms);
+    }
+    
+    public String getTypeQueryName(String alias) {
+        return froms.get(alias);
+    }
+    
+    public TypeDefinition getTypeDefinitionFromQueryName(String queryName) {
+        return typeMgr.getTypeByQueryName(queryName);       
+    }
+    
+    public TypeDefinition getParentType(TypeDefinition td) {
+        String parentType = td.getParentTypeId();
+        return parentType==null ? null : typeMgr.getTypeById(parentType).getTypeDefinition();
+    }
+    
+    public TypeDefinition getParentType(String typeId) {
+        TypeDefinition td = typeMgr.getTypeById(typeId).getTypeDefinition();
+        String parentType = td == null ? null : td.getParentTypeId();
+        return parentType==null ? null : typeMgr.getTypeById(parentType).getTypeDefinition();
+    }
+    
+    public TypeDefinition getMainFromName() {
+        String queryName = froms.values().iterator().next(); // as we don't support JOINS take first type
+        TypeDefinition td = getTypeDefinitionFromQueryName(queryName);
+        return td;
+    }
+    
+    /**
+     * return a map of all columns that have been requested in the SELECT
+     * part of the statement.
+     * 
+     * @return
+     *      a map with a String as a key and value. key is the query name
+     *      of the property, value is the alias if an alias was given or 
+     *      the query name otherwise.
+     */
+    public Map<String, String> getRequestedProperties() {
+        Map<String, String> res = new HashMap<String, String> ();
+        for (CmisSelector sel : selectReferences) {
+            if (sel instanceof ColumnReference) {
+                ColumnReference colRef = (ColumnReference) sel;
+                String key = colRef.getPropertyId();
+                if (null == key)
+                    key = colRef.getPropertyQueryName(); // happens for *
+                String propDescr = colRef.getAliasName() == null ? colRef.getPropertyQueryName() : colRef.getAliasName();
+                res.put(key, propDescr);
+            }
+        }
+        return res;
+    }
+    
+    /**
+     * return a map of all functions that have been requested in the SELECT
+     * part of the statement.
+     * 
+     * @return
+     *      a map with a String as a key and value. key is the function name
+     *      of the property, value is the alias if an alias was given or 
+     *      the function name otherwise.
+     */
+    public Map<String, String> getRequestedFuncs() {
+        Map<String, String> res = new HashMap<String, String> ();
+        for (CmisSelector sel : selectReferences) {
+            if (sel instanceof FunctionReference) {
+                FunctionReference funcRef = (FunctionReference) sel;
+                String propDescr = funcRef.getAliasName() == null ? funcRef.getName() : funcRef.getAliasName();
+                res.put(funcRef.getName(), propDescr);
+            }
+        }
+        return res;
+    }
+    
+    /////////////////////////////////////////////////////////
+    // JOINS
+    
+    void addJoinReference(Object node, CmisSelector reference) {
+        columnReferences.put(((Tree)node).getTokenStartIndex(), reference);
+        joinReferences.add(reference);
+    }
+    
+    public List<CmisSelector> getJoinReferences() {
+        return Collections.unmodifiableList(joinReferences);
+    }
+
+    
+    /////////////////////////////////////////////////////////
+    // WHERE part
+    
+    void addWhereReference(Object node, CmisSelector reference) {
+        LOG.debug("add node to where: " + System.identityHashCode(node));
+
+        columnReferences.put(((Tree)node).getTokenStartIndex(), reference);
+        whereReferences.add(reference);
+    }
+    
+    public List<CmisSelector> getWhereReferences() {
+        return Collections.unmodifiableList(whereReferences);
+    }
+
+    
+    /////////////////////////////////////////////////////////
+    // ORDER_BY part
+    
+    public List<SortSpec> getOrderBys() {
+        return Collections.unmodifiableList(sortSpecs);
+    }
+    
+    public void addSortCriterium(Tree node, ColumnReference colRef, boolean ascending) {
+        LOG.debug("addSortCriterium: " + colRef + " ascending: " + ascending);
+        columnReferences.put(node.getTokenStartIndex(), colRef);
+        sortSpecs.add(new SortSpec(node.getTokenStartIndex(), ascending));
+    }
+
+    /////////////////////////////////////////////////////////
+    // resolve types after first pass traversing the AST is complete
+    
+    public void resolveTypes() {
+        LOG.debug("First pass of query traversal is complete, resolving types");
+        if (null == typeMgr)
+            return;
+        
+        // First resolve all alias names defined in SELECT:
+        for (CmisSelector alias : colOrFuncAlias.values()) {
+            if (alias instanceof ColumnReference) { 
+                ColumnReference colRef = ((ColumnReference) alias);
+                resolveTypeForAlias(colRef);
+            }
+        }
+        
+        // Then replace all aliases used somewhere by their resolved column reference:
+        for (Integer obj : columnReferences.keySet()) {
+            CmisSelector selector = columnReferences.get(obj);
+            String key = selector.getName();
+            if (colOrFuncAlias.containsKey(key)) { // it is an alias
+              CmisSelector resolvedReference = colOrFuncAlias.get(key);
+              columnReferences.put(obj, resolvedReference);
+                // Note: ^ This may replace the value in the map with the same value, but this does not harm.
+                //       Otherwise we need to check if it is resolved or not which causes two more ifs: 
+//                if (selector instanceof ColumnReference) {
+//                    ColumnReference colRef = ((ColumnReference) selector);
+//                    if (colRef.getTypeDefinition() == null) // it is not yet resolved
+//                        // replace unresolved column reference by resolved on from alias map
+//                        columnReferences.put(obj, colOrFuncAlias.get(selector.getAliasName()));
+//                } else
+//                    columnReferences.put(obj, colOrFuncAlias.get(selector.getAliasName()));
+              if (whereReferences.remove(selector))
+                  whereReferences.add(resolvedReference); // replace unresolved by resolved reference
+              if (joinReferences.remove(selector))
+                  joinReferences.add(resolvedReference); // replace unresolved by resolved reference
+            }
+        }
+        
+        // The replace all remaining column references not using an alias
+        for (CmisSelector select : columnReferences.values()) {
+            // ignore functions here
+            if (select instanceof ColumnReference) { 
+                ColumnReference colRef = ((ColumnReference) select);
+                if (colRef.getTypeDefinition() == null) { // not yet resolved
+                    if (colRef.getTypeQueryName() == null) {
+                        // unqualified select: SELECT p FROM
+                        resolveTypeForColumnReference(colRef);
+                    } else {
+                        // qualified select: SELECT t.p FROM
+                        validateColumnReferenceAndResolveType(colRef);
+                    }
+                }
+            }
+        }
+    }
+    
+    
+    private void resolveTypeForAlias(ColumnReference colRef) {
+        String aliasName = colRef.getAliasName();
+        
+        if (colOrFuncAlias.containsKey(aliasName)) {
+            CmisSelector selector = colOrFuncAlias.get(aliasName);
+            if (selector instanceof ColumnReference) {
+                colRef = (ColumnReference) selector; // alias target
+                if (colRef.getTypeQueryName() == null) {
+                    // unqualified select: SELECT p FROM
+                    resolveTypeForColumnReference(colRef);
+                } else {
+                    // qualified select: SELECT t.p FROM
+                    validateColumnReferenceAndResolveType(colRef);
+                }
+            }
+            // else --> ignore FunctionReference
+        }
+    }
+        
+        
+    // for a select x from y, z ... find the type in type manager for x
+    private void resolveTypeForColumnReference(ColumnReference colRef) {
+        String propName = colRef.getPropertyQueryName();
+        boolean isStar = propName.equals("*");
+        
+        // it is property query name without a type, so find type
+        int noFound = 0;
+        TypeDefinition tdFound = null;
+        for (String typeQueryName : froms.values()) {
+            TypeDefinition td = typeMgr.getTypeByQueryName(typeQueryName);
+            if (null == td) 
+                throw new CmisInvalidArgumentException(typeQueryName + " is neither a type query name nor an alias.");
+            else if (isStar) {
+                ++noFound;
+                tdFound = null;
+            } else if (TypeValidator.typeContainsPropertyWithQueryName(td, propName)) {
+                ++noFound;
+                tdFound = td;
+            }
+        }
+        if (noFound == 0)
+            throw new CmisInvalidArgumentException(propName + " is not a property query name in any of the types in from ...");
+        else if (noFound > 1 && !isStar)
+            throw new CmisInvalidArgumentException(propName + " is not a unique property query name within the types in from ...");
+        else {
+            if (null != tdFound) // can be null in select * from t1 JOIN t2....
+                validateColumnReferenceAndResolveType(tdFound, colRef);
+        }
+    }
+
+    // for a select x.y from x ... check that x has property y and that x is in from
+    private void validateColumnReferenceAndResolveType(ColumnReference colRef) {
+        
+        String typeQueryName = getReferencedTypeQueryName(colRef.getTypeQueryName()); // either same name or mapped alias
+        TypeDefinition td = typeMgr.getTypeByQueryName(typeQueryName);
+        if (null == td) 
+            throw new CmisInvalidArgumentException(colRef.getTypeQueryName() + " is neither a type query name nor an alias.");
+        
+        validateColumnReferenceAndResolveType(td, colRef);
+    }
+
+    private void validateColumnReferenceAndResolveType(TypeDefinition td, ColumnReference colRef) {
+        
+        // type found, check if property exists
+        boolean hasProp;
+        if (colRef.getPropertyQueryName().equals("*"))
+            hasProp = true;
+        else
+            hasProp = TypeValidator.typeContainsPropertyWithQueryName(td, colRef.getPropertyQueryName());
+        if (!hasProp)
+            throw new CmisInvalidArgumentException(colRef.getPropertyQueryName() + " is not a valid property query name in type " + td.getId() + ".");
+        
+        colRef.setTypeDefinition(typeMgr.getPropertyIdForQueryName(td, colRef.getPropertyQueryName()), td);
+    }
+    
+    // return type query name for a referenced column (which can be the name itself or an alias
+    private String getReferencedTypeQueryName(String typeQueryNameOrAlias) {
+        String typeQueryName = froms.get(typeQueryNameOrAlias);
+        if (null == typeQueryName) {
+            // if an alias was defined but still the original is used we have to search case: SELECT T.p FROM T AS TAlias 
+            for (String tqn : froms.values()) {
+              if (typeQueryNameOrAlias.equals(tqn))
+                  return tqn;
+            }
+            return null;
+        } else
+            return typeQueryName;
+    }
+    
+    
+    public void processWhereClause(Tree whereRoot)
+    {
+        if (null!=queryProcessor && null != whereRoot) {
+            queryProcessor.onStartProcessing(whereRoot);
+            processWhereNode(whereRoot);
+            queryProcessor.onStopProcessing();
+        }
+    }
+    
+    private void processWhereNode(Tree root) {
+        int count = root.getChildCount();
+        for (int i=0; i<count; i++) {
+            Tree child = root.getChild(i);
+            processWhereNode(child);
+            evalWhereNode(child); // recursive descent
+        }
+    }
+    
+    /////////////////////////////////////////////////////////
+    // Processing the WHERE clause
+    
+    private void evalWhereNode(Tree node) {
+        // Ensure that we receive only valid tokens and nodes in the where clause:
+            LOG.debug("evaluating node: " + node.toString());
+            switch (node.getType()) {
+            case CmisQlStrictLexer.WHERE:;
+                break; // ignore
+            case CmisQlStrictLexer.EQ:
+                queryProcessor.onEquals(node, node.getChild(0), node.getChild(1));
+                break;
+            case CmisQlStrictLexer.NEQ:
+                queryProcessor.onNotEquals(node, node.getChild(0), node.getChild(1));
+                break;
+            case CmisQlStrictLexer.GT:
+                queryProcessor.onGreaterThan(node, node.getChild(0), node.getChild(1));
+                break;
+            case CmisQlStrictLexer.GTEQ:
+                queryProcessor.onGreaterOrEquals(node, node.getChild(0), node.getChild(1));
+                break;
+            case CmisQlStrictLexer.LT:
+                queryProcessor.onLessThan(node, node.getChild(0), node.getChild(1));
+                break;
+            case CmisQlStrictLexer.LTEQ:
+                queryProcessor.onLessOrEquals(node, node.getChild(0), node.getChild(1));
+                break;
+                
+            case CmisQlStrictLexer.NOT:
+                queryProcessor.onNot(node, node.getChild(0));
+                break;
+            case CmisQlStrictLexer.AND:
+                queryProcessor.onAnd(node, node.getChild(0), node.getChild(1));
+                break;
+            case CmisQlStrictLexer.OR:
+                queryProcessor.onOr(node, node.getChild(0), node.getChild(1));
+                break;
+                
+            // Multi-value:
+            case CmisQlStrictLexer.IN:
+                queryProcessor.onIn(node, node.getChild(0), node.getChild(1));
+                break;
+            case CmisQlStrictLexer.NOT_IN:
+                queryProcessor.onNotIn(node, node.getChild(0), node.getChild(1));
+                break;
+            case CmisQlStrictLexer.IN_ANY:
+                queryProcessor.onInAny(node, node.getChild(0), node.getChild(1));
+                break;
+            case CmisQlStrictLexer.NOT_IN_ANY:
+                queryProcessor.onNotInAny(node, node.getChild(0), node.getChild(1));
+                break;
+            case CmisQlStrictLexer.EQ_ANY:
+                queryProcessor.onEqAny(node, node.getChild(0), node.getChild(1));
+                break;
+
+            // Null comparisons:
+            case CmisQlStrictLexer.IS_NULL:
+                queryProcessor.onIsNull(node, node.getChild(0));
+                break;
+            case CmisQlStrictLexer.IS_NOT_NULL:
+                queryProcessor.onIsNotNull(node, node.getChild(0));
+                break;
+
+                // String matching
+            case CmisQlStrictLexer.LIKE:
+                queryProcessor.onIsLike(node, node.getChild(0), node.getChild(1));
+                break;
+            case CmisQlStrictLexer.NOT_LIKE:
+                queryProcessor.onIsNotLike(node, node.getChild(0), node.getChild(1));
+                break;
+
+                // Functions
+            case CmisQlStrictLexer.CONTAINS:
+                if (node.getChildCount()==1)
+                    queryProcessor.onContains(node, null, node.getChild(0));
+                else
+                    queryProcessor.onContains(node, node.getChild(0), node.getChild(1));
+                break;
+            case CmisQlStrictLexer.IN_FOLDER:
+                if (node.getChildCount()==1)
+                    queryProcessor.onInFolder(node, null, node.getChild(0));
+                else
+                    queryProcessor.onInFolder(node, node.getChild(0), node.getChild(1));
+                break;
+            case CmisQlStrictLexer.IN_TREE:
+                if (node.getChildCount()==1)
+                    queryProcessor.onInTree(node, null, node.getChild(0));
+                else
+                    queryProcessor.onInTree(node, node.getChild(0), node.getChild(1));
+                break;
+            case CmisQlStrictLexer.SCORE:
+                queryProcessor.onScore(node, node.getChild(0));
+                break;
+                
+            default:
+               // do nothing;
+            }
+    }
+}