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