You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@chemistry.apache.org by je...@apache.org on 2010/06/14 20:51:25 UTC

svn commit: r954587 [2/4] - in /incubator/chemistry/opencmis/trunk: chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/main/java/org/apache/chemistry/opencmis/commons/impl/dataobjects/ chemistry-opencmis-server/chemistry-opencmis-server-inm...

Added: incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/query/InMemoryQueryProcessor.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/query/InMemoryQueryProcessor.java?rev=954587&view=auto
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/query/InMemoryQueryProcessor.java (added)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/query/InMemoryQueryProcessor.java Mon Jun 14 18:51:24 2010
@@ -0,0 +1,574 @@
+/*
+ * 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.inmemory.query;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.GregorianCalendar;
+import java.util.List;
+import java.util.Map;
+
+import org.antlr.runtime.tree.Tree;
+import org.apache.chemistry.opencmis.commons.data.ObjectData;
+import org.apache.chemistry.opencmis.commons.data.ObjectList;
+import org.apache.chemistry.opencmis.commons.data.PropertyData;
+import org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition;
+import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
+import org.apache.chemistry.opencmis.commons.enums.Cardinality;
+import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships;
+import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectListImpl;
+import org.apache.chemistry.opencmis.inmemory.TypeManager;
+import org.apache.chemistry.opencmis.inmemory.storedobj.api.StoredObject;
+import org.apache.chemistry.opencmis.inmemory.types.PropertyCreationHelper;
+import org.apache.chemistry.opencmis.server.support.query.CalendarHelper;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * A processor for a CMIS query for the In-Memory server. During tree traversal conditions
+ * are checked against the data contained in the central hash map with all objects. In a first 
+ * pass one time setup is performed, in a custom walk across the query expression tree an object
+ * is checked if it matches. In case of a match it is appended to a list of matching objects.
+ * 
+ * @author Jens
+ *
+ */
+public class InMemoryQueryProcessor implements IQueryConditionProcessor {
+
+    private static Log LOG = LogFactory.getLog(InMemoryQueryProcessor.class);
+    
+    private List<StoredObject> matches = new ArrayList<StoredObject>();
+    private QueryObject queryObj;
+    private Tree whereTree;
+    
+    public InMemoryQueryProcessor() {
+    }
+    
+    public void setQueryObject(QueryObject qo) {
+        queryObj = qo;
+    }
+    
+    public void onStartProcessing(Tree node) {
+        // log.debug("onStartProcessing()");
+        // checkRoot(node);
+        whereTree = node;
+    }
+
+    public void onStopProcessing() {
+        // log.debug("onStopProcessing()");
+    }
+
+    /**
+     * Check for each object contained in the in-memory repository if it matches the current query
+     * expression. If yes add it to the list of matched objects.
+     * 
+     * @param so
+     *      object stored in the in-memory repository
+     */
+    public void checkMatch(StoredObject so) {
+        // log.debug("checkMatch() for object: " + so.getId());
+        match(so);
+    }
+
+    public ObjectList buildResultList(TypeManager tm, String user, 
+            Boolean includeAllowableActions, IncludeRelationships includeRelationships, String renditionFilter,
+            BigInteger maxItems, BigInteger skipCount) {
+        // TODO sort according to order by criteria
+        ObjectListImpl res = new ObjectListImpl();
+        List<ObjectData> objDataList = new ArrayList<ObjectData>();
+        Map<String, String> props = queryObj.getRequestedProperties();
+        Map<String, String> funcs = queryObj.getRequestedFuncs();
+        for (StoredObject so : matches) {
+            TypeDefinition td = tm.getTypeById(so.getTypeId()).getTypeDefinition();
+            ObjectData od = PropertyCreationHelper.getObjectDataQueryResult(td, so, user, 
+                    props, funcs, includeAllowableActions, includeRelationships, renditionFilter);
+            
+            objDataList.add(od); 
+        }
+        res.setObjects(objDataList);
+        res.setNumItems(BigInteger.valueOf(objDataList.size()));
+        res.setHasMoreItems(false);
+        return res;
+    }
+    
+    private boolean typeMatches(TypeDefinition td, StoredObject so) {
+        String typeId = so.getTypeId();
+        while (typeId != null) {
+            if (typeId.equals(td.getId())) {
+                return true;
+            }
+            // check parent type
+            TypeDefinition parentTD = queryObj.getParentType(typeId);
+            typeId = parentTD == null ? null : parentTD.getId();
+        }
+        return false;
+    }
+
+    private void match(StoredObject so) {
+        // log.debug("Tree is: " + (whereTree == null ? "(empty)" : whereTree.toStringTree()));
+        // first check if type is matching...
+        String queryName = queryObj.getTypes().values().iterator().next(); // as we don't support JOINS take first type
+        TypeDefinition td = queryObj.getTypeDefinitionFromQueryName(queryName);
+        boolean typeMatches = typeMatches(td, so);
+        // ... then check expression...
+        if (typeMatches)
+            evalWhereTree(whereTree, so);        
+    }
+    
+    private void evalWhereTree(Tree node, StoredObject so) {
+        boolean match=true;
+        if (null != node)
+            match = evalWhereNode(so, node.getChild(0));
+        if (match)
+            matches.add(so); // add to list
+    }
+
+    // Standard expression evaluator for single pass walking. This is used as first
+    // pass walk in this object for one-time setup tasks (e.g. setup maps)
+    public void onEquals(Tree eqNode, Tree leftNode, Tree rightNode) {
+        
+    }
+    
+    public void onNotEquals(Tree neNode, Tree leftNode, Tree rightNode) {
+        
+    }
+    
+    public void onGreaterThan(Tree gtNode, Tree leftNode, Tree rightNode) {
+        
+    }
+    
+    public void onGreaterOrEquals(Tree geNode, Tree leftNode, Tree rightNode) {
+        
+    }
+    
+    public void onLessThan(Tree ltNode, Tree leftNode, Tree rightNode) {
+        
+    }
+    
+    public void onLessOrEquals(Tree leqNode, Tree leftNode, Tree rightNode) { 
+        
+    }
+
+    // Boolean operators
+    public void onNot(Tree opNode, Tree leftNode) {
+        
+    }
+    
+    public void onAnd(Tree opNode, Tree leftNode, Tree rightNode) {
+        
+    }
+    
+    public void onOr(Tree opNode, Tree leftNode, Tree rightNode) {
+        
+    }
+
+    // Multi-value:
+    public void onIn(Tree node, Tree colNode, Tree listNode) {
+        
+    }
+    
+    public void onNotIn(Tree nod, Tree colNode, Tree listNode) {
+        
+    }
+    
+    public void onNotInList(Tree node) {
+        
+    }
+    
+    public void onInAny(Tree node, Tree colNode, Tree listNode) {
+        
+    }
+    
+    public void onNotInAny(Tree node, Tree colNode, Tree listNode) {
+        
+    }
+    
+    public 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:
+    public void onIsLike(Tree node, Tree colNode, Tree stringNode) {
+        
+    }
+    
+    public void onIsNotLike(Tree node, Tree colNode, Tree stringNode) {
+        
+    }
+
+    // Functions:
+    public void onContains(Tree node, Tree colNode, Tree paramNode) {
+        
+    }
+    
+    public void onInFolder(Tree node, Tree colNode, Tree paramNode) {
+        
+    }
+    
+    public void onInTree(Tree node, Tree colNode, Tree paramNode) {
+        
+    }
+    public void onScore(Tree node, Tree paramNode) { 
+        
+    }
+
+    private void checkRoot(Tree root) {
+        if (root.getType() == CMISQLLexerStrict.WHERE)
+            LOG.debug("Found root with where node.");
+        else
+            LOG.debug("NOT Found root with where node!! " + root.toStringTree());        
+    }
+
+    /**
+     * For each object check if it matches and append it to match-list if it does.
+     * We do here our own walking mechanism so that we can pass additional parameters
+     * and define the return types.
+     *   
+     * @param node
+     *      node in where clause
+     * @return
+     *      true if it matches, false if it not matches
+     */
+    boolean evalWhereNode(StoredObject so, Tree node) {
+        boolean matches = true;
+
+        switch (node.getType()) {
+        case CMISQLLexerStrict.WHERE:
+            matches = evalWhereNode(so, node.getChild(0));
+            break; // ignore
+        case CMISQLLexerStrict.EQ:
+            matches = evalWhereEquals(so, node, node.getChild(0), node.getChild(1));
+            break;
+        case CMISQLLexerStrict.NEQ:
+            matches = evalWhereNotEquals(so, node, node.getChild(0), node.getChild(1));
+            break;
+        case CMISQLLexerStrict.GT:
+            matches = evalWhereGreaterThan(so, node, node.getChild(0), node.getChild(1));
+            break;
+        case CMISQLLexerStrict.GTEQ:
+            matches = evalWhereGreaterOrEquals(so, node, node.getChild(0), node.getChild(1));
+            break;
+        case CMISQLLexerStrict.LT:
+            matches = evalWhereLessThan(so, node, node.getChild(0), node.getChild(1));
+            break;
+        case CMISQLLexerStrict.LTEQ:
+            matches = evalWhereLessOrEquals(so, node, node.getChild(0), node.getChild(1));
+            break;
+
+        case CMISQLLexerStrict.NOT:
+            matches = evalWhereNot(so, node, node.getChild(0));
+            break;
+        case CMISQLLexerStrict.AND:
+            matches = evalWhereAnd(so, node, node.getChild(0), node.getChild(1));
+            break;
+        case CMISQLLexerStrict.OR:
+            matches = evalWhereOr(so, node, node.getChild(0), node.getChild(1));
+            break;
+
+        // Multi-value:
+        case CMISQLLexerStrict.IN:
+            matches = evalWhereIn(so, node, node.getChild(0), node.getChild(1));
+            break;
+        case CMISQLLexerStrict.NOT_IN:
+            matches = evalWhereNotIn(so, node, node.getChild(0), node.getChild(1));
+            break;
+        case CMISQLLexerStrict.IN_ANY:
+            matches = evalWhereInAny(so, node, node.getChild(0), node.getChild(1));
+            break;
+        case CMISQLLexerStrict.NOT_IN_ANY:
+            matches = evalWhereNotInAny(so, node, node.getChild(0), node.getChild(1));
+            break;
+        case CMISQLLexerStrict.EQ_ANY:
+            matches = evalWhereEqAny(so, node, node.getChild(0), node.getChild(1));
+            break;
+
+        // Null comparisons:
+        case CMISQLLexerStrict.IS_NULL:
+            matches = evalWhereIsNull(so, node, node.getChild(0));
+            break;
+        case CMISQLLexerStrict.IS_NOT_NULL:
+            matches = evalWhereIsNotNull(so, node, node.getChild(0));
+            break;
+
+        // String matching
+        case CMISQLLexerStrict.LIKE:
+            matches = evalWhereIsLike(so, node, node.getChild(0), node.getChild(1));
+            break;
+        case CMISQLLexerStrict.NOT_LIKE:
+            matches = evalWhereIsNotLike(so, node, node.getChild(0), node.getChild(1));
+            break;
+
+        // Functions
+        case CMISQLLexerStrict.CONTAINS:
+            if (node.getChildCount() == 1)
+                matches = evalWhereContains(so, node, null, node.getChild(0));
+            else
+                matches = evalWhereContains(so, node, node.getChild(0), node.getChild(1));
+            break;
+        case CMISQLLexerStrict.IN_FOLDER:
+            if (node.getChildCount() == 1)
+                matches = evalWhereInFolder(so, node, null, node.getChild(0));
+            else
+                matches = evalWhereInFolder(so, node, node.getChild(0), node.getChild(1));
+            break;
+        case CMISQLLexerStrict.IN_TREE:
+            if (node.getChildCount() == 1)
+                matches = evalWhereInTree(so, node, null, node.getChild(0));
+            else
+                matches = evalWhereInTree(so, node, node.getChild(0), node.getChild(1));
+            break;
+
+        default:
+            // do nothing;
+        }
+
+        return matches;
+    }
+
+    private boolean evalWhereEquals(StoredObject so, Tree node, Tree leftChild, Tree rightChild) {
+        Integer cmp = compareTo(so, leftChild, rightChild);
+        if (null == cmp)
+            return false; // property is not set
+        else
+            return cmp == 0;
+    }
+
+    private boolean evalWhereNotEquals(StoredObject so, Tree node, Tree leftChild, Tree rightChild) {
+        Integer cmp = compareTo(so, leftChild, rightChild);
+        if (null == cmp)
+            return false; // property is not set
+        else
+            return cmp != 0;
+    }
+
+    private boolean evalWhereGreaterThan(StoredObject so, Tree node, Tree leftChild, Tree rightChild) {
+        Integer cmp = compareTo(so, leftChild, rightChild);
+        if (null == cmp)
+            return false; // property is not set
+        else
+            return cmp > 0;
+    }
+
+    private boolean evalWhereGreaterOrEquals(StoredObject so, Tree node, Tree leftChild, Tree rightChild) {
+        Integer cmp = compareTo(so, leftChild, rightChild);
+        if (null == cmp)
+            return false; // property is not set
+        else
+            return cmp >= 0;
+    }
+
+    private boolean evalWhereLessThan(StoredObject so, Tree node, Tree leftChild, Tree rightChild) {
+        Integer cmp = compareTo(so, leftChild, rightChild);
+        if (null == cmp)
+            return false; // property is not set
+        else
+            return cmp < 0;
+    }
+
+    private boolean evalWhereLessOrEquals(StoredObject so, Tree node, Tree leftChild, Tree rightChild) {
+        Integer cmp = compareTo(so, leftChild, rightChild);
+        if (null == cmp)
+            return false; // property is not set
+        else
+            return cmp <= 0;
+    }
+
+    private boolean evalWhereNot(StoredObject so, Tree node, Tree child) {
+        boolean matches = evalWhereNode(so, child);
+        return !matches;
+    }
+
+    private boolean evalWhereAnd(StoredObject so, Tree node, Tree leftChild, Tree rightChild) {
+        boolean matches1 = evalWhereNode(so, leftChild);
+        boolean matches2 = evalWhereNode(so, rightChild);        
+        return matches1 && matches2;
+    }
+
+    private boolean evalWhereOr(StoredObject so, Tree node, Tree leftChild, Tree rightChild) {
+        boolean matches1 = evalWhereNode(so, leftChild);
+        boolean matches2 = evalWhereNode(so, rightChild);        
+        return matches1 || matches2;
+    }
+
+    private boolean evalWhereIn(StoredObject so, Tree node, Tree leftChild, Tree rightChild) {
+        throw new RuntimeException("Operator IN not supported in InMemory server.");
+    }
+
+    private boolean evalWhereNotIn(StoredObject so, Tree node, Tree colNode, Tree listNode) {
+        throw new RuntimeException("Operator NOT IN not supported in InMemory server.");
+    }
+
+    private boolean evalWhereInAny(StoredObject so, Tree node, Tree colNode, Tree listNode) {
+        throw new RuntimeException("Operator IN ANY not supported in InMemory server.");
+    }
+
+    private boolean evalWhereNotInAny(StoredObject so, Tree node, Tree colNode, Tree listNode) {
+        throw new RuntimeException("Operator NOT IN ANY not supported in InMemory server.");
+    }
+
+    private boolean evalWhereEqAny(StoredObject so, Tree node, Tree colNode, Tree listNode) {
+        throw new RuntimeException("Operator = ANY not supported in InMemory server.");
+    }
+
+    private boolean evalWhereIsNull(StoredObject so, Tree node, Tree child) {
+        throw new RuntimeException("Operator IS NULL not supported in InMemory server.");
+    }
+
+    private boolean evalWhereIsNotNull(StoredObject so, Tree node, Tree child) {
+        throw new RuntimeException("Operator IS NOT NULL not supported in InMemory server.");
+    }
+
+    private boolean evalWhereIsLike(StoredObject so, Tree node, Tree colNode, Tree StringNode) {
+        throw new RuntimeException("Operator LIKE not supported in InMemory server.");
+    }
+
+    private boolean evalWhereIsNotLike(StoredObject so, Tree node, Tree colNode, Tree stringNode) {
+        throw new RuntimeException("Operator NOT LIKE not supported in InMemory server.");
+    }
+
+    private boolean evalWhereContains(StoredObject so, Tree node, Tree colNode, Tree paramNode) {
+        throw new RuntimeException("Operator CONTAINS not supported in InMemory server.");
+    }
+
+    private boolean evalWhereInFolder(StoredObject so, Tree node, Tree colNode, Tree paramNode) {
+        throw new RuntimeException("Operator IN_FOLDER not supported in InMemory server.");
+    }
+
+    private boolean evalWhereInTree(StoredObject so, Tree node, Tree colNode, Tree paramNode) {
+        throw new RuntimeException("Operator IN_TREE not supported in InMemory server.");
+    }
+
+    private void checkLiteral(Tree node) {
+        int type = node.getType();
+        if (type != CMISQLLexerStrict.BOOL_LIT && type != CMISQLLexerStrict.NUM_LIT || type != CMISQLLexerStrict.STRING_LIT
+                || type != CMISQLLexerStrict.TIME_LIT)
+            throw new RuntimeException("Literal expected.");
+    }
+
+    private Object onLiteral(Tree node) {
+        int type = node.getType();
+        String text = node.getText();
+        switch (type) {
+        case CMISQLLexerStrict.BOOL_LIT:
+            return Boolean.parseBoolean(node.getText());
+        case CMISQLLexerStrict.NUM_LIT:
+            if (text.contains(".") || text.contains("e") || text.contains("E"))
+                return Double.parseDouble(text);
+            else    
+                return Long.parseLong(text);
+        case CMISQLLexerStrict.STRING_LIT:
+            return text.substring(1, text.length()-1);
+        case CMISQLLexerStrict.TIME_LIT:
+            GregorianCalendar gc = CalendarHelper.fromString(text.substring(text.indexOf('\'')+1, text.lastIndexOf('\'')));
+            return gc; 
+        default:
+            LOG.error("Unknown literal. " + node);
+            return null;
+        }
+    }
+    
+    private Integer compareTo(StoredObject so, Tree leftChild, Tree rightChild) {
+        Object rVal = onLiteral(rightChild);
+        //log.debug("retrieve node from where: " + System.identityHashCode(leftChild) + " is " + leftChild);
+        CmisSelector sel = queryObj.getColumnReference(leftChild.getTokenStartIndex());
+        if (null == sel)
+            throw new RuntimeException("Unknown property query name " + leftChild.getChild(0));
+        else if (sel instanceof ColumnReference) {
+            ColumnReference colRef = (ColumnReference) sel;
+            TypeDefinition td = colRef.getTypeDefinition();
+            PropertyDefinition<?> pd = td.getPropertyDefinitions().get(colRef.getPropertyId());
+            PropertyData<?> lVal = so.getProperties().get(colRef.getPropertyId());
+            if (null == lVal)
+                return null; // property is not set
+            else if (pd.getCardinality() == Cardinality.MULTI)
+                throw new RuntimeException("You can't query operators <, <=, ==, !=, >=, > on multi-value properties ");
+
+            return compareTo(pd, lVal, rVal);
+        } else {
+            throw new RuntimeException("Unexpected numerical value function in where clause");
+        }
+    }
+    
+    private int compareTo(PropertyDefinition<?> td, PropertyData<?> lVal, Object rVal) {
+        Object lValue = lVal.getFirstValue();
+        switch (td.getPropertyType()) {
+        case BOOLEAN:
+            if (rVal instanceof Boolean)
+                return ((Boolean)lValue).compareTo((Boolean)rVal);
+            else 
+                throwIncompatibleTypesException(lValue, rVal);
+            break;
+        case INTEGER: 
+        { 
+            Long lLongValue = ((BigInteger)lVal.getFirstValue()).longValue();
+            if (rVal instanceof Long)
+                return (lLongValue).compareTo((Long)rVal);
+            else if (rVal instanceof Double)
+                return Double.valueOf(((Integer)lValue).doubleValue()).compareTo((Double)rVal);
+            else 
+                throwIncompatibleTypesException(lValue, rVal);
+            break;
+        }
+        case DATETIME:
+            if (rVal instanceof GregorianCalendar) {
+                // LOG.debug("left:" + CalendarHelper.toString((GregorianCalendar)lValue) + " right: " + CalendarHelper.toString((GregorianCalendar)rVal));
+                return ((GregorianCalendar)lValue).compareTo((GregorianCalendar)rVal);
+            } else 
+                throwIncompatibleTypesException(lValue, rVal);
+            break;
+        case DECIMAL:
+        { 
+            Double lDoubleValue = ((BigDecimal)lVal.getFirstValue()).doubleValue();
+            if (rVal instanceof Double)
+                return lDoubleValue.compareTo((Double)rVal);
+            else if (rVal instanceof Long)
+                return Double.valueOf(((Integer)lValue).doubleValue()).compareTo((Double)rVal);
+            else 
+                throwIncompatibleTypesException(lValue, rVal);
+            break;
+        }
+        case HTML:
+        case STRING:
+        case URI:   
+        case ID: 
+            if (rVal instanceof String) {
+                LOG.debug("compare strings: " + lValue + " with " + rVal);
+                return ((String)lValue).compareTo((String)rVal);
+            } else 
+                throwIncompatibleTypesException(lValue, rVal);
+            break;
+        }
+        return 0;
+    }
+    
+    private void throwIncompatibleTypesException(Object o1, Object o2) {
+        throw new RuntimeException("Incompatible Types to compare: " + o1 + " and " + o2);
+    }
+
+}

Added: incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/query/QueryObject.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/query/QueryObject.java?rev=954587&view=auto
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/query/QueryObject.java (added)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/query/QueryObject.java Mon Jun 14 18:51:24 2010
@@ -0,0 +1,507 @@
+/*
+ * 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.inmemory.query;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+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.inmemory.TypeManager;
+import org.apache.chemistry.opencmis.inmemory.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 IQueryConditionProcessor queryProcessor;
+    
+    // from part
+    /** 
+     * map from alias name to type query name
+     */
+    private Map<String,String> froms = new HashMap<String,String>();
+
+    // where part
+//    private IdentityHashMap<Object, CmisSelector> columnReferences = new IdentityHashMap<Object, CmisSelector>(); 
+    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, IQueryConditionProcessor 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;
+    }
+    
+    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;
+    }
+    
+    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
+    
+    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 CMISQLLexerStrict.WHERE:;
+                break; // ignore
+            case CMISQLLexerStrict.EQ:
+                queryProcessor.onEquals(node, node.getChild(0), node.getChild(1));
+                break;
+            case CMISQLLexerStrict.NEQ:
+                queryProcessor.onNotEquals(node, node.getChild(0), node.getChild(1));
+                break;
+            case CMISQLLexerStrict.GT:
+                queryProcessor.onGreaterThan(node, node.getChild(0), node.getChild(1));
+                break;
+            case CMISQLLexerStrict.GTEQ:
+                queryProcessor.onGreaterOrEquals(node, node.getChild(0), node.getChild(1));
+                break;
+            case CMISQLLexerStrict.LT:
+                queryProcessor.onLessThan(node, node.getChild(0), node.getChild(1));
+                break;
+            case CMISQLLexerStrict.LTEQ:
+                queryProcessor.onLessOrEquals(node, node.getChild(0), node.getChild(1));
+                break;
+                
+            case CMISQLLexerStrict.NOT:
+                queryProcessor.onNot(node, node.getChild(0));
+                break;
+            case CMISQLLexerStrict.AND:
+                queryProcessor.onAnd(node, node.getChild(0), node.getChild(1));
+                break;
+            case CMISQLLexerStrict.OR:
+                queryProcessor.onOr(node, node.getChild(0), node.getChild(1));
+                break;
+                
+            // Multi-value:
+            case CMISQLLexerStrict.IN:
+                queryProcessor.onIn(node, node.getChild(0), node.getChild(1));
+                break;
+            case CMISQLLexerStrict.NOT_IN:
+                queryProcessor.onNotIn(node, node.getChild(0), node.getChild(1));
+                break;
+            case CMISQLLexerStrict.IN_ANY:
+                queryProcessor.onInAny(node, node.getChild(0), node.getChild(1));
+                break;
+            case CMISQLLexerStrict.NOT_IN_ANY:
+                queryProcessor.onNotInAny(node, node.getChild(0), node.getChild(1));
+                break;
+            case CMISQLLexerStrict.EQ_ANY:
+                queryProcessor.onEqAny(node, node.getChild(0), node.getChild(1));
+                break;
+
+            // Null comparisons:
+            case CMISQLLexerStrict.IS_NULL:
+                queryProcessor.onIsNull(node, node.getChild(0));
+                break;
+            case CMISQLLexerStrict.IS_NOT_NULL:
+                queryProcessor.onIsNotNull(node, node.getChild(0));
+                break;
+
+                // String matching
+            case CMISQLLexerStrict.LIKE:
+                queryProcessor.onIsLike(node, node.getChild(0), node.getChild(1));
+                break;
+            case CMISQLLexerStrict.NOT_LIKE:
+                queryProcessor.onIsNotLike(node, node.getChild(0), node.getChild(1));
+                break;
+
+                // Functions
+            case CMISQLLexerStrict.CONTAINS:
+                if (node.getChildCount()==1)
+                    queryProcessor.onContains(node, null, node.getChild(0));
+                else
+                    queryProcessor.onContains(node, node.getChild(0), node.getChild(1));
+                break;
+            case CMISQLLexerStrict.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 CMISQLLexerStrict.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 CMISQLLexerStrict.SCORE:
+                queryProcessor.onScore(node, node.getChild(0));
+                break;
+                
+            default:
+               // do nothing;
+            }
+    }
+}

Modified: incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/server/InMemoryDiscoveryServiceImpl.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/server/InMemoryDiscoveryServiceImpl.java?rev=954587&r1=954586&r2=954587&view=diff
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/server/InMemoryDiscoveryServiceImpl.java (original)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/server/InMemoryDiscoveryServiceImpl.java Mon Jun 14 18:51:24 2010
@@ -20,6 +20,7 @@ package org.apache.chemistry.opencmis.in
 
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
+import java.io.UnsupportedEncodingException;
 import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.GregorianCalendar;
@@ -33,33 +34,124 @@ import org.antlr.runtime.TokenSource;
 import org.antlr.runtime.TokenStream;
 import org.antlr.runtime.tree.CommonTree;
 import org.antlr.runtime.tree.CommonTreeNodeStream;
+import org.antlr.runtime.tree.Tree;
 import org.apache.chemistry.opencmis.commons.data.ExtensionsData;
 import org.apache.chemistry.opencmis.commons.data.ObjectData;
 import org.apache.chemistry.opencmis.commons.data.ObjectInFolderContainer;
 import org.apache.chemistry.opencmis.commons.data.ObjectList;
 import org.apache.chemistry.opencmis.commons.data.RepositoryInfo;
-import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
 import org.apache.chemistry.opencmis.commons.enums.ChangeType;
 import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships;
-import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException;
 import org.apache.chemistry.opencmis.commons.impl.dataobjects.ChangeEventInfoDataImpl;
 import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectDataImpl;
 import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectListImpl;
 import org.apache.chemistry.opencmis.commons.server.CallContext;
 import org.apache.chemistry.opencmis.commons.server.ObjectInfoHandler;
 import org.apache.chemistry.opencmis.commons.spi.Holder;
-import org.apache.chemistry.opencmis.inmemory.query.InMemoryQueryWalker;
+import org.apache.chemistry.opencmis.inmemory.TypeManager;
+import org.apache.chemistry.opencmis.inmemory.query.CMISQLLexerStrict;
+import org.apache.chemistry.opencmis.inmemory.query.CMISQLParserStrict;
+import org.apache.chemistry.opencmis.inmemory.query.CmisQueryWalker;
+import org.apache.chemistry.opencmis.inmemory.query.InMemoryQueryProcessor;
+import org.apache.chemistry.opencmis.inmemory.query.QueryObject;
 import org.apache.chemistry.opencmis.inmemory.storedobj.api.ObjectStore;
 import org.apache.chemistry.opencmis.inmemory.storedobj.api.StoreManager;
 import org.apache.chemistry.opencmis.inmemory.storedobj.api.StoredObject;
 import org.apache.chemistry.opencmis.inmemory.storedobj.impl.ObjectStoreImpl;
-import org.apache.chemistry.opencmis.inmemory.types.PropertyCreationHelper;
-import org.apache.chemistry.opencmis.server.support.query.CMISQLLexer;
-import org.apache.chemistry.opencmis.server.support.query.CMISQLParser;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
 public class InMemoryDiscoveryServiceImpl extends InMemoryAbstractServiceImpl{
+    
+    private static Log log = LogFactory.getLog(InMemoryDiscoveryServiceImpl.class);
+    
+     private static class InMemoryQueryContext {
+        
+        public CommonTree parserTree; // the ANTLR tree after parsing phase
+        public CommonTree walkerTree; // the ANTLR tree after walking phase
+        private QueryObject queryObj;
+        
+        /**
+         * Main entry function to process a query from discovery service
+         */
+        public ObjectList query(StoreManager storeMgr, String user, String repositoryId, String statement, Boolean searchAllVersions,
+                Boolean includeAllowableActions, IncludeRelationships includeRelationships, String renditionFilter,
+                BigInteger maxItems, BigInteger skipCount) {
+            
+            TypeManager tm = storeMgr.getTypeManager(repositoryId);
+            ObjectStore objectStore = storeMgr.getObjectStore(repositoryId);
+
+            InMemoryQueryProcessor queryProcessor = new InMemoryQueryProcessor();
+            queryObj = new QueryObject(tm, queryProcessor);
+            queryProcessor.setQueryObject(queryObj);
+            processQueryAndCatchExc(statement); // calls query processor
+
+            // iterate over all the objects and check for each if the query matches
+            for (String objectId : ((ObjectStoreImpl) objectStore).getIds()) {
+                StoredObject so = objectStore.getObjectById(objectId);
+                queryProcessor.checkMatch(so);
+            }
+
+            ObjectList objList = queryProcessor.buildResultList(tm, user, includeAllowableActions, includeRelationships, renditionFilter,
+                    maxItems, skipCount);
+            log.debug("Query result, number of matching objects: " + objList.getNumItems());
+            for (ObjectData od : objList.getObjects())
+                log.debug("Found matching object: " + od);
+            return objList;
+        }        
+        
+        private CmisQueryWalker getWalker(String statement) throws UnsupportedEncodingException, IOException, RecognitionException {
+            CharStream input = new ANTLRInputStream(new ByteArrayInputStream(statement.getBytes("UTF-8")));
+            TokenSource lexer = new CMISQLLexerStrict(input);
+            TokenStream tokens = new CommonTokenStream(lexer);
+            CMISQLParserStrict parser = new CMISQLParserStrict(tokens);
+
+            CMISQLParserStrict.query_return parsedStatement = parser.query();
+            if (parser.errorMessage != null) {
+                throw new RuntimeException("Cannot parse query: " + statement + " (" + parser.errorMessage + ")");
+            }
+            parserTree = (CommonTree) parsedStatement.getTree();            
+        
+            CommonTreeNodeStream nodes = new CommonTreeNodeStream(parserTree);
+            nodes.setTokenStream(tokens);
+            CmisQueryWalker walker = new CmisQueryWalker(nodes);
+            return walker;
+        }
+
+        public CmisQueryWalker processQuery(String statement) throws UnsupportedEncodingException, IOException, RecognitionException {
+            CmisQueryWalker walker = getWalker(statement);
+            walker.query(queryObj);
+            String errMsg = walker.getErrorMessageString();
+            if (null != errMsg) {
+                throw new RuntimeException("Walking of statement failed with error: \n   " + errMsg + 
+                        "\n   Statement was: " + statement);
+            }
+            walkerTree = (CommonTree) walker.getTreeNodeStream().getTreeSource();
+            return walker;
+        }
+
+        public CmisQueryWalker processQueryAndCatchExc(String statement) {
+            try {
+                return processQuery(statement);
+            } catch (RecognitionException e) {
+                throw new RuntimeException("Walking of statement failed with RecognitionException error: \n   " + e); 
+            } catch (Exception e) {
+                throw new RuntimeException("Walking of statement failed with other exception: \n   " + e); 
+            }
+        }
+        
+        private Tree getWhereTree(Tree root) {
+            int count = root.getChildCount();
+            for (int i=0; i<count; i++) {
+                Tree child = root.getChild(i);
+                if (child.getType() == CMISQLLexerStrict.WHERE) {
+                    return child;
+                }
+            }
+            return null;
+        }
+        
+    }
 
     private static final Log LOG = LogFactory.getLog(InMemoryDiscoveryServiceImpl.class.getName());
 
@@ -124,116 +216,14 @@ public class InMemoryDiscoveryServiceImp
 
         LOG.debug("start query()");
         checkRepositoryId(repositoryId);
-        ObjectStore objectStore = fStoreManager.getObjectStore(repositoryId);
-
         String user = context.getUsername();
-        List<ObjectData> lod = new ArrayList<ObjectData>();
 
-        try {
-            CMISQLParser parser = getParser(statement);
-
-            CMISQLParser.query_return parsedStatement = parser.query();
-            if (parser.errorMessage != null) {
-                throw new CmisRuntimeException("Cannot parse query: " + statement + " (" + parser.errorMessage + ")");
-            }
-            CommonTree tree = (CommonTree) parsedStatement.getTree();            
-            TokenStream tokens = parser.getTokenStream();
-
-            String tableName = null;
-            // iterate over all the objects and check for each if the query matches
-            for (String objectId : ((ObjectStoreImpl) objectStore).getIds()) {
-                StoredObject so = objectStore.getObjectById(objectId);
-                if (tableName != null) {
-                    // type already available: check early
-                    if (!typeMatches(context, repositoryId, tableName, so.getTypeId())) {
-                        continue;
-                    }
-                }
-                CommonTreeNodeStream nodes = new CommonTreeNodeStream(tree);
-                nodes.setTokenStream(tokens);
-                InMemoryQueryWalker walker = new InMemoryQueryWalker(nodes);
-                InMemoryQueryWalker.query_return ret = matchStoredObject(walker, so);
-                if (tableName == null) {
-                    // first time: check late
-                    tableName = ret.tableName.toLowerCase();
-                    if (!typeMatches(context, repositoryId, tableName, so.getTypeId())) {
-                        continue;
-                    }
-                }
-                if (ret.matches) {
-                    String filter = "*"; // TODO select_list
-	                TypeDefinition td = fStoreManager.getTypeById(repositoryId, so.getTypeId()).getTypeDefinition();
-                    ObjectData od = PropertyCreationHelper.getObjectData(td, so, filter, user,
-                            includeAllowableActions, includeRelationships, renditionFilter, false, false, null);
-                    lod.add(od);
-                }
-            }
-
-        } catch (IOException e) {
-            throw new CmisRuntimeException(e.getMessage(), e);
-        } catch (RecognitionException e) {
-            throw new CmisRuntimeException("Cannot parse query: " + statement, e);
-        }
-        // TODO order_by_clause
-
-        ObjectListImpl objList = new ObjectListImpl();
-        objList.setObjects(lod);
-        objList.setNumItems(BigInteger.valueOf(lod.size()));
+        InMemoryQueryContext queryCtx  = new InMemoryQueryContext();
+        ObjectList objList =  queryCtx.query(fStoreManager, user, repositoryId, statement, searchAllVersions,
+                includeAllowableActions, includeRelationships, renditionFilter, maxItems, skipCount); 
 
         LOG.debug("stop query()");
         return objList;
     }
 
-    protected boolean typeMatches(CallContext context, String repositoryId, String tableName, String typeId) {
-        do {
-            TypeDefinition td = fRepositoryService.getTypeDefinition(context, repositoryId, typeId, null);
-            if (tableName.equals(td.getQueryName().toLowerCase())) {
-                return true;
-            }
-            // check parent type
-            typeId = td.getParentTypeId();
-        } while (typeId != null);
-        return false;
-    }
-
-
-    private CMISQLParser getParser(String statement) throws RecognitionException, IOException {
-        CharStream input = new ANTLRInputStream(new ByteArrayInputStream(statement.getBytes("UTF-8")));
-        TokenSource lexer = new CMISQLLexer(input);
-        TokenStream tokens = new CommonTokenStream(lexer);
-        CMISQLParser parser = new CMISQLParser(tokens);
-        return parser;
-    }
-        
-    private InMemoryQueryWalker.query_return matchStoredObject(InMemoryQueryWalker walker, StoredObject so) throws RecognitionException {
-        InMemoryQueryWalker.query_return res = walker.query(so);
-        return res;
-    }
-    
-    protected InMemoryQueryWalker.query_return queryStoredObject(String statement, StoredObject so) {
-        try {
-            CharStream input = new ANTLRInputStream(new ByteArrayInputStream(statement.getBytes("UTF-8")));
-            TokenSource lexer = new CMISQLLexer(input);
-            TokenStream tokens = new CommonTokenStream(lexer);
-            CMISQLParser parser = new CMISQLParser(tokens);
-            CMISQLParser.query_return query = parser.query();
-            if (parser.errorMessage != null) {
-                throw new CmisRuntimeException("Cannot parse query: " + statement + " (" + parser.errorMessage + ")");
-            }
-            CommonTree tree = (CommonTree) query.getTree();
-            CommonTreeNodeStream nodes = new CommonTreeNodeStream(tree);
-            nodes.setTokenStream(tokens);
-            InMemoryQueryWalker walker = new InMemoryQueryWalker(nodes);
-            InMemoryQueryWalker.query_return res = walker.query(so);
-            if (walker.errorMessage != null) {
-                throw new CmisRuntimeException("Cannot parse query: " + statement + " (" + walker.errorMessage + ")");
-            }
-            return res;
-        } catch (IOException e) {
-            throw new CmisRuntimeException(e.getMessage(), e);
-        } catch (RecognitionException e) {
-            throw new CmisRuntimeException("Cannot parse query: " + statement, e);
-        }
-    }
-
 }

Modified: incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/storedobj/impl/StoreManagerImpl.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/storedobj/impl/StoreManagerImpl.java?rev=954587&r1=954586&r2=954587&view=diff
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/storedobj/impl/StoreManagerImpl.java (original)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/storedobj/impl/StoreManagerImpl.java Mon Jun 14 18:51:24 2010
@@ -45,6 +45,7 @@ import org.apache.chemistry.opencmis.com
 import org.apache.chemistry.opencmis.inmemory.RepositoryInfoCreator;
 import org.apache.chemistry.opencmis.inmemory.TypeCreator;
 import org.apache.chemistry.opencmis.inmemory.TypeManager;
+import org.apache.chemistry.opencmis.inmemory.TypeManagerImpl;
 import org.apache.chemistry.opencmis.inmemory.storedobj.api.ObjectStore;
 import org.apache.chemistry.opencmis.inmemory.storedobj.api.StoreManager;
 
@@ -61,7 +62,7 @@ public class StoreManagerImpl implements
     /**
      * map from repository id to a type manager
      */
-    private Map<String, TypeManager> fMapRepositoryToTypeManager = new HashMap<String, TypeManager>();
+    private Map<String, TypeManagerImpl> fMapRepositoryToTypeManager = new HashMap<String, TypeManagerImpl>();
 
     /**
      * map from repository id to a object store
@@ -85,7 +86,7 @@ public class StoreManagerImpl implements
 
     public void initRepository(String repositoryId) {
         fMapRepositoryToObjectStore.put(repositoryId, new ObjectStoreImpl(repositoryId));
-        fMapRepositoryToTypeManager.put(repositoryId, new TypeManager());
+        fMapRepositoryToTypeManager.put(repositoryId, new TypeManagerImpl());
     }
 
     public void createAndInitRepository(String repositoryId, String typeCreatorClassName) {
@@ -94,7 +95,7 @@ public class StoreManagerImpl implements
             throw new RuntimeException("Cannot add repository, repository " + repositoryId + " already exists.");
 
         fMapRepositoryToObjectStore.put(repositoryId, new ObjectStoreImpl(repositoryId));
-        fMapRepositoryToTypeManager.put(repositoryId, new TypeManager());
+        fMapRepositoryToTypeManager.put(repositoryId, new TypeManagerImpl());
 
         // initialize the type system:
         initTypeSystem(repositoryId, typeCreatorClassName);
@@ -186,7 +187,7 @@ public class StoreManagerImpl implements
     }
 
     public void clearTypeSystem(String repositoryId) {
-        TypeManager typeManager = fMapRepositoryToTypeManager.get(repositoryId);
+        TypeManagerImpl typeManager = fMapRepositoryToTypeManager.get(repositoryId);
         if (null == typeManager)
             throw new RuntimeException("Unknown repository " + repositoryId);
 
@@ -260,7 +261,7 @@ public class StoreManagerImpl implements
     private void initTypeSystem(String repositoryId, String typeCreatorClassName) {
 
         List<TypeDefinition> typeDefs = null;
-        TypeManager typeManager = fMapRepositoryToTypeManager.get(repositoryId);
+        TypeManagerImpl typeManager = fMapRepositoryToTypeManager.get(repositoryId);
         if (null == typeManager)
             throw new RuntimeException("Unknown repository " + repositoryId);
 

Modified: incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/types/PropertyCreationHelper.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/types/PropertyCreationHelper.java?rev=954587&r1=954586&r2=954587&view=diff
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/types/PropertyCreationHelper.java (original)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/types/PropertyCreationHelper.java Mon Jun 14 18:51:24 2010
@@ -18,6 +18,7 @@
  */
 package org.apache.chemistry.opencmis.inmemory.types;
 
+import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -30,9 +31,9 @@ import org.apache.chemistry.opencmis.com
 import org.apache.chemistry.opencmis.commons.data.ObjectData;
 import org.apache.chemistry.opencmis.commons.data.Properties;
 import org.apache.chemistry.opencmis.commons.data.PropertyData;
+import org.apache.chemistry.opencmis.commons.data.PropertyInteger;
 import org.apache.chemistry.opencmis.commons.definitions.Choice;
 import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
-import org.apache.chemistry.opencmis.commons.definitions.TypeDefinitionContainer;
 import org.apache.chemistry.opencmis.commons.enums.Cardinality;
 import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships;
 import org.apache.chemistry.opencmis.commons.enums.PropertyType;
@@ -43,6 +44,7 @@ import org.apache.chemistry.opencmis.com
 import org.apache.chemistry.opencmis.commons.impl.dataobjects.BindingsObjectFactoryImpl;
 import org.apache.chemistry.opencmis.commons.impl.dataobjects.ChoiceImpl;
 import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectDataImpl;
+import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertiesImpl;
 import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyBooleanDefinitionImpl;
 import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyDateTimeDefinitionImpl;
 import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyDecimalDefinitionImpl;
@@ -55,8 +57,6 @@ import org.apache.chemistry.opencmis.com
 import org.apache.chemistry.opencmis.inmemory.DataObjectCreator;
 import org.apache.chemistry.opencmis.inmemory.FilterParser;
 import org.apache.chemistry.opencmis.inmemory.NameValidator;
-import org.apache.chemistry.opencmis.inmemory.storedobj.api.ObjectStore;
-import org.apache.chemistry.opencmis.inmemory.storedobj.api.StoreManager;
 import org.apache.chemistry.opencmis.inmemory.storedobj.api.StoredObject;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -229,7 +229,51 @@ public class PropertyCreationHelper {
         return props;
     }
 
-    public static ObjectData getObjectData(TypeDefinition typeDef, StoredObject so, String filter, String user,
+    public static Properties getPropertiesFromObject(StoredObject so, TypeDefinition td,
+            Map<String, String> requestedIds, Map<String, String> requestedFuncs) {
+        // build properties collection
+
+        List<String> idList = new ArrayList<String>(requestedIds.keySet());
+        BindingsObjectFactory objectFactory = new BindingsObjectFactoryImpl();
+        Map<String, PropertyData<?>> properties = new HashMap<String, PropertyData<?>>();
+        so.fillProperties(properties, objectFactory, idList);
+
+        String typeId = so.getTypeId();
+        if (FilterParser.isContainedInFilter(PropertyIds.BASE_TYPE_ID, idList)) {
+            if (td == null) {
+                log.warn("getPropertiesFromObject(), cannot get type definition, a type with id " + typeId
+                        + " is unknown");
+            } else {
+                String baseTypeId = td.getBaseTypeId().value();
+                properties.put(PropertyIds.BASE_TYPE_ID, objectFactory.createPropertyIdData(PropertyIds.BASE_TYPE_ID,
+                        baseTypeId));
+            }
+        }
+
+        // replace all ids with query names or alias:
+        Map<String, PropertyData<?>> mappedProperties = new HashMap<String, PropertyData<?>>();
+        for (Map.Entry<String, PropertyData<?>> prop : properties.entrySet()) {
+            String key = requestedIds.get(prop.getKey());
+            if (key == null)
+                key = prop.getKey();
+            mappedProperties.put(key, prop.getValue());
+        }
+
+        // add functions:
+        BindingsObjectFactory objFactory = new BindingsObjectFactoryImpl();
+        for (String func : requestedFuncs.keySet()) {
+            PropertyInteger pi = objFactory.createPropertyIntegerData(func, BigInteger.valueOf(100)); // fixed
+                                                                                                      // dummy
+                                                                                                      // value
+            mappedProperties.put(requestedFuncs.get(func), pi);
+
+        }
+
+        Properties props = new PropertiesImpl(mappedProperties);
+        return props;
+    }
+    
+   public static ObjectData getObjectData(TypeDefinition typeDef, StoredObject so, String filter, String user,
             Boolean includeAllowableActions, IncludeRelationships includeRelationships, String renditionFilter,
             Boolean includePolicyIds, Boolean includeACL, ExtensionsData extension) {
 
@@ -263,8 +307,33 @@ public class PropertyCreationHelper {
         od.setProperties(props);
 
         // Note: do not set change event info for this call
-        log.debug("stop getObject()");
         return od;
     }
 
+    public static ObjectData getObjectDataQueryResult(TypeDefinition typeDef, StoredObject so, String user, 
+            Map<String, String> requestedProperties, Map<String, String> requestedFuncs,
+            Boolean includeAllowableActions, IncludeRelationships includeRelationships, String renditionFilter
+            ) {
+
+        ObjectDataImpl od = new ObjectDataImpl();
+
+        // build properties collection
+        Properties props = getPropertiesFromObject(so, typeDef, requestedProperties, requestedFuncs);
+
+        // fill output object
+        if (null != includeAllowableActions && includeAllowableActions) {
+            AllowableActions allowableActions = DataObjectCreator.fillAllowableActions(so, user);
+            od.setAllowableActions(allowableActions);
+        }
+        
+        if (null != includeRelationships && includeRelationships != IncludeRelationships.NONE)
+            od.setRelationships(DataObjectCreator.fillRelationships(includeRelationships, so));
+
+        if (renditionFilter != null && renditionFilter.length() > 0)
+            od.setRenditions(DataObjectCreator.fillRenditions(so));
+
+        od.setProperties(props);
+
+        return od;
+    }
 }

Modified: incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/DiscoveryServiceTest.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/DiscoveryServiceTest.java?rev=954587&r1=954586&r2=954587&view=diff
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/DiscoveryServiceTest.java (original)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/DiscoveryServiceTest.java Mon Jun 14 18:51:24 2010
@@ -74,10 +74,24 @@ public class DiscoveryServiceTest extend
         BigInteger maxItems = null;
         BigInteger skipCount = null;
 
-        String statement = "SELECT * FROM cmis:document";
+        String statement = "SELECT * FROM " + TEST_DOCUMENT_TYPE_ID + " WHERE " + TEST_DOCUMENT_STRING_PROP_ID + "='My Doc StringProperty 1'";
         ObjectList res = fDiscSvc.query(fRepositoryId, statement, searchAllVersions, includeAllowableActions,
                 includeRelationships, renditionFilter, maxItems, skipCount, null);
-        // 3 at level 1 + 3*2 at level 2 = 9
+        assertEquals(BigInteger.valueOf(1), res.getNumItems());
+        
+        statement = "SELECT " + TEST_DOCUMENT_STRING_PROP_ID + " FROM " + TEST_DOCUMENT_TYPE_ID + " WHERE " + TEST_DOCUMENT_STRING_PROP_ID + "='My Doc StringProperty 1'";
+        res = fDiscSvc.query(fRepositoryId, statement, searchAllVersions, includeAllowableActions,
+                includeRelationships, renditionFilter, maxItems, skipCount, null);
+        assertEquals(BigInteger.valueOf(1), res.getNumItems());
+        assertEquals(1, res.getObjects().get(0).getProperties().getProperties().size()); // only one property should be delivered
+
+        statement = "SELECT * FROM cmis:folder";
+        res = fDiscSvc.query(fRepositoryId, statement, searchAllVersions, includeAllowableActions,
+                includeRelationships, renditionFilter, maxItems, skipCount, null);
+        // root + 2 at level 1 + 2*2 at level 2 = 7
+        assertEquals(BigInteger.valueOf(7), res.getNumItems());
+
+        /*        
         assertEquals(BigInteger.valueOf(9), res.getNumItems());
 
         statement = "SELECT * FROM cmis:folder";
@@ -96,7 +110,7 @@ public class DiscoveryServiceTest extend
         res = fDiscSvc.query(fRepositoryId, statement, searchAllVersions, includeAllowableActions,
                 includeRelationships, renditionFilter, maxItems, skipCount, null);
         assertEquals(BigInteger.valueOf(0), res.getNumItems());
-
+*/
         log.info("... testQuery() finished.");
     }
 

Modified: incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/TypeValidationTest.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/TypeValidationTest.java?rev=954587&r1=954586&r2=954587&view=diff
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/TypeValidationTest.java (original)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/TypeValidationTest.java Mon Jun 14 18:51:24 2010
@@ -677,7 +677,7 @@ public class TypeValidationTest extends 
 
     private static TypeManager buildInheritedTypes() {
 
-        TypeManager tm = new TypeManager();
+        TypeManagerImpl tm = new TypeManagerImpl();
         tm.initTypeSystem(null); // create CMIS default types
 
         // create super type

Modified: incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/UnitTestTypeSystemCreator.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/UnitTestTypeSystemCreator.java?rev=954587&r1=954586&r2=954587&view=diff
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/UnitTestTypeSystemCreator.java (original)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/UnitTestTypeSystemCreator.java Mon Jun 14 18:51:24 2010
@@ -42,6 +42,7 @@ import org.apache.chemistry.opencmis.com
 import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyStringDefinitionImpl;
 import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyUriDefinitionImpl;
 import org.apache.chemistry.opencmis.inmemory.types.InMemoryDocumentTypeDefinition;
+import org.apache.chemistry.opencmis.inmemory.types.InMemoryFolderTypeDefinition;
 import org.apache.chemistry.opencmis.inmemory.types.PropertyCreationHelper;
 
 public class UnitTestTypeSystemCreator implements TypeCreator {
@@ -52,6 +53,24 @@ public class UnitTestTypeSystemCreator i
     public static final String LEVEL2_TYPE = "DocumentLevel2";
     public static final String VERSION_DOCUMENT_TYPE_ID = "MyVersionedType";
     public static final String VERSION_PROPERTY_ID = "StringProp";
+    public static final String FOLDER_TYPE = "FolderType";
+    
+    public static final String PROP_ID_BOOLEAN = "BooleanProp";
+    public static final String PROP_ID_DATETIME = "DateTimeProp";
+    public static final String PROP_ID_DECIMAL = "DecimalProp";
+    public static final String PROP_ID_HTML = "HtmlProp";
+    public static final String PROP_ID_ID = "IdProp";
+    public static final String PROP_ID_INT = "IntProp";
+    public static final String PROP_ID_STRING = "StringProp";
+    public static final String PROP_ID_URI = "UriProp";
+    public static final String PROP_ID_BOOLEAN_MULTI_VALUE = "BooleanPropMV";
+    public static final String PROP_ID_DATETIME_MULTI_VALUE = "DateTimePropMV";
+    public static final String PROP_ID_DECIMAL_MULTI_VALUE = "DecimalPropMV";
+    public static final String PROP_ID_HTML_MULTI_VALUE = "HtmlPropMV";
+    public static final String PROP_ID_ID_MULTI_VALUE = "IdPropMV";
+    public static final String PROP_ID_INT_MULTI_VALUE = "IntPropMV";
+    public static final String PROP_ID_STRING_MULTI_VALUE = "StringPropMV";
+    public static final String PROP_ID_URI_MULTI_VALUE = "UriPropMV";
 
     /**
      * in the public interface of this class we return the singleton containing
@@ -143,57 +162,61 @@ public class UnitTestTypeSystemCreator i
 
         Map<String, PropertyDefinition<?>> propertyDefinitions = new HashMap<String, PropertyDefinition<?>>();
 
-        PropertyDefinition<Boolean> prop = PropertyCreationHelper.createBooleanDefinition("BooleanProp",
+        PropertyDefinition<Boolean> prop = PropertyCreationHelper.createBooleanDefinition(PROP_ID_BOOLEAN,
                 "Sample Boolean Property");
         propertyDefinitions.put(prop.getId(), prop);
 
-        prop = PropertyCreationHelper.createBooleanMultiDefinition("BooleanPropMV",
+        prop = PropertyCreationHelper.createBooleanMultiDefinition(PROP_ID_BOOLEAN_MULTI_VALUE,
                 "Sample Boolean multi-value Property");
         propertyDefinitions.put(prop.getId(), prop);
 
-        PropertyDateTimeDefinitionImpl prop2 = PropertyCreationHelper.createDateTimeDefinition("DateTimeProp",
+        PropertyDateTimeDefinitionImpl prop2 = PropertyCreationHelper.createDateTimeDefinition(PROP_ID_DATETIME,
                 "Sample DateTime Property");
         propertyDefinitions.put(prop2.getId(), prop2);
 
-        prop2 = PropertyCreationHelper.createDateTimeMultiDefinition("DateTimePropMV",
+        prop2 = PropertyCreationHelper.createDateTimeMultiDefinition(PROP_ID_DATETIME_MULTI_VALUE,
                 "Sample DateTime multi-value Property");
         propertyDefinitions.put(prop2.getId(), prop2);
 
-        PropertyDecimalDefinitionImpl prop3 = PropertyCreationHelper.createDecimalDefinition("DecimalProp",
+        PropertyDecimalDefinitionImpl prop3 = PropertyCreationHelper.createDecimalDefinition(PROP_ID_DECIMAL,
                 "Sample Decimal Property");
         propertyDefinitions.put(prop3.getId(), prop3);
 
-        prop3 = PropertyCreationHelper.createDecimalMultiDefinition("DecimalPropMV", "Sample Decimal multi-value Property");
+        prop3 = PropertyCreationHelper.createDecimalMultiDefinition(PROP_ID_DECIMAL_MULTI_VALUE, "Sample Decimal multi-value Property");
         propertyDefinitions.put(prop3.getId(), prop3);
 
-        PropertyHtmlDefinitionImpl prop4 = PropertyCreationHelper.createHtmlDefinition("HtmlProp",
+        PropertyHtmlDefinitionImpl prop4 = PropertyCreationHelper.createHtmlDefinition(PROP_ID_HTML,
                 "Sample Html Property");
         propertyDefinitions.put(prop4.getId(), prop4);
 
-        prop4 = PropertyCreationHelper.createHtmlDefinition("HtmlPropMV", "Sample Html multi-value Property");
+        prop4 = PropertyCreationHelper.createHtmlDefinition(PROP_ID_HTML_MULTI_VALUE, "Sample Html multi-value Property");
         propertyDefinitions.put(prop4.getId(), prop4);
 
-        PropertyIdDefinitionImpl prop5 = PropertyCreationHelper.createIdDefinition("IdProp", "Sample Id Property");
+        PropertyIdDefinitionImpl prop5 = PropertyCreationHelper.createIdDefinition(PROP_ID_ID, "Sample Id Property");
         propertyDefinitions.put(prop5.getId(), prop5);
 
-        prop5 = PropertyCreationHelper.createIdMultiDefinition("IdPropMV", "Sample Id Html multi-value Property");
+        prop5 = PropertyCreationHelper.createIdMultiDefinition(PROP_ID_ID_MULTI_VALUE, "Sample Id Html multi-value Property");
         propertyDefinitions.put(prop5.getId(), prop5);
 
-        PropertyIntegerDefinitionImpl prop6 = PropertyCreationHelper.createIntegerDefinition("IntProp",
+        PropertyIntegerDefinitionImpl prop6 = PropertyCreationHelper.createIntegerDefinition(PROP_ID_INT,
                 "Sample Int Property");
         propertyDefinitions.put(prop6.getId(), prop6);
 
-        prop6 = PropertyCreationHelper.createIntegerMultiDefinition("IntPropMV", "Sample Int multi-value Property");
+        prop6 = PropertyCreationHelper.createIntegerMultiDefinition(PROP_ID_INT_MULTI_VALUE, "Sample Int multi-value Property");
         propertyDefinitions.put(prop6.getId(), prop6);
 
-        PropertyStringDefinitionImpl prop7 = PropertyCreationHelper.createStringDefinition("StringProp",
+        PropertyStringDefinitionImpl prop7 = PropertyCreationHelper.createStringDefinition(PROP_ID_STRING,
                 "Sample String Property");
         propertyDefinitions.put(prop7.getId(), prop7);
 
-        PropertyUriDefinitionImpl prop8 = PropertyCreationHelper.createUriDefinition("UriProp", "Sample Uri Property");
+        prop7 = PropertyCreationHelper.createStringMultiDefinition(PROP_ID_STRING_MULTI_VALUE,
+        "Sample String multi-value Property");
+        propertyDefinitions.put(prop7.getId(), prop7);
+
+        PropertyUriDefinitionImpl prop8 = PropertyCreationHelper.createUriDefinition(PROP_ID_URI, "Sample Uri Property");
         propertyDefinitions.put(prop8.getId(), prop8);
 
-        prop8 = PropertyCreationHelper.createUriMultiDefinition("UriPropMV", "Sample Uri multi-value Property");
+        prop8 = PropertyCreationHelper.createUriMultiDefinition(PROP_ID_URI_MULTI_VALUE, "Sample Uri multi-value Property");
         propertyDefinitions.put(prop8.getId(), prop8);
 
         PropertyStringDefinitionImpl prop9 = PropertyCreationHelper.createStringDefinition("PickListProp",
@@ -270,11 +293,30 @@ public class UnitTestTypeSystemCreator i
         cmisVersionedType.addCustomPropertyDefinitions(propertyDefinitions);
         cmisVersionedType.setIsVersionable(true); // make it a versionable type;
 
+        // create a folder type
+        // create a complex type with properties
+        InMemoryFolderTypeDefinition cmisFolderType = new InMemoryFolderTypeDefinition(FOLDER_TYPE,
+                "Folder type with properties", InMemoryFolderTypeDefinition.getRootFolderType());
+
+        // create a two property definitions for folder
+
+        propertyDefinitions = new HashMap<String, PropertyDefinition<?>>();
+
+        prop6 = PropertyCreationHelper.createIntegerDefinition(PROP_ID_INT, "Sample Folder Int Property");
+        propertyDefinitions.put(prop6.getId(), prop6);
+
+        prop7 = PropertyCreationHelper.createStringDefinition(PROP_ID_STRING,
+            "Sample Folder String Property");
+        propertyDefinitions.put(prop7.getId(), prop7);
+        cmisFolderType.addCustomPropertyDefinitions(propertyDefinitions);
+
+        
         // add type to types collection
         typesList.add(cmisDocTypeTopLevel);
         typesList.add(cmisDocTypeLevel1);
         typesList.add(cmisDocTypeLevel2);
         typesList.add(cmisVersionedType);
+        typesList.add(cmisFolderType);
 
         return typesList;
     }