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