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;
+ }
+ }
+}