You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@chemistry.apache.org by fg...@apache.org on 2010/07/29 19:13:30 UTC
svn commit: r980513 [14/15] - in
/incubator/chemistry/opencmis/trunk/chemistry-opencmis-server:
chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/dummy/
chemistry-opencmis-server-bindings/src/main/java/org/apach...
Modified: 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=980513&r1=980512&r2=980513&view=diff
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/QueryConditionProcessor.java (original)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/QueryConditionProcessor.java Thu Jul 29 17:13:28 2010
@@ -1,68 +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);
-}
+/*
+ * 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);
+}
Propchange: incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/QueryConditionProcessor.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: 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=980513&r1=980512&r2=980513&view=diff
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/QueryObject.java (original)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/QueryObject.java Thu Jul 29 17:13:28 2010
@@ -1,524 +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;
- }
- }
-}
+/*
+ * 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;
+ }
+ }
+}
Propchange: incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/QueryObject.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/test/gunit/org/apache/chemistry/opencmis/server/support/query/CMISQL.testsuite
------------------------------------------------------------------------------
svn:eol-style = native
Modified: incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/test/java/org/apache/chemistry/opencmis/server/support/query/AbstractParserTst.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/test/java/org/apache/chemistry/opencmis/server/support/query/AbstractParserTst.java?rev=980513&r1=980512&r2=980513&view=diff
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/test/java/org/apache/chemistry/opencmis/server/support/query/AbstractParserTst.java (original)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/test/java/org/apache/chemistry/opencmis/server/support/query/AbstractParserTst.java Thu Jul 29 17:13:28 2010
@@ -1,196 +1,196 @@
-/*
- * 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 static org.junit.Assert.fail;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
-
-import org.antlr.runtime.ANTLRStringStream;
-import org.antlr.runtime.CharStream;
-import org.antlr.runtime.CommonTokenStream;
-import org.antlr.runtime.Lexer;
-import org.antlr.runtime.TokenStream;
-import org.antlr.runtime.tree.CommonTree;
-import org.antlr.stringtemplate.StringTemplate;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * This class is clone of org.antlr.gunit.gUnitBase class adapted to Java style
- * Because the original class can't deal with composite grammar this is a replacement
- * working around this antlr bug.
- *
- */
-public class AbstractParserTst{
-
- private static Log log = LogFactory.getLog(AbstractParserTst.class);
-
- protected String superGrammarName;
- Class<?> lexer;
- Class<?> parser;
- protected String treeParserPath;
-
- protected void setUp(Class<?> lexerClass, Class<?> parserClass, String baseGrammar) throws Exception {
- lexer = lexerClass;
- parser = parserClass;
- this.superGrammarName = baseGrammar;
- }
-
- protected void tearDown() throws Exception {
- }
-
- protected void testLexerOk(String rule, String statement) throws Exception {
- // test input: "a"
- try {
- Object retval = execLexer(rule, statement, false);
- log.debug("testing rule " + rule + " parsed to: " + retval);
- } catch (Exception e) {
- fail("testing rule " + rule + ": " + e.toString());
- }
- }
-
- protected void testLexerFail(String rule, String statement) throws Exception {
- // test input: "a"
- try {
- Object retval = execLexer(rule, statement, false);
- fail("testing rule should fail " + rule);
- } catch (Exception e) {
- log.debug("testing rule " + rule + " parsed with exception: " + e);
- }
- }
-
- protected void testParserOk(String rule, String statement) throws Exception {
- try {
- Object retval = execParser(rule, statement, false);
- log.debug("testing rule " + rule + " parsed to: " + retval);
- } catch (Exception e) {
- fail("testing rule "+rule + " failed: " + e.toString());
- }
- }
-
- protected void testParserFail(String rule, String statement) throws Exception {
- try {
- Object retval = execParser(rule, statement, false);
- fail("testing rule should fail " + rule);
- } catch (Exception e) {
- log.debug("testing rule "+rule + " failed: " + e.toString());
- }
- }
-
- protected void testParser(String rule, String statement, String expectedResult) throws Exception {
- try {
- Object actual = execParser(rule, statement, false);
- log.debug("testing rule " + rule + " parsed to: " + actual);
- } catch (Exception e) {
- fail("testing rule " + rule + " failed: " + e);
- }
- }
-
-
- // Invoke target lexer.rule
- public String execLexer(String testRuleName, String testInput, boolean isFile) throws Exception {
- String result = null;
- CharStream input;
- /** Set up ANTLR input stream based on input source, file or String */
- input = new ANTLRStringStream(testInput);
-
- /** Use Reflection to create instances of lexer and parser */
- Class<?>[] lexArgTypes = new Class[]{CharStream.class}; // assign type to lexer's args
- Constructor<?> lexConstructor = lexer.getConstructor(lexArgTypes);
- Object[] lexArgs = new Object[]{input}; // assign value to lexer's args
- Object lexObj = lexConstructor.newInstance(lexArgs); // makes new instance of lexer
-
- Method ruleName = lexer.getMethod("m"+testRuleName, new Class[0]);
-
- /** Invoke lexer rule, and get the current index in CharStream */
- ruleName.invoke(lexObj, new Object[0]);
- Method ruleName2 = lexer.getMethod("getCharIndex", new Class[0]);
- int currentIndex = (Integer) ruleName2.invoke(lexObj, new Object[0]);
- if ( currentIndex!=input.size() ) {
- throw new RuntimeException("extra text found, '"+input.substring(currentIndex, input.size()-1)+"'");
-// System.out.println("extra text found, '"+input.substring(currentIndex, input.size()-1)+"'");
- }
-
- return result;
- }
-
- // Invoke target parser.rule
- public Object execParser(String testRuleName, String testInput, boolean isFile) throws Exception {
- String result = null;
- CharStream input;
- /** Set up ANTLR input stream based on input source, file or String */
- input = new ANTLRStringStream(testInput);
-
- /** Use Reflection to create instances of lexer and parser */
- Class<?>[] lexArgTypes = new Class[]{CharStream.class}; // assign type to lexer's args
- Constructor<?> lexConstructor = lexer.getConstructor(lexArgTypes);
- Object[] lexArgs = new Object[]{input}; // assign value to lexer's args
- Object lexObj = lexConstructor.newInstance(lexArgs); // makes new instance of lexer
-
- CommonTokenStream tokens = new CommonTokenStream((Lexer) lexObj);
- Class<?>[] parArgTypes = new Class[]{TokenStream.class}; // assign type to parser's args
- Constructor<?> parConstructor = parser.getConstructor(parArgTypes);
- Object[] parArgs = new Object[]{tokens}; // assign value to parser's args
- Object parObj = parConstructor.newInstance(parArgs); // makes new instance of parser
-
- Method ruleName = parser.getMethod(testRuleName);
-
- /** Invoke grammar rule, and store if there is a return value */
- Object ruleReturn = ruleName.invoke(parObj);
-
- /** If rule has return value, determine if it contains an AST or a ST */
- if ( ruleReturn!=null ) {
- if ( ruleReturn.getClass().toString().indexOf(testRuleName+"_return")>0 ) {
- try { // NullPointerException may happen here...
- String classPath = parser.getName();
- if (null != superGrammarName)
- classPath += "_" + superGrammarName;
- Class<?> _return = Class.forName(classPath+"$"+testRuleName+"_return");
- Method[] methods = _return.getDeclaredMethods();
- for(Method method : methods) {
- if ( method.getName().equals("getTree") ) {
- Method returnName = _return.getMethod("getTree");
- CommonTree tree = (CommonTree) returnName.invoke(ruleReturn);
- result = tree.toStringTree();
- }
- else if ( method.getName().equals("getTemplate") ) {
- Method returnName = _return.getMethod("getTemplate");
- StringTemplate st = (StringTemplate) returnName.invoke(ruleReturn);
- result = st.toString();
- }
- }
- }
- catch(Exception e) {
- throw(e); // Note: If any exception occurs, the test is viewed as failed.
- }
- }
- }
-
-
- /** Invalid input */
- if ( tokens.index()!=tokens.size() ) {
- throw new RuntimeException("Invalid input.");
- }
-
- return result;
- }
-
- }
+/*
+ * 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 static org.junit.Assert.fail;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+import org.antlr.runtime.ANTLRStringStream;
+import org.antlr.runtime.CharStream;
+import org.antlr.runtime.CommonTokenStream;
+import org.antlr.runtime.Lexer;
+import org.antlr.runtime.TokenStream;
+import org.antlr.runtime.tree.CommonTree;
+import org.antlr.stringtemplate.StringTemplate;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * This class is clone of org.antlr.gunit.gUnitBase class adapted to Java style
+ * Because the original class can't deal with composite grammar this is a replacement
+ * working around this antlr bug.
+ *
+ */
+public class AbstractParserTst{
+
+ private static Log log = LogFactory.getLog(AbstractParserTst.class);
+
+ protected String superGrammarName;
+ Class<?> lexer;
+ Class<?> parser;
+ protected String treeParserPath;
+
+ protected void setUp(Class<?> lexerClass, Class<?> parserClass, String baseGrammar) throws Exception {
+ lexer = lexerClass;
+ parser = parserClass;
+ this.superGrammarName = baseGrammar;
+ }
+
+ protected void tearDown() throws Exception {
+ }
+
+ protected void testLexerOk(String rule, String statement) throws Exception {
+ // test input: "a"
+ try {
+ Object retval = execLexer(rule, statement, false);
+ log.debug("testing rule " + rule + " parsed to: " + retval);
+ } catch (Exception e) {
+ fail("testing rule " + rule + ": " + e.toString());
+ }
+ }
+
+ protected void testLexerFail(String rule, String statement) throws Exception {
+ // test input: "a"
+ try {
+ Object retval = execLexer(rule, statement, false);
+ fail("testing rule should fail " + rule);
+ } catch (Exception e) {
+ log.debug("testing rule " + rule + " parsed with exception: " + e);
+ }
+ }
+
+ protected void testParserOk(String rule, String statement) throws Exception {
+ try {
+ Object retval = execParser(rule, statement, false);
+ log.debug("testing rule " + rule + " parsed to: " + retval);
+ } catch (Exception e) {
+ fail("testing rule "+rule + " failed: " + e.toString());
+ }
+ }
+
+ protected void testParserFail(String rule, String statement) throws Exception {
+ try {
+ Object retval = execParser(rule, statement, false);
+ fail("testing rule should fail " + rule);
+ } catch (Exception e) {
+ log.debug("testing rule "+rule + " failed: " + e.toString());
+ }
+ }
+
+ protected void testParser(String rule, String statement, String expectedResult) throws Exception {
+ try {
+ Object actual = execParser(rule, statement, false);
+ log.debug("testing rule " + rule + " parsed to: " + actual);
+ } catch (Exception e) {
+ fail("testing rule " + rule + " failed: " + e);
+ }
+ }
+
+
+ // Invoke target lexer.rule
+ public String execLexer(String testRuleName, String testInput, boolean isFile) throws Exception {
+ String result = null;
+ CharStream input;
+ /** Set up ANTLR input stream based on input source, file or String */
+ input = new ANTLRStringStream(testInput);
+
+ /** Use Reflection to create instances of lexer and parser */
+ Class<?>[] lexArgTypes = new Class[]{CharStream.class}; // assign type to lexer's args
+ Constructor<?> lexConstructor = lexer.getConstructor(lexArgTypes);
+ Object[] lexArgs = new Object[]{input}; // assign value to lexer's args
+ Object lexObj = lexConstructor.newInstance(lexArgs); // makes new instance of lexer
+
+ Method ruleName = lexer.getMethod("m"+testRuleName, new Class[0]);
+
+ /** Invoke lexer rule, and get the current index in CharStream */
+ ruleName.invoke(lexObj, new Object[0]);
+ Method ruleName2 = lexer.getMethod("getCharIndex", new Class[0]);
+ int currentIndex = (Integer) ruleName2.invoke(lexObj, new Object[0]);
+ if ( currentIndex!=input.size() ) {
+ throw new RuntimeException("extra text found, '"+input.substring(currentIndex, input.size()-1)+"'");
+// System.out.println("extra text found, '"+input.substring(currentIndex, input.size()-1)+"'");
+ }
+
+ return result;
+ }
+
+ // Invoke target parser.rule
+ public Object execParser(String testRuleName, String testInput, boolean isFile) throws Exception {
+ String result = null;
+ CharStream input;
+ /** Set up ANTLR input stream based on input source, file or String */
+ input = new ANTLRStringStream(testInput);
+
+ /** Use Reflection to create instances of lexer and parser */
+ Class<?>[] lexArgTypes = new Class[]{CharStream.class}; // assign type to lexer's args
+ Constructor<?> lexConstructor = lexer.getConstructor(lexArgTypes);
+ Object[] lexArgs = new Object[]{input}; // assign value to lexer's args
+ Object lexObj = lexConstructor.newInstance(lexArgs); // makes new instance of lexer
+
+ CommonTokenStream tokens = new CommonTokenStream((Lexer) lexObj);
+ Class<?>[] parArgTypes = new Class[]{TokenStream.class}; // assign type to parser's args
+ Constructor<?> parConstructor = parser.getConstructor(parArgTypes);
+ Object[] parArgs = new Object[]{tokens}; // assign value to parser's args
+ Object parObj = parConstructor.newInstance(parArgs); // makes new instance of parser
+
+ Method ruleName = parser.getMethod(testRuleName);
+
+ /** Invoke grammar rule, and store if there is a return value */
+ Object ruleReturn = ruleName.invoke(parObj);
+
+ /** If rule has return value, determine if it contains an AST or a ST */
+ if ( ruleReturn!=null ) {
+ if ( ruleReturn.getClass().toString().indexOf(testRuleName+"_return")>0 ) {
+ try { // NullPointerException may happen here...
+ String classPath = parser.getName();
+ if (null != superGrammarName)
+ classPath += "_" + superGrammarName;
+ Class<?> _return = Class.forName(classPath+"$"+testRuleName+"_return");
+ Method[] methods = _return.getDeclaredMethods();
+ for(Method method : methods) {
+ if ( method.getName().equals("getTree") ) {
+ Method returnName = _return.getMethod("getTree");
+ CommonTree tree = (CommonTree) returnName.invoke(ruleReturn);
+ result = tree.toStringTree();
+ }
+ else if ( method.getName().equals("getTemplate") ) {
+ Method returnName = _return.getMethod("getTemplate");
+ StringTemplate st = (StringTemplate) returnName.invoke(ruleReturn);
+ result = st.toString();
+ }
+ }
+ }
+ catch(Exception e) {
+ throw(e); // Note: If any exception occurs, the test is viewed as failed.
+ }
+ }
+ }
+
+
+ /** Invalid input */
+ if ( tokens.index()!=tokens.size() ) {
+ throw new RuntimeException("Invalid input.");
+ }
+
+ return result;
+ }
+
+ }
Propchange: incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/test/java/org/apache/chemistry/opencmis/server/support/query/AbstractParserTst.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/test/java/org/apache/chemistry/opencmis/server/support/query/TestParserExt.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/test/java/org/apache/chemistry/opencmis/server/support/query/TestParserExt.java?rev=980513&r1=980512&r2=980513&view=diff
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/test/java/org/apache/chemistry/opencmis/server/support/query/TestParserExt.java (original)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/test/java/org/apache/chemistry/opencmis/server/support/query/TestParserExt.java Thu Jul 29 17:13:28 2010
@@ -1,67 +1,67 @@
-/*
- * 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.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-public class TestParserExt extends AbstractParserTst {
-
- private static Log log = LogFactory.getLog(TestParserStrict.class);
-
- @Before
- public void setUp() throws Exception {
- super.setUp(CmisQlStrictLexer.class, CmisQlExtParser.class, null);
- }
-
- @After
- public void tearDown() throws Exception {
- super.tearDown();
- }
-
- @Test
- public void test_predicate1() throws Exception {
- testParser("value_expression", "LOWER(foo)", "(FUNC LOWER (COL foo))");
- }
-
- @Test
- public void test_query1() throws Exception {
- testParser("query", "SELECT DISTINCT a, b, c FROM Document", "(SELECT DISTINCT (LIST (COL a) (COL b) (COL c)) (FROM (TABLE Document)))");
- }
-
- @Test
- public void test_query2() throws Exception {
- testParserOk("query",
- "SELECT Y.CLAIM_NUM, X.PROPERTY_ADDRESS, Y.DAMAGE_ESTIMATES " +
- "FROM POLICY AS X JOIN CLAIMS AS Y ON X.POLICY_NUM = Y.POLICY_NUM " +
- " WHERE ( 100000 <= ANY Y.DAMAGE_ESTIMATES ) AND ( Y.CAUSE NOT LIKE '%Katrina%' )");
- }
-
-
- @Test
- public void test_query3() throws Exception {
- testParserOk("query",
- "SELECT OBJECT_ID, SCORE() AS X, DESTINATION, DEPARTURE_DATES " +
- "FROM TRAVEL_BROCHURE " +
- "WHERE ( CONTAINS('CARIBBEAN CENTRAL AMERICA CRUISE TOUR') ) AND( '2010-1-1' < ANY DEPARTURE_DATES )");
- }
-}
+/*
+ * 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.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestParserExt extends AbstractParserTst {
+
+ private static Log log = LogFactory.getLog(TestParserStrict.class);
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp(CmisQlStrictLexer.class, CmisQlExtParser.class, null);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ @Test
+ public void test_predicate1() throws Exception {
+ testParser("value_expression", "LOWER(foo)", "(FUNC LOWER (COL foo))");
+ }
+
+ @Test
+ public void test_query1() throws Exception {
+ testParser("query", "SELECT DISTINCT a, b, c FROM Document", "(SELECT DISTINCT (LIST (COL a) (COL b) (COL c)) (FROM (TABLE Document)))");
+ }
+
+ @Test
+ public void test_query2() throws Exception {
+ testParserOk("query",
+ "SELECT Y.CLAIM_NUM, X.PROPERTY_ADDRESS, Y.DAMAGE_ESTIMATES " +
+ "FROM POLICY AS X JOIN CLAIMS AS Y ON X.POLICY_NUM = Y.POLICY_NUM " +
+ " WHERE ( 100000 <= ANY Y.DAMAGE_ESTIMATES ) AND ( Y.CAUSE NOT LIKE '%Katrina%' )");
+ }
+
+
+ @Test
+ public void test_query3() throws Exception {
+ testParserOk("query",
+ "SELECT OBJECT_ID, SCORE() AS X, DESTINATION, DEPARTURE_DATES " +
+ "FROM TRAVEL_BROCHURE " +
+ "WHERE ( CONTAINS('CARIBBEAN CENTRAL AMERICA CRUISE TOUR') ) AND( '2010-1-1' < ANY DEPARTURE_DATES )");
+ }
+}
Propchange: incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/test/java/org/apache/chemistry/opencmis/server/support/query/TestParserExt.java
------------------------------------------------------------------------------
svn:eol-style = native