chemistry-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From j...@apache.org
Subject svn commit: r1466171 - in /chemistry/opencmis/trunk/chemistry-opencmis-server: chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/query/ chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis...
Date Tue, 09 Apr 2013 18:27:22 GMT
Author: jens
Date: Tue Apr  9 18:27:22 2013
New Revision: 1466171

URL: http://svn.apache.org/r1466171
Log:
InMemory: add query for secondary types, fix a bug with not set properties in query results

Modified:
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/query/InMemoryQueryProcessor.java
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/types/PropertyCreationHelper.java
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/UnitTestTypeSystemCreator.java
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/EvalQueryTest.java
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/QueryTestDataCreator.java
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/QueryTypesTest.java
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/QueryObject.java

Modified: 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/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/query/InMemoryQueryProcessor.java?rev=1466171&r1=1466170&r2=1466171&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/query/InMemoryQueryProcessor.java
(original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/query/InMemoryQueryProcessor.java
Tue Apr  9 18:27:22 2013
@@ -60,6 +60,7 @@ import org.apache.chemistry.opencmis.ser
 import org.apache.chemistry.opencmis.server.support.query.CmisSelector;
 import org.apache.chemistry.opencmis.server.support.query.ColumnReference;
 import org.apache.chemistry.opencmis.server.support.query.QueryObject;
+import org.apache.chemistry.opencmis.server.support.query.QueryObject.JoinSpec;
 import org.apache.chemistry.opencmis.server.support.query.QueryObject.SortSpec;
 import org.apache.chemistry.opencmis.server.support.query.QueryUtilStrict;
 import org.apache.chemistry.opencmis.server.support.query.StringUtil;
@@ -81,6 +82,7 @@ public class InMemoryQueryProcessor {
     private QueryObject queryObj;
     private Tree whereTree;
     private ObjectStoreImpl objStore;
+    private List<TypeDefinition> secondaryTypeIds;
     
     public InMemoryQueryProcessor(ObjectStoreImpl objStore) {
         this.objStore = objStore;
@@ -113,6 +115,7 @@ public class InMemoryQueryProcessor {
         CmisQueryWalker walker = queryUtil.getWalker();
         queryObj = queryUtil.getQueryObject();
         whereTree = walker.getWherePredicateTree();
+        secondaryTypeIds = queryObj.getJoinedSecondaryTypes();
         doAdditionalChecks(walker);
     }
 
@@ -144,18 +147,18 @@ public class InMemoryQueryProcessor {
         if (start > 0 || stop > 0) {
             matches = matches.subList(start, stop);
         }
+       
+        
         List<ObjectData> objDataList = new ArrayList<ObjectData>();
         Map<String, String> props = queryObj.getRequestedPropertiesByAlias();
         Map<String, String> funcs = queryObj.getRequestedFuncsByAlias();
-        TypeDefinition fromType = queryObj.getMainFromName();
         
         for (StoredObject so : matches) {
             String queryName = queryObj.getTypes().values().iterator().next();
             TypeDefinition td = queryObj.getTypeDefinitionFromQueryName(queryName);
 
             ObjectData od = PropertyCreationHelper.getObjectDataQueryResult(tm, td, so, user,
props, funcs,
-                    fromType, includeAllowableActions, includeRelationships, renditionFilter);
-
+                    secondaryTypeIds, includeAllowableActions, includeRelationships, renditionFilter);
             objDataList.add(od);
         }
         res.setObjects(objDataList);
@@ -737,6 +740,15 @@ public class InMemoryQueryProcessor {
     private void doAdditionalChecks(CmisQueryWalker walker) {
         if (walker.getNumberOfContainsClauses() > 1)
             throw new CmisInvalidArgumentException("More than one CONTAINS clause is not
allowed");
+        List<JoinSpec> joins = queryObj.getJoins();
+        if (null == secondaryTypeIds && joins.size() > 0)
+            throw new CmisInvalidArgumentException("JOINs are not supported with the exception
of secondary types and a LEFT OUTER JOIN");
+        else if (null != secondaryTypeIds) {
+            for (JoinSpec join : joins) {
+                if (!join.kind.equals("LEFT"))
+                    throw new CmisInvalidArgumentException("JOINs are not supported with
the exception of secondary types and a LEFT OUTER JOIN");
+            }
+        }
     }
 
     // translate SQL wildcards %, _ to Java regex syntax

Modified: 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/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/types/PropertyCreationHelper.java?rev=1466171&r1=1466170&r2=1466171&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/types/PropertyCreationHelper.java
(original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/types/PropertyCreationHelper.java
Tue Apr  9 18:27:22 2013
@@ -82,7 +82,7 @@ import org.slf4j.LoggerFactory;
  * @author Jens
  * 
  */
-public class PropertyCreationHelper {
+public final class PropertyCreationHelper {
 
     private static final Logger log = LoggerFactory.getLogger(PropertyCreationHelper.class);
 
@@ -207,15 +207,15 @@ public class PropertyCreationHelper {
         prop.setDefaultValue(Collections.singletonList(defVal));
     }
 
-    public static Properties getPropertiesFromObject(StoredObject so, TypeManager typeManager,
List<String> requestedIds,
-            boolean fillOptionalPropertyData) {
+    public static Properties getPropertiesFromObject(StoredObject so, TypeManager typeManager,
+            List<String> requestedIds, boolean fillOptionalPropertyData) {
         // build properties collection
 
         BindingsObjectFactory objectFactory = new BindingsObjectFactoryImpl();
         Map<String, PropertyData<?>> properties = new HashMap<String, PropertyData<?>>();
         so.fillProperties(properties, objectFactory, requestedIds);
         TypeDefinition td = typeManager.getTypeById(so.getTypeId()).getTypeDefinition();
-        
+
         String typeId = so.getTypeId();
         if (FilterParser.isContainedInFilter(PropertyIds.BASE_TYPE_ID, requestedIds)) {
             if (td == null) {
@@ -232,17 +232,19 @@ public class PropertyCreationHelper {
         // fill not-set properties from type definition (as spec requires)
         Map<String, PropertyDefinition<?>> propDefs = td.getPropertyDefinitions();
         for (PropertyDefinition<?> propDef : propDefs.values()) {
-            if (!properties.containsKey(propDef.getId()) && FilterParser.isContainedInFilter(propDef.getId(),
requestedIds))
+            if (!properties.containsKey(propDef.getId())
+                    && FilterParser.isContainedInFilter(propDef.getId(), requestedIds))
                 properties.put(propDef.getId(), getEmptyValue(propDef));
         }
-        
+
         // fill not-set properties from secondary types
         List<String> secTypeIds = so.getSecondaryTypeIds();
-        for (String secTypeId: secTypeIds) {
+        for (String secTypeId : secTypeIds) {
             td = typeManager.getTypeById(secTypeId).getTypeDefinition();
             propDefs = td.getPropertyDefinitions();
             for (PropertyDefinition<?> propDef : propDefs.values()) {
-                if (!properties.containsKey(propDef.getId()) && FilterParser.isContainedInFilter(propDef.getId(),
requestedIds))
+                if (!properties.containsKey(propDef.getId())
+                        && FilterParser.isContainedInFilter(propDef.getId(), requestedIds))
                     properties.put(propDef.getId(), getEmptyValue(propDef));
             }
         }
@@ -258,9 +260,8 @@ public class PropertyCreationHelper {
         return props;
     }
 
-	public static Properties getPropertiesFromObject(StoredObject so,
-			TypeDefinition td, TypeDefinition fromType,
-			Map<String, String> requestedIds, Map<String, String> requestedFuncs) {
+    public static Properties getPropertiesFromObject(StoredObject so, TypeDefinition primaryType,
List<TypeDefinition> secondaryTypes,
+            Map<String, String> requestedIds, Map<String, String> requestedFuncs)
{
         // build properties collection
 
         List<String> idList = new ArrayList<String>(requestedIds.values());
@@ -268,77 +269,128 @@ public class PropertyCreationHelper {
         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));
-            }
+            String baseTypeId = primaryType.getBaseTypeId().value();
+            properties.put(PropertyIds.BASE_TYPE_ID,
+                    objectFactory.createPropertyIdData(PropertyIds.BASE_TYPE_ID, baseTypeId));
         }
 
         Map<String, PropertyData<?>> mappedProperties = new HashMap<String,
PropertyData<?>>();
+        
+        // primary type:
         if (requestedIds.containsValue("*")) {
             for (Map.Entry<String, PropertyData<?>> prop : properties.entrySet())
{
-            	if (fromType.getPropertyDefinitions().containsKey(prop.getKey())) {
-            		// map property id to property query name
-            		String queryName = td.getPropertyDefinitions().get(prop.getKey()).getQueryName();
-            		String localName = td.getPropertyDefinitions().get(prop.getKey()).getLocalName();
-            		String displayName = td.getPropertyDefinitions().get(prop.getKey()).getDisplayName();
-            		AbstractPropertyData<?> ad = clonePropertyData(prop.getValue()); 
-
-            		ad.setQueryName(queryName);
-            		ad.setLocalName(localName);
-            		ad.setDisplayName(displayName);
-            		mappedProperties.put(queryName, ad);
-            	}
+                addPropertyToMap(mappedProperties, primaryType, prop.getValue(), null);
+            }
+            // add all values that are not set:
+            Map<String, PropertyDefinition<?>> propDefs = primaryType.getPropertyDefinitions();
+            for (PropertyDefinition<?> propDef : propDefs.values()) {
+                if (!mappedProperties.containsKey(propDef.getQueryName()))
+                    mappedProperties.put(propDef.getId(), getEmptyValue(propDef));
             }
+
         } else {
             // replace all ids with query names or alias:
             for (Entry<String, String> propAlias : requestedIds.entrySet()) {
-            	String queryNameOrAlias = propAlias.getKey();
-            	PropertyData<?> prop = properties.get(propAlias.getValue());
-            	if (fromType.getPropertyDefinitions().containsKey(prop.getId())) {
-            		String localName = td.getPropertyDefinitions().get(prop.getId()).getLocalName();
-            		String displayName = td.getPropertyDefinitions().get(prop.getId()).getDisplayName();
-            		AbstractPropertyData<?> ad = clonePropertyData(prop); 
-
-            		ad.setQueryName(queryNameOrAlias);
-            		ad.setLocalName(localName);
-            		ad.setDisplayName(displayName);
-            		mappedProperties.put(queryNameOrAlias, ad);
-            	}
+                String queryNameOrAlias = propAlias.getKey();
+                PropertyData<?> prop = properties.get(propAlias.getValue());
+                if (null != prop) {
+                    addPropertyToMap(mappedProperties, primaryType, prop, queryNameOrAlias);
+                } else {
+                    addNotSetPropertyToMap(mappedProperties, primaryType, propAlias.getValue(),
queryNameOrAlias);
+                }
             }
         }
+        
+        // secondary types:
+        if (null != secondaryTypes) {
+            for (TypeDefinition typeDef : secondaryTypes) {
+                if (requestedIds.containsValue("*")) {
+                    for (Map.Entry<String, PropertyData<?>> prop : properties.entrySet())
{
+                        addPropertyToMap(mappedProperties, typeDef, prop.getValue(), null);
+                    }
+                    // add all values that are not set:
+                    Map<String, PropertyDefinition<?>> propDefs = typeDef.getPropertyDefinitions();
+                    for (PropertyDefinition<?> propDef : propDefs.values()) {
+                        if (!mappedProperties.containsKey(propDef.getQueryName()))
+                            mappedProperties.put(propDef.getId(), getEmptyValue(propDef));
+                    }
+                } else {
+                    // replace all ids with query names or alias:
+                    for (Entry<String, String> propAlias : requestedIds.entrySet())
{
+                        String queryNameOrAlias = propAlias.getKey();
+                        PropertyData<?> prop = properties.get(propAlias.getValue());
+                        if (null != prop) {
+                            addPropertyToMap(mappedProperties, typeDef, prop, queryNameOrAlias);
+                        } else {
+                            addNotSetPropertyToMap(mappedProperties, typeDef, propAlias.getValue(),
queryNameOrAlias);
+                        }
+                    }
+                }            
+            }
+        }
+        
         // add functions:
         for (Entry<String, String> funcEntry : requestedFuncs.entrySet()) {
-        	String queryName;
-        	if (funcEntry.getValue().equals("SCORE")) {
-        		queryName = "SEARCH_SCORE";
-        		if (!funcEntry.getKey().equals("SCORE"))
-        			queryName = funcEntry.getKey();
-                
-//        		PropertyDecimal pd = objFactory.createPropertyDecimalData(queryName, BigDecimal.valueOf(1.0));
-        		// does not give me an impl class, so directly use it
+            String queryName;
+            if (funcEntry.getValue().equals("SCORE")) {
+                queryName = "SEARCH_SCORE";
+                if (!funcEntry.getKey().equals("SCORE"))
+                    queryName = funcEntry.getKey();
+
+                // PropertyDecimal pd =
+                // objFactory.createPropertyDecimalData(queryName,
+                // BigDecimal.valueOf(1.0));
+                // does not give me an impl class, so directly use it
                 PropertyDecimalImpl pd = new PropertyDecimalImpl();
 
                 // fixed dummy value
-        		pd.setValue(BigDecimal.valueOf(1.0));
-        		pd.setId(queryName);
-        		pd.setQueryName(queryName);
-        		pd.setLocalName("SCORE");
-        		pd.setDisplayName("Score");
+                pd.setValue(BigDecimal.valueOf(1.0));
+                pd.setId(queryName);
+                pd.setQueryName(queryName);
+                pd.setLocalName("SCORE");
+                pd.setDisplayName("Score");
                 mappedProperties.put(funcEntry.getKey(), pd);
-        	}
+            }
         }
 
         Properties props = new PropertiesImpl(mappedProperties.values());
         return props;
     }
 
+    private static void addNotSetPropertyToMap(Map<String, PropertyData<?>> mappedProperties,
TypeDefinition typeDef,
+            String propId, String queryNameOrAlias) {
+        PropertyDefinition<?> propDef = typeDef.getPropertyDefinitions().get(propId);
+        if (null != propDef) {
+            AbstractPropertyData<?> ad = getEmptyValue(propDef);
+            String localName = propDef.getLocalName();
+            String displayName = propDef.getDisplayName();
+            ad.setQueryName(queryNameOrAlias);
+            ad.setLocalName(localName);
+            ad.setDisplayName(displayName);
+            mappedProperties.put(queryNameOrAlias, ad);
+        }
+    }
+
+    private static void addPropertyToMap(Map<String, PropertyData<?>> mappedProperties,
TypeDefinition typeDef,
+            PropertyData<?> propData, String queryNameOrAlias) {
+        String propId = propData.getId();
+        if (typeDef.getPropertyDefinitions().containsKey(propId)) {
+            // map property id to property query name
+            PropertyDefinition<?> propDef = typeDef.getPropertyDefinitions().get(propId);
+            String queryName = propDef.getQueryName();
+            String localName = propDef.getLocalName();
+            String displayName = propDef.getDisplayName();
+            
+            AbstractPropertyData<?> ad = clonePropertyData(propData);
+            ad.setQueryName(queryNameOrAlias == null ? queryName : queryNameOrAlias);
+            ad.setLocalName(localName);
+            ad.setDisplayName(displayName);
+            
+            mappedProperties.put(queryName, ad);
+        }
+    }
+
     public static ObjectData getObjectData(TypeManager tm, StoredObject so, String filter,
String user,
             Boolean includeAllowableActions, IncludeRelationships includeRelationships, String
renditionFilter,
             Boolean includePolicyIds, Boolean includeACL, ExtensionsData extension) {
@@ -391,14 +443,15 @@ public class PropertyCreationHelper {
         return od;
     }
 
-    public static ObjectData getObjectDataQueryResult(TypeManager tm, TypeDefinition typeDef,
StoredObject so, String user,
-            Map<String, String> requestedProperties, Map<String, String> requestedFuncs,
TypeDefinition fromType,
-            Boolean includeAllowableActions, IncludeRelationships includeRelationships, String
renditionFilter) {
+    public static ObjectData getObjectDataQueryResult(TypeManager tm, TypeDefinition primaryType,
StoredObject so,
+            String user, Map<String, String> requestedProperties, Map<String, String>
requestedFuncs,
+            List<TypeDefinition> secondaryTypes, Boolean includeAllowableActions,
+            IncludeRelationships includeRelationships, String renditionFilter) {
 
         ObjectDataImpl od = new ObjectDataImpl();
 
         // build properties collection
-        Properties props = getPropertiesFromObject(so, typeDef, fromType, requestedProperties,
requestedFuncs);
+        Properties props = getPropertiesFromObject(so, primaryType, secondaryTypes, requestedProperties,
requestedFuncs);
 
         // fill output object
         if (null != includeAllowableActions && includeAllowableActions) {
@@ -472,7 +525,7 @@ public class PropertyCreationHelper {
         }
     }
 
-    private static PropertyData<?> getEmptyValue(PropertyDefinition<?> propDef)
{
+    private static AbstractPropertyData<?> getEmptyValue(PropertyDefinition<?>
propDef) {
         if (propDef.getPropertyType().equals(PropertyType.BOOLEAN))
             return new PropertyBooleanImpl(propDef.getId(), (Boolean) null);
         else if (propDef.getPropertyType().equals(PropertyType.DATETIME))
@@ -492,52 +545,52 @@ public class PropertyCreationHelper {
         else
             return null;
     }
-    
+
     private static AbstractPropertyData<?> clonePropertyData(PropertyData<?>
prop) {
         AbstractPropertyData<?> ad = null;
-        
+
         if (prop instanceof PropertyBooleanImpl) {
             PropertyBooleanImpl clone = new PropertyBooleanImpl();
-            clone.setValues(((PropertyBooleanImpl)prop).getValues());
+            clone.setValues(((PropertyBooleanImpl) prop).getValues());
             ad = clone;
         } else if (prop instanceof PropertyDateTimeImpl) {
             PropertyDateTimeImpl clone = new PropertyDateTimeImpl();
-            clone.setValues(((PropertyDateTimeImpl)prop).getValues());
+            clone.setValues(((PropertyDateTimeImpl) prop).getValues());
             ad = clone;
         } else if (prop instanceof PropertyDecimalImpl) {
             PropertyDecimalImpl clone = new PropertyDecimalImpl();
-            clone.setValues(((PropertyDecimalImpl)prop).getValues());
+            clone.setValues(((PropertyDecimalImpl) prop).getValues());
             ad = clone;
         } else if (prop instanceof PropertyHtmlImpl) {
             PropertyHtmlImpl clone = new PropertyHtmlImpl();
-            clone.setValues(((PropertyHtmlImpl)prop).getValues());
+            clone.setValues(((PropertyHtmlImpl) prop).getValues());
             ad = clone;
         } else if (prop instanceof PropertyIdImpl) {
             PropertyIdImpl clone = new PropertyIdImpl();
-            clone.setValues(((PropertyIdImpl)prop).getValues());
+            clone.setValues(((PropertyIdImpl) prop).getValues());
             ad = clone;
         } else if (prop instanceof PropertyIntegerImpl) {
             PropertyIntegerImpl clone = new PropertyIntegerImpl();
-            clone.setValues(((PropertyIntegerImpl)prop).getValues());
+            clone.setValues(((PropertyIntegerImpl) prop).getValues());
             ad = clone;
         } else if (prop instanceof PropertyStringImpl) {
             PropertyStringImpl clone = new PropertyStringImpl();
-            clone.setValues(((PropertyStringImpl)prop).getValues());
+            clone.setValues(((PropertyStringImpl) prop).getValues());
             ad = clone;
         } else if (prop instanceof PropertyUriImpl) {
             PropertyUriImpl clone = new PropertyUriImpl();
-            clone.setValues(((PropertyUriImpl)prop).getValues());
+            clone.setValues(((PropertyUriImpl) prop).getValues());
             ad = clone;
         } else {
             throw new RuntimeException("Unknown property type: " + prop.getClass());
         }
-        
+
         ad.setDisplayName(prop.getDisplayName());
         ad.setId(prop.getId());
         ad.setLocalName(prop.getLocalName());
         ad.setQueryName(prop.getQueryName());
         ad.setExtensions(prop.getExtensions());
 
-        return ad;        
+        return ad;
     }
 }

Modified: 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/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/UnitTestTypeSystemCreator.java?rev=1466171&r1=1466170&r2=1466171&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/UnitTestTypeSystemCreator.java
(original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/UnitTestTypeSystemCreator.java
Tue Apr  9 18:27:22 2013
@@ -57,6 +57,7 @@ public class UnitTestTypeSystemCreator i
     public static final String VERSION_PROPERTY_ID = "StringProp";
     public static final String FOLDER_TYPE = "FolderType";
     public static final String SECONDARY_TYPE = "MySecondaryType";
+    public static final String SECONDARY_TYPE_2 = "MySecondaryType2";
     
     public static final String PROP_ID_BOOLEAN = "BooleanProp";
     public static final String PROP_ID_DATETIME = "DateTimeProp";
@@ -321,7 +322,6 @@ public class UnitTestTypeSystemCreator i
                 "MySecondaryType");
         // create a single String property definition
         propertyDefinitions = new HashMap<String, PropertyDefinition<?>>();
-        propertyDefinitions = new HashMap<String, PropertyDefinition<?>>();
         PropertyStringDefinitionImpl propStr = PropertyCreationHelper.createStringDefinition(SECONDARY_STRING_PROP,
                 "Secondary String Property", Updatability.READWRITE);
         propertyDefinitions.put(propStr.getId(), propStr);
@@ -331,15 +331,17 @@ public class UnitTestTypeSystemCreator i
         propertyDefinitions.put(propInt.getId(), propInt);
         cmisSecondaryType.addCustomPropertyDefinitions(propertyDefinitions);
 
+        InMemorySecondaryTypeDefinition cmisSecondaryType2 = new InMemorySecondaryTypeDefinition(SECONDARY_TYPE_2,

+                "MySecondaryType-2");
 
-        // add type to types collection
+        // add type to types collectio
         typesList.add(cmisDocTypeTopLevel);
         typesList.add(cmisDocTypeLevel1);
         typesList.add(cmisDocTypeLevel2);
         typesList.add(cmisVersionedType);
         typesList.add(cmisFolderType);
         typesList.add(cmisSecondaryType);
-
+        typesList.add(cmisSecondaryType2);
         return typesList;
     }
 

Modified: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/EvalQueryTest.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/EvalQueryTest.java?rev=1466171&r1=1466170&r2=1466171&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/EvalQueryTest.java
(original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/EvalQueryTest.java
Tue Apr  9 18:27:22 2013
@@ -22,6 +22,7 @@ import static org.apache.chemistry.openc
 import static org.apache.chemistry.opencmis.inmemory.UnitTestTypeSystemCreator.PROP_ID_BOOLEAN;
 import static org.apache.chemistry.opencmis.inmemory.UnitTestTypeSystemCreator.PROP_ID_DATETIME;
 import static org.apache.chemistry.opencmis.inmemory.UnitTestTypeSystemCreator.PROP_ID_DECIMAL;
+import static org.apache.chemistry.opencmis.inmemory.UnitTestTypeSystemCreator.PROP_ID_ID;
 import static org.apache.chemistry.opencmis.inmemory.UnitTestTypeSystemCreator.PROP_ID_INT;
 import static org.apache.chemistry.opencmis.inmemory.UnitTestTypeSystemCreator.SECONDARY_TYPE;
 import static org.junit.Assert.assertEquals;
@@ -37,7 +38,6 @@ import org.apache.chemistry.opencmis.com
 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.TypeDefinition;
 import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships;
 import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
 import org.apache.chemistry.opencmis.inmemory.AbstractServiceTest;
@@ -1000,6 +1000,24 @@ public class EvalQueryTest extends Abstr
     }
 
     @Test
+    public void testNotSetProperties() {
+        log.debug("Start testNotSetProperties...");
+        // PROP_ID_ID is not set property
+        String statement = "SELECT cmis:name, " + PROP_ID_ID + " FROM " + COMPLEX_TYPE +
" WHERE " + PROP_ID_INT + "= 100";
+        ObjectList res = doQuery(statement);
+        assertEquals(1, res.getObjects().size());
+        assertTrue(resultContains("epsilon", res));
+        assertTrue(resultContainsNotSetPropertyValue(PROP_ID_ID, res.getObjects().get(0)));
+
+        statement = "SELECT * FROM " + COMPLEX_TYPE + " WHERE " + PROP_ID_INT + "= 100";
+        res = doQuery(statement);
+        assertEquals(1, res.getObjects().size());
+        assertTrue(resultContains("epsilon", res));
+        assertTrue(resultContainsNotSetPropertyValue(PROP_ID_ID, res.getObjects().get(0)));
+        log.debug("...Stop testNotSetProperties.");
+    }
+    
+    @Test
     public void testSecondaryTypes() {
         log.debug("Start testSecondaryTypes...");
         // create documents with secondary types in addition
@@ -1023,14 +1041,26 @@ public class EvalQueryTest extends Abstr
         log.debug("...Stop testSecondaryTypes.");
     }
 
-    // @Test
-    private void testSecondaryJoin() {
+    @Test
+    public void testSecondaryJoin() {
         log.debug("Start testSecondaryJoin...");
         // create documents with secondary types in addition
         dataCreator.createSecondaryTestDocuments();
-        String statement = "SELECT * FROM " + COMPLEX_TYPE + " JOIN SECONDARY_TYPE ON id
= id WHERE "
-                + UnitTestTypeSystemCreator.PROP_ID_STRING + "= 'Secondary'";
+        String statement = "SELECT * FROM " + COMPLEX_TYPE + " LEFT JOIN " + SECONDARY_TYPE
+ " ON " + COMPLEX_TYPE
+                + ".cmis:objectId = " + SECONDARY_TYPE + ".cmis:objectId WHERE cmis:name
LIKE 'docwithsecondary%'";
         ObjectList res = doQuery(statement);
+        assertEquals(2, res.getObjects().size());
+        assertTrue(resultContainsProperty(UnitTestTypeSystemCreator.PROP_ID_STRING, res));
+        assertTrue(resultContainsProperty(PropertyIds.NAME, res));
+        assertTrue(resultContainsProperty(PropertyIds.OBJECT_ID, res));
+        assertTrue(resultContainsProperty(PropertyIds.OBJECT_TYPE_ID, res));
+        assertTrue(resultContainsProperty(UnitTestTypeSystemCreator.SECONDARY_STRING_PROP,
res));
+        assertTrue(resultContainsProperty(UnitTestTypeSystemCreator.SECONDARY_INTEGER_PROP,
res));
+
+        // Test a query with secondary types matching only one document not having this secondary
type
+        statement = "SELECT * FROM " + COMPLEX_TYPE + " LEFT JOIN " + SECONDARY_TYPE + "
ON " + COMPLEX_TYPE
+                + ".cmis:objectId = " + SECONDARY_TYPE + ".cmis:objectId WHERE cmis:name
= 'alpha'";
+        res = doQuery(statement);
         assertEquals(1, res.getObjects().size());
         assertTrue(resultContainsProperty(UnitTestTypeSystemCreator.PROP_ID_STRING, res));
         assertTrue(resultContainsProperty(PropertyIds.NAME, res));
@@ -1038,12 +1068,14 @@ public class EvalQueryTest extends Abstr
         assertTrue(resultContainsProperty(PropertyIds.OBJECT_TYPE_ID, res));
         assertTrue(resultContainsProperty(UnitTestTypeSystemCreator.SECONDARY_STRING_PROP,
res));
         assertTrue(resultContainsProperty(UnitTestTypeSystemCreator.SECONDARY_INTEGER_PROP,
res));
+        
         log.debug("...Stop testSecondaryJoin.");
     }
 
     @Test
     public void testMultipleContains() {
         log.debug("Start testMultipleContains...");
+        dataCreator.createSecondaryTestDocuments();
         String statement = "SELECT * FROM " + COMPLEX_TYPE + " WHERE CONTAINS('abc') AND
CONTAINS('123')";
         try {
             doQuery(statement);
@@ -1126,14 +1158,19 @@ public class EvalQueryTest extends Abstr
         return name.equals(nameProp);
     }
 
+    private boolean resultContainsNotSetPropertyValue(String propId, ObjectData od) {
+        PropertyData<?> propData = od.getProperties().getProperties().get(propId);
+        return propData != null && propId.equals(propData.getId()) && propData.getValues().isEmpty();
+    }
+
     private static boolean resultContainsProperty(String propId, ObjectList results) {
         for (ObjectData od : results.getObjects()) {
             PropertyData<?> propData = od.getProperties().getProperties().get(propId);
-            if (null != propData) {
-                return true;
+            if (null == propData) {
+                return false;
             }
         }
-        return false;
+        return true;
     }
 
 }

Modified: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/QueryTestDataCreator.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/QueryTestDataCreator.java?rev=1466171&r1=1466170&r2=1466171&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/QueryTestDataCreator.java
(original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/QueryTestDataCreator.java
Tue Apr  9 18:27:22 2013
@@ -351,8 +351,7 @@ public class QueryTestDataCreator {
         gc1.set(1945, 4, 8);
 
         final Map<String, Object> propertyMap1 =
-            new HashMap<String, Object>() {
-            {
+            new HashMap<String, Object>() {{
                 put(PROP_ID_STRING, "Secondary");
                 put(PROP_ID_INT, Integer.valueOf(-100));
                 put(PROP_ID_DECIMAL, Double.valueOf(-4.0E24d));
@@ -367,19 +366,18 @@ public class QueryTestDataCreator {
         assertNotNull(doc1);
         
         final Map<String, Object> propertyMap2 =
-                new HashMap<String, Object>() {
-                {
-                    put(PROP_ID_STRING, "Secondary 2");
-                    put(PROP_ID_INT, Integer.valueOf(123));
-                    put(PROP_ID_DECIMAL, Double.valueOf(1.23E24d));
-                    put(PROP_ID_BOOLEAN, false);
-                    put(SECONDARY_STRING_PROP, stringPropVal2);
-                    put(SECONDARY_INTEGER_PROP,intPropVal2);
-                    put(PropertyIds.SECONDARY_OBJECT_TYPE_IDS, SECONDARY_TYPE);     
-                }};
-            ContentStream content2 = createContent("Even still some more content.");
-            doc1 = createDocument("docwithsecondary2", rootFolderId, COMPLEX_TYPE, propertyMap2,
content2);
-            assertNotNull(doc1);
+            new HashMap<String, Object>() {{
+                put(PROP_ID_STRING, "Secondary 2");
+                put(PROP_ID_INT, Integer.valueOf(123));
+                put(PROP_ID_DECIMAL, Double.valueOf(1.23E24d));
+                put(PROP_ID_BOOLEAN, false);
+                put(SECONDARY_STRING_PROP, stringPropVal2);
+                put(SECONDARY_INTEGER_PROP,intPropVal2);
+                put(PropertyIds.SECONDARY_OBJECT_TYPE_IDS, SECONDARY_TYPE);     
+            }};
+        ContentStream content2 = createContent("Even still some more content.");
+        doc1 = createDocument("docwithsecondary2", rootFolderId, COMPLEX_TYPE, propertyMap2,
content2);
+        assertNotNull(doc1);
     }
     
     

Modified: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/QueryTypesTest.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/QueryTypesTest.java?rev=1466171&r1=1466170&r2=1466171&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/QueryTypesTest.java
(original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/QueryTypesTest.java
Tue Apr  9 18:27:22 2013
@@ -20,6 +20,7 @@ package org.apache.chemistry.opencmis.in
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
@@ -32,6 +33,7 @@ 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.TypeManagerImpl;
+import org.apache.chemistry.opencmis.inmemory.UnitTestTypeSystemCreator;
 import org.apache.chemistry.opencmis.server.support.query.AbstractPredicateWalker;
 import org.apache.chemistry.opencmis.server.support.query.CmisQueryWalker;
 import org.apache.chemistry.opencmis.server.support.query.CmisSelector;
@@ -526,7 +528,69 @@ public class QueryTypesTest extends Abst
             }
         }
     }
+    
+    @Test
+    public void testSecondaryJoin() throws RecognitionException {
+        // needs some special types:
+        tm = new TypeManagerImpl();
+        tm.initTypeSystem(null); // create CMIS default types
+
+        // create some types for testing
+        List<TypeDefinition> typeDefs = UnitTestTypeSystemCreator.getTypesList(); 
+        for (TypeDefinition typeDef : typeDefs) {
+            tm.addTypeDefinition(typeDef);
+        }
+        super.setUp(tm, pw);
 
+        String statement = "SELECT * FROM cmis:document JOIN " + UnitTestTypeSystemCreator.SECONDARY_TYPE
+                + " WHERE SecondaryStringProp='groovy'";
+        CmisQueryWalker walker = getWalker(statement);
+        assertNotNull(queryObj);
+        assertNotNull(walker);
+        List<TypeDefinition> secondaryJoinedTypes = queryObj.getJoinedSecondaryTypes();
+        assertNull(secondaryJoinedTypes);
+
+        statement = "SELECT * FROM cmis:document WHERE cmis:name='groovy'";
+        walker = getWalker(statement);
+        secondaryJoinedTypes = queryObj.getJoinedSecondaryTypes();
+        assertNull(secondaryJoinedTypes);
+        
+        statement = "SELECT * FROM cmis:document JOIN " + UnitTestTypeSystemCreator.COMPLEX_TYPE
+ " WHERE "
+                + UnitTestTypeSystemCreator.PROP_ID_STRING + "='groovy'";
+        walker = getWalker(statement);
+        secondaryJoinedTypes = queryObj.getJoinedSecondaryTypes();
+        assertNull(secondaryJoinedTypes);
+        
+        statement = "SELECT * FROM cmis:document JOIN " + UnitTestTypeSystemCreator.SECONDARY_TYPE
+                + " ON cmis:document.cmis:objectId = " + UnitTestTypeSystemCreator.SECONDARY_TYPE
+                + ".cmis:objectId WHERE SecondaryStringProp='groovy'";
+        walker = getWalker(statement);
+        secondaryJoinedTypes = queryObj.getJoinedSecondaryTypes();
+        assertEquals(1, secondaryJoinedTypes.size());
+        assertEquals(UnitTestTypeSystemCreator.SECONDARY_TYPE, secondaryJoinedTypes.get(0).getId());
+        
+        statement = "SELECT * FROM cmis:document JOIN " + UnitTestTypeSystemCreator.SECONDARY_TYPE
+                + " ON " + UnitTestTypeSystemCreator.SECONDARY_TYPE
+                + ".cmis:objectId = cmis:document.cmis:objectId WHERE SecondaryStringProp='groovy'";
+        walker = getWalker(statement);
+        secondaryJoinedTypes = queryObj.getJoinedSecondaryTypes();
+        assertEquals(1, secondaryJoinedTypes.size());
+        assertEquals(UnitTestTypeSystemCreator.SECONDARY_TYPE, secondaryJoinedTypes.get(0).getId());
+
+        statement = "SELECT * FROM cmis:document JOIN MySecondaryType ON cmis:document.cmis:objectId
= MySecondaryType.cmis:objectId JOIN MySecondaryType2 ON cmis:document.cmis:objectId = MySecondaryType2.cmis:objectId
WHERE SecondaryStringProp='groovy'";
+        walker = getWalker(statement);
+        secondaryJoinedTypes = queryObj.getJoinedSecondaryTypes();
+        assertEquals(2, secondaryJoinedTypes.size());
+        assertEquals(UnitTestTypeSystemCreator.SECONDARY_TYPE, secondaryJoinedTypes.get(0).getId());
+        assertEquals(UnitTestTypeSystemCreator.SECONDARY_TYPE_2, secondaryJoinedTypes.get(1).getId());
+
+        statement = "SELECT a.cmis:objectId, a.cmis:name, b.SecondaryStringProp FROM cmis:document
AS a JOIN MySecondaryType AS b ON a.cmis:objectId = b.cmis:objectId WHERE b.SecondaryStringProp='groovy'";
+        walker = getWalker(statement);
+        secondaryJoinedTypes = queryObj.getJoinedSecondaryTypes();
+        assertEquals(1, secondaryJoinedTypes.size());
+        assertEquals(UnitTestTypeSystemCreator.SECONDARY_TYPE, secondaryJoinedTypes.get(0).getId());
+    }
+    
     @Test
     public void resolveTypeQualifiers1() throws Exception {
         String statement = "SELECT Title FROM BookType WHERE IN_TREE(BookType, 'foo')";

Modified: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/QueryObject.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/QueryObject.java?rev=1466171&r1=1466170&r2=1466171&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/QueryObject.java
(original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/query/QueryObject.java
Tue Apr  9 18:27:22 2013
@@ -28,7 +28,9 @@ import java.util.Map;
 import java.util.Map.Entry;
 
 import org.antlr.runtime.tree.Tree;
+import org.apache.chemistry.opencmis.commons.PropertyIds;
 import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
+import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
 import org.apache.chemistry.opencmis.server.support.TypeManager;
 import org.apache.chemistry.opencmis.server.support.TypeValidator;
 import org.slf4j.Logger;
@@ -389,6 +391,39 @@ public class QueryObject {
         sortSpecs.add(new SortSpec(node.getTokenStartIndex(), ascending));
     }
 
+    /**
+     * Tests if the query has a JOIN from one primary type to only secondary types
+     * (This JOIN does not require a JOIN capability in CMIS).
+     * 
+     * @return list of secondary type ids that are joined or null if the
+     * query has no JOINs or has joins to primary types
+     */
+    public List<TypeDefinition> getJoinedSecondaryTypes() {
+        List<TypeDefinition> secondaryTypeIds = new ArrayList<TypeDefinition>();
+        Map<String, String> froms = getTypes();
+        if (froms.size() == 1)
+            return null; // no JOIN in query
+        String mainTypeQueryName = froms.get(getMainTypeAlias());
+        for (String queryName: froms.values()) {
+            TypeDefinition td = getTypeDefinitionFromQueryName(queryName);
+            if (queryName.equals(mainTypeQueryName))
+                continue;
+            if (td.getBaseTypeId() == BaseTypeId.CMIS_SECONDARY) {
+                secondaryTypeIds.add(td);
+            } else {
+                return null;
+            }
+        }
+        for (JoinSpec join : getJoins()) {
+            if (!(null != join.onLeft && null != join.onRight && ((join.onRight.getPropertyId()
== null && join.onRight.getTypeDefinition().getBaseTypeId() == BaseTypeId.CMIS_SECONDARY
&&
+                    join.onLeft.getPropertyId().equals(PropertyIds.OBJECT_ID)) ||
+                    (join.onLeft.getPropertyId() == null && join.onLeft.getTypeDefinition().getBaseTypeId()
== BaseTypeId.CMIS_SECONDARY && 
+                    join.onRight.getPropertyId().equals(PropertyIds.OBJECT_ID)  ))))
+                return null;             
+        }
+        return secondaryTypeIds;
+    }
+
     // ///////////////////////////////////////////////////////
     // resolve types after first pass traversing the AST is complete
 
@@ -574,6 +609,8 @@ public class QueryObject {
             hasProp = true;
         } else {
             hasProp = TypeValidator.typeContainsPropertyWithQueryName(td, colRef.getPropertyQueryName());
+            if (!hasProp && td.getBaseTypeId() == BaseTypeId.CMIS_SECONDARY &&
colRef.getPropertyQueryName().equals(PropertyIds.OBJECT_ID))
+                hasProp = true; // special handling for object id on secondary types which
are required for JOINS
         }
         if (!hasProp) {
             throw new CmisQueryException(colRef.getPropertyQueryName()



Mime
View raw message