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 [4/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/test/java/org/apache/chemistry/opencmis/inmemory/query/QueryTestDataCreator.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/query/QueryTestDataCreator.java?rev=954587&view=auto
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/QueryTestDataCreator.java (added)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/QueryTestDataCreator.java Mon Jun 14 18:51:24 2010
@@ -0,0 +1,279 @@
+/*
+ * 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 static org.junit.Assert.fail;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.GregorianCalendar;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TimeZone;
+
+import org.apache.chemistry.opencmis.commons.PropertyIds;
+import org.apache.chemistry.opencmis.commons.data.Acl;
+import org.apache.chemistry.opencmis.commons.data.ContentStream;
+import org.apache.chemistry.opencmis.commons.data.ExtensionsData;
+import org.apache.chemistry.opencmis.commons.data.Properties;
+import org.apache.chemistry.opencmis.commons.data.PropertyData;
+import org.apache.chemistry.opencmis.commons.enums.VersioningState;
+import org.apache.chemistry.opencmis.commons.impl.dataobjects.BindingsObjectFactoryImpl;
+import org.apache.chemistry.opencmis.commons.spi.BindingsObjectFactory;
+import org.apache.chemistry.opencmis.commons.spi.ObjectService;
+import static org.apache.chemistry.opencmis.inmemory.UnitTestTypeSystemCreator.*;
+
+/**
+ * Utility class that fills the in-memory repository with some test objects that
+ * can be used for query
+ * 
+ * @author Jens
+ *
+ * This class uses the following data for query testing. We have one document type
+ * "ComplexType" and one folder type "FolderType" The document type has one property of
+ * each of the types boolean, integer, decimal, string and datetime. id, uri and html are
+ * treated like a string and do not make a difference. 
+ * 
+ * String   Int         Double      DateTime  Boolean
+ * ------------------------------------------------
+ * Alpha    -100        -1.6E-5     23.05.1618  true
+ * Beta     -50         -4.0E24     08.05.1945  false
+ * Gamma    0           3.141592    (now)       true
+ * Delta    50          1.23456E-6  20.01.2038  true
+ * Epsilon  100         1.2345E12   14.07.2345  false
+ * 
+ * For folder and tree tests this series is put in each of the three test folders
+ */
+public class QueryTestDataCreator {
+    
+    private BindingsObjectFactory fFactory = new BindingsObjectFactoryImpl();
+    private String rootFolderId;
+    private String repositoryId;
+    private ObjectService fObjSvc;
+    private String doc1, doc2, doc3, doc4, doc5;
+    private String folder1;
+    private String folder2;
+    private String folder11;
+    private static final TimeZone TZ = TimeZone.getTimeZone("Zulu");
+    
+    public QueryTestDataCreator(String repositoryId, String rootFolderId, ObjectService objSvc) {
+        this.rootFolderId = rootFolderId;
+        this.repositoryId = repositoryId;
+        fObjSvc = objSvc;
+    }
+    
+    public void createTestData() {
+        createTestFolders();
+        createTestDocuments();
+    }
+
+    @SuppressWarnings("serial")
+    public void createTestDocuments() {
+
+        final GregorianCalendar gc1 = new GregorianCalendar(TZ);
+        gc1.clear();
+        gc1.set(1945, 4, 8);
+        
+        final Map<String, Object> propertyMap1 = 
+            new HashMap<String, Object>() {
+            { 
+                put(PROP_ID_STRING, "Alpha");
+                put(PROP_ID_INT, new Integer(-100));
+                put(PROP_ID_DECIMAL, new Double(-4.0E24d));
+                put(PROP_ID_DATETIME, gc1);
+                put(PROP_ID_BOOLEAN, true);
+            }};           
+        doc1 = createDocument("alpha", rootFolderId, COMPLEX_TYPE, propertyMap1);
+        
+        final GregorianCalendar gc2 = new GregorianCalendar(TZ);
+        gc2.clear();
+        gc2.set(1618, 4, 23);
+        
+        final Map<String, Object> propertyMap2 = 
+            new HashMap<String, Object>() {
+            { 
+                put(PROP_ID_STRING, "Beta");
+                put(PROP_ID_INT, new Integer(-50));
+                put(PROP_ID_DECIMAL, new Double(-1.6E-5d));
+                put(PROP_ID_DATETIME, gc2);
+                put(PROP_ID_BOOLEAN, false);
+            }};           
+        doc2 = createDocument("beta", rootFolderId, COMPLEX_TYPE, propertyMap2);
+
+        final Map<String, Object> propertyMap3 = 
+            new HashMap<String, Object>() {
+            { 
+                put(PROP_ID_STRING, "Gamma");
+                put(PROP_ID_INT, new Integer(0));
+                put(PROP_ID_DECIMAL, new Double(Math.PI));
+                put(PROP_ID_DATETIME, new GregorianCalendar(TZ));
+                put(PROP_ID_BOOLEAN, true);
+            }};           
+        doc3 = createDocument("gamma", rootFolderId, COMPLEX_TYPE, propertyMap3);
+
+        final GregorianCalendar gc4 = new GregorianCalendar(TZ);
+        gc4.clear();
+        gc4.set(2038, 0, 20);
+        
+        final Map<String, Object> propertyMap4 = 
+            new HashMap<String, Object>() {
+            { 
+                put(PROP_ID_STRING, "Delta");
+                put(PROP_ID_INT, new Integer(50));
+                put(PROP_ID_DECIMAL, new Double(1.23456E-6));
+                put(PROP_ID_DATETIME, gc4);
+                put(PROP_ID_BOOLEAN, true);
+            }};           
+        doc4 = createDocument("delta", rootFolderId, COMPLEX_TYPE, propertyMap4);
+
+        final GregorianCalendar gc5 = new GregorianCalendar(TZ);
+        gc5.clear();
+        gc5.set(2345, 6, 14);
+        
+        final Map<String, Object> propertyMap5 = 
+            new HashMap<String, Object>() {
+            { 
+                put(PROP_ID_STRING, "Epsilon");
+                put(PROP_ID_INT, new Integer(100));
+                put(PROP_ID_DECIMAL, new Double(1.2345E12));
+                put(PROP_ID_DATETIME, gc5);
+                put(PROP_ID_BOOLEAN, false);
+            }};           
+        doc5 = createDocument("epsilon", rootFolderId, COMPLEX_TYPE, propertyMap5);
+
+}
+    
+    @SuppressWarnings("serial")
+    public void createTestFolders() {
+        final Map<String, Object> propertyMap1 = 
+            new HashMap<String, Object>() {
+            { 
+                put(PROP_ID_INT, new Integer(1234));
+                put(PROP_ID_STRING, "ABCD");
+            }};           
+        folder1 = createFolder("Folder 1", rootFolderId, FOLDER_TYPE, propertyMap1);
+        
+        final Map<String, Object> propertyMap2 = 
+            new HashMap<String, Object>() {
+            { 
+                put(PROP_ID_INT, new Integer(-2345));
+                put(PROP_ID_STRING, "defg");
+            }};           
+        folder2 = createFolder("Folder 2", rootFolderId, FOLDER_TYPE, propertyMap2);
+
+        final Map<String, Object> propertyMap3 = 
+            new HashMap<String, Object>() {
+            { 
+                put(PROP_ID_INT, new Integer(123));
+                put(PROP_ID_STRING, "ZZZZ");
+            }};           
+        folder11 = createFolder("Folder 11", folder1, FOLDER_TYPE, propertyMap3);
+    }
+    
+
+    private String createFolder(String folderName, String parentFolderId, String typeId, Map<String, Object> properties) {
+        Properties props = createFolderProperties(folderName, typeId, properties);
+        String id = null;
+        try {
+            id = fObjSvc.createFolder(repositoryId, props, parentFolderId, null, null, null, null);
+            if (null == id)
+                fail("createFolder failed.");
+        } catch (Exception e) {
+            fail("createFolder() failed with exception: " + e);
+        }
+        return id;
+    }
+
+    private String createDocument(String name, String folderId, String typeId, Map<String, Object> properties) {
+        ContentStream contentStream = null;
+        List<String> policies = null;
+        Acl addACEs = null;
+        Acl removeACEs = null;
+        ExtensionsData extension = null;
+
+        Properties props = createDocumentProperties(name, typeId, properties);
+
+        String id = null;
+        try {
+            id = fObjSvc.createDocument(repositoryId, props, folderId, contentStream, VersioningState.NONE, policies,
+                    addACEs, removeACEs, extension);
+            if (null == id)
+                fail("createDocument failed.");
+        } catch (Exception e) {
+            fail("createDocument() failed with exception: " + e);
+        }
+        return id;
+
+    }
+
+    private Properties createDocumentProperties(String name, String typeId, Map<String, Object> propertyMap) {
+        List<PropertyData<?>> properties = new ArrayList<PropertyData<?>>();
+        properties.add(fFactory.createPropertyIdData(PropertyIds.NAME, name));
+        properties.add(fFactory.createPropertyIdData(PropertyIds.OBJECT_TYPE_ID, typeId));
+        for (Map.Entry<String,Object> propEntry :propertyMap.entrySet()) {
+            PropertyData<?> pd =
+            createPropertyData(propEntry.getKey(), propEntry.getValue());
+            properties.add(pd);
+        }
+        Properties props = fFactory.createPropertiesData(properties);
+        return props;
+    }
+
+    private Properties createFolderProperties(String folderName, String typeId, Map<String, Object> propertyMap) {
+        List<PropertyData<?>> properties = new ArrayList<PropertyData<?>>();
+        properties.add(fFactory.createPropertyIdData(PropertyIds.NAME, folderName));
+        properties.add(fFactory.createPropertyIdData(PropertyIds.OBJECT_TYPE_ID, typeId));
+        for (Map.Entry<String,Object> propEntry :propertyMap.entrySet()) {
+            PropertyData<?> pd =
+            createPropertyData(propEntry.getKey(), propEntry.getValue());
+            properties.add(pd);
+        }
+        Properties props = fFactory.createPropertiesData(properties);
+        return props;
+    }
+        
+
+    /**
+     * Simplified property creation method, create Property of Boolean, String, Integer,
+     * Decimal, or DataTime depending on class of value (Boolean, String, Integer, Double,
+     * or GregorianCalendar. Id, Html and URI are not supported
+     * 
+     * @param propId
+     * @param value
+     * @return
+     */
+    private PropertyData<?> createPropertyData (String propId, Object value) {
+        Class<?> clazz = value.getClass();
+        if (clazz.equals(Boolean.class)) {
+            return fFactory.createPropertyBooleanData(propId, (Boolean)value);
+        } else if (clazz.equals(Double.class)) {
+            return fFactory.createPropertyDecimalData(propId, BigDecimal.valueOf((Double)value));
+        } else if (clazz.equals(Integer.class)) {
+            return fFactory.createPropertyIntegerData(propId, BigInteger.valueOf((Integer)value));
+        } else if (clazz.equals(String.class)) {
+            return fFactory.createPropertyStringData(propId, (String)value);
+        } else if (clazz.equals(GregorianCalendar.class)) {
+            return fFactory.createPropertyDateTimeData(propId, (GregorianCalendar)value);
+        } else
+            fail("unsupported type in propery value: " + clazz);
+        return null;
+    }
+}

Added: incubator/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/incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/QueryTypesTest.java?rev=954587&view=auto
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/QueryTypesTest.java (added)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/query/QueryTypesTest.java Mon Jun 14 18:51:24 2010
@@ -0,0 +1,422 @@
+/*
+ * 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.List;
+import java.util.Map;
+
+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.query.CmisQueryWalker;
+import org.apache.chemistry.opencmis.inmemory.query.CmisSelector;
+import org.apache.chemistry.opencmis.inmemory.query.ColumnReference;
+import org.apache.chemistry.opencmis.inmemory.query.QueryObject;
+import org.apache.chemistry.opencmis.inmemory.query.QueryObject.SortSpec;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class QueryTypesTest extends AbstractQueryTest {
+    
+    private TypeManagerImpl tm;
+
+    @Before
+    public void setUp() throws Exception {
+        tm = new TypeManagerImpl();
+        tm.initTypeSystem(null); // create CMIS default types
+        
+        // create some types for testing
+        List<TypeDefinition> typeDefs = super.createTypes();
+        for (TypeDefinition typeDef : typeDefs)
+            tm.addTypeDefinition(typeDef);
+        
+        // initialize query object with type manager
+        super.setUp(new QueryObject(tm, null));
+    }
+
+    @After
+    public void tearDown() throws Exception {
+    }
+
+    @Test
+    public void resolveTypesTest1() throws Exception {
+        String statement = "SELECT " + TITLE_PROP + ", " + AUTHOR_PROP + " FROM " + BOOK_TYPE + " AS BooksAlias WHERE " + ISBN_PROP + " = '100'"; 
+        verifyResolveSelect(statement);
+    }
+    
+    @Test
+    public void resolveTypesTest2() throws Exception {
+        String statement = "SELECT BookType.Title, BookType.Author FROM BookType WHERE ISBN = '100'"; 
+        verifyResolveSelect(statement);
+    }
+
+    @Test
+    public void resolveTypesTest3() throws Exception {
+        String statement = "SELECT BookType.Title, BookType.Author FROM BookType AS BooksAlias WHERE ISBN = '100'"; 
+        verifyResolveSelect(statement);
+    }
+    
+    @Test
+    public void resolveTypesTest4() throws Exception {
+        String statement = "SELECT BooksAlias.Title, BooksAlias.Author FROM BookType AS BooksAlias WHERE ISBN = '100'"; 
+        verifyResolveSelect(statement);
+    }
+
+    @Test
+    public void resolveTypesTest5() throws Exception {
+        String statement = "SELECT BooksAlias.Title AS abc, BooksAlias.Author def FROM BookType AS BooksAlias WHERE ISBN = '100'"; 
+        verifyResolveSelect(statement);
+    }
+
+    @Test
+    public void resolveTypesTest6() throws Exception {
+        String statement = "SELECT BookType.UnknownProperty FROM BookType WHERE ISBN = '100'";
+        try {
+            verifyResolveSelect(statement);
+            fail("Select of unknown property in type should fail.");
+        } catch (Exception e) {
+            assertTrue(e instanceof CmisInvalidArgumentException);
+            assertTrue(e.getMessage().contains("is not a valid property query name in"));
+        }
+    }
+
+    @Test
+    public void resolveTypesTest7() throws Exception {
+        String statement = "SELECT UnknownProperty FROM BookType WHERE ISBN = '100'";
+        try {
+            verifyResolveSelect(statement);
+            fail("Select of unknown property in type should fail.");
+        } catch (Exception e) {
+            assertTrue(e instanceof CmisInvalidArgumentException);
+            assertTrue(e.getMessage().contains("is not a property query name in any"));
+        }
+    }
+
+    @Test
+    public void resolveTypesTest8() throws Exception {
+        String statement = "SELECT BookType.Title, BookType.Author FROM BookType WHERE ISBN = '100'"; 
+        verifyResolveSelect(statement);
+    }
+
+    @Test
+    public void resolveTypesTest9() throws Exception {
+        String statement = "SELECT BookType.Author, Title TitleAlias FROM BookType WHERE TitleAlias <> 'Harry Potter'"; 
+        verifyResolveSelect(statement);
+    }
+
+    @Test
+    public void resolveTypesTest10() throws Exception {
+        String statement = "SELECT BookType.Author, BookType.Title TitleAlias FROM BookType WHERE TitleAlias <> 'Harry Potter'"; 
+        verifyResolveSelect(statement);
+    }
+
+    private void verifyResolveSelect(String statement) throws Exception {
+        CmisQueryWalker walker = traverseStatement(statement);
+        QueryObject qo = walker.queryObj;
+        Map<String,String> types = qo.getTypes();
+        assertTrue(1 == types.size());
+        List<CmisSelector> selects = qo.getSelectReferences();
+        assertTrue(2 == selects.size());
+        for (CmisSelector select : selects) {
+            assertTrue(select instanceof ColumnReference);
+            ColumnReference colRef = ((ColumnReference) select);
+            assertEquals(bookType, colRef.getTypeDefinition());
+            assertTrue(colRef.getPropertyQueryName().equals(TITLE_PROP) || colRef.getPropertyQueryName().equals(AUTHOR_PROP));
+        }
+    }
+    
+    @Test
+    public void resolveTypesWithTwoFromsQualified() throws Exception {
+        String statement = "SELECT BookType.Title, MyDocType.MyStringProp FROM BookType JOIN MyDocType WHERE BookType.ISBN = '100'"; 
+        
+        CmisQueryWalker walker = traverseStatement(statement);
+        QueryObject qo = walker.queryObj;
+        Map<String,String> types = qo.getTypes();
+        assertTrue(2 == types.size());
+        List<CmisSelector> selects = qo.getSelectReferences();
+        assertTrue(2 == selects.size());
+
+        ColumnReference colRef = ((ColumnReference) selects.get(0));
+        assertEquals(colRef.getTypeDefinition(), bookType);
+        assertTrue(colRef.getPropertyQueryName().equals(TITLE_PROP));
+
+        colRef = ((ColumnReference) selects.get(1));
+        assertEquals(colRef.getTypeDefinition(), myType);
+        assertTrue(colRef.getPropertyQueryName().equals(STRING_PROP));        
+    }
+
+    @Test
+    public void resolveTypesWithTwoFromsUnqualified() throws Exception {
+        String statement = "SELECT Title, MyStringProp FROM BookType JOIN MyDocType AS MyDocAlias WHERE BookType.ISBN = '100'"; 
+        
+        CmisQueryWalker walker = traverseStatement(statement);
+        QueryObject qo = walker.queryObj;
+        Map<String,String> types = qo.getTypes();
+        assertTrue(2 == types.size());
+        List<CmisSelector> selects = qo.getSelectReferences();
+        assertTrue(2 == selects.size());
+
+        ColumnReference colRef = ((ColumnReference) selects.get(0));
+        assertEquals(colRef.getTypeDefinition(), bookType);
+        assertTrue(colRef.getPropertyQueryName().equals(TITLE_PROP));
+
+        colRef = ((ColumnReference) selects.get(1));
+        assertEquals(colRef.getTypeDefinition(), myType);
+        assertTrue(colRef.getPropertyQueryName().equals(STRING_PROP));        
+    }
+
+    @Test
+    public void resolveTypesWithTwoFromsNotUnique() throws Exception {
+        String statement = "SELECT MyStringProp FROM MyDocTypeCopy JOIN MyDocType"; 
+        
+        try {
+            traverseStatement(statement);
+            fail("Select with an unqualified property that is not unique should fail.");
+        } catch (Exception e) {
+            assertTrue(e instanceof CmisInvalidArgumentException);
+            assertTrue(e.getMessage().contains("is not a unique property query name within the types in from"));
+        }
+    }
+
+    @Test
+    public void resolveTypesWithTwoFromsUniqueByQualifying() throws Exception {
+        String statement = "SELECT MyDocType.MyStringProp FROM MyDocTypeCopy JOIN MyDocType"; 
+        
+        CmisQueryWalker walker = traverseStatement(statement);
+        QueryObject qo = walker.queryObj;
+        Map<String,String> types = qo.getTypes();
+        assertTrue(2 == types.size());
+        List<CmisSelector> selects = qo.getSelectReferences();
+        assertTrue(1 == selects.size());
+        ColumnReference colRef = ((ColumnReference) selects.get(0));
+        assertEquals(myType, colRef.getTypeDefinition());
+        assertTrue(colRef.getPropertyQueryName().equals(STRING_PROP));        
+    }
+
+    @Test
+    public void resolveTypesTest11() throws Exception {
+        String statement = "SELECT BookType.* FROM BookType WHERE ISBN = '100'"; 
+        CmisQueryWalker walker = traverseStatement(statement);
+        QueryObject qo = walker.queryObj;
+        Map<String,String> types = qo.getTypes();
+        assertTrue(1 == types.size());
+        List<CmisSelector> selects = qo.getSelectReferences();
+        assertTrue(1 == selects.size());
+        ColumnReference colRef = ((ColumnReference) selects.get(0));
+        assertTrue(colRef.getPropertyQueryName().equals("*"));        
+        assertEquals(bookType, colRef.getTypeDefinition());
+    }
+
+    @Test
+    public void resolveTypesTest12() throws Exception {
+        String statement = "SELECT * FROM MyDocTypeCopy JOIN MyDocType"; 
+        CmisQueryWalker walker = traverseStatement(statement);
+        QueryObject qo = walker.queryObj;
+        Map<String,String> types = qo.getTypes();
+        assertTrue(2 == types.size());
+        List<CmisSelector> selects = qo.getSelectReferences();
+        assertTrue(1 == selects.size());
+        ColumnReference colRef = ((ColumnReference) selects.get(0));
+        assertTrue(colRef.getPropertyQueryName().equals("*"));        
+        assertEquals(null, colRef.getTypeDefinition());
+    }
+    
+    @Test
+    public void resolveTypesWhere1() throws Exception {
+        String statement = "SELECT * FROM BookType WHERE ISBN = '100'"; 
+        verifyResolveWhere(statement);
+    }
+
+    @Test
+    public void resolveTypesWhere2() throws Exception {
+        String statement = "SELECT * FROM BookType WHERE BookType.ISBN = '100'"; 
+        verifyResolveWhere(statement);
+    }
+
+    @Test
+    public void resolveTypesWhere3() throws Exception {
+        String statement = "SELECT * FROM BookType As BookAlias WHERE BookAlias.ISBN = '100'"; 
+        verifyResolveWhere(statement);
+    }
+
+    @Test
+    public void resolveTypesWhere4() throws Exception {
+        String statement = "SELECT BookType.ISBN IsbnAlias FROM BookType WHERE IsbnAlias < '100'"; 
+        verifyResolveWhere(statement);
+    }
+
+    @Test
+    public void resolveTypesWhereWithTwoFromsUnqualified() throws Exception {
+        String statement = "SELECT * FROM BookType JOIN MyDocType WHERE ISBN = '100'"; 
+        CmisQueryWalker walker = traverseStatement(statement);
+        QueryObject qo = walker.queryObj;
+        List<CmisSelector> wheres = qo.getWhereReferences();
+        assertTrue(1 == wheres.size());
+        for (CmisSelector where : wheres) {
+            assertTrue(where instanceof ColumnReference);
+            ColumnReference colRef = ((ColumnReference) where);
+            assertEquals(colRef.getTypeDefinition(), bookType);
+            assertTrue(colRef.getPropertyQueryName().equals(ISBN_PROP));
+        }
+    }
+
+    @Test
+    public void resolveTypesWhereWithTwoFromsQualified() throws Exception {
+        String statement = "SELECT * FROM BookType JOIN MyDocType AS MyDocAlias WHERE BookType.ISBN = '100'"; 
+        CmisQueryWalker walker = traverseStatement(statement);
+        QueryObject qo = walker.queryObj;
+        List<CmisSelector> wheres = qo.getWhereReferences();
+        assertTrue(1 == wheres.size());
+        for (CmisSelector where : wheres) {
+            assertTrue(where instanceof ColumnReference);
+            ColumnReference colRef = ((ColumnReference) where);
+            assertEquals(colRef.getTypeDefinition(), bookType);
+            assertTrue(colRef.getPropertyQueryName().equals(ISBN_PROP));
+        }
+    }
+    
+
+    @Test
+    public void resolveTypesWhereWithTwoFromsQualifiedWithAlias() throws Exception {
+        String statement = "SELECT * FROM BookType AS MyBookAlias JOIN MyDocType  WHERE MyBookAlias.ISBN = '100'"; 
+        CmisQueryWalker walker = traverseStatement(statement);
+        QueryObject qo = walker.queryObj;
+        List<CmisSelector> wheres = qo.getWhereReferences();
+        assertTrue(1 == wheres.size());
+        for (CmisSelector where : wheres) {
+            assertTrue(where instanceof ColumnReference);
+            ColumnReference colRef = ((ColumnReference) where);
+            assertEquals(colRef.getTypeDefinition(), bookType);
+            assertTrue(colRef.getPropertyQueryName().equals(ISBN_PROP));
+        }
+    }
+
+    private void verifyResolveWhere(String statement) throws Exception {
+        CmisQueryWalker walker = traverseStatement(statement);
+        QueryObject qo = walker.queryObj;
+        Map<String,String> types = qo.getTypes();
+        assertTrue(1 == types.size());
+        List<CmisSelector> wheres = qo.getWhereReferences();
+        assertTrue(1 == wheres.size());
+        for (CmisSelector where : wheres) {
+            assertTrue(where instanceof ColumnReference);
+            ColumnReference colRef = ((ColumnReference) where);
+            assertEquals(bookType, colRef.getTypeDefinition());
+            assertTrue(colRef.getPropertyQueryName().equals(ISBN_PROP));
+        }
+    }
+
+    @Test
+    public void resolveTypesWhereWithTwoFromsNotUnique() throws Exception {
+        String statement = "SELECT * FROM MyDocTypeCopy JOIN MyDocType WHERE MyStringProp = '100'"; 
+        
+        try {
+            CmisQueryWalker walker = traverseStatement(statement);
+            fail("Select with an unqualified property that is not unique should fail.");
+        } catch (Exception e) {
+            assertTrue(e instanceof CmisInvalidArgumentException);
+            assertTrue(e.getMessage().contains("is not a unique property query name within the types in from"));
+        }
+    }
+    
+    @Test
+    public void resolveTypesWhereWithTwoFromsUniqueByQualifying() throws Exception {
+        String statement = "SELECT * FROM MyDocTypeCopy JOIN MyDocType WHERE MyDocType.MyStringProp = '100'";         
+        CmisQueryWalker walker = traverseStatement(statement);
+        QueryObject qo = walker.queryObj;
+        List<CmisSelector> wheres = qo.getWhereReferences();
+        assertTrue(1 == wheres.size());
+        for (CmisSelector where : wheres) {
+            assertTrue(where instanceof ColumnReference);
+            ColumnReference colRef = ((ColumnReference) where);
+            assertEquals(colRef.getTypeDefinition(), myType);
+            assertTrue(colRef.getPropertyQueryName().equals(STRING_PROP));
+        }
+    }
+
+    @Test
+    public void resolveTypesOrderBy() throws Exception {
+        String statement = "SELECT Title AS TitleAlias FROM BookType WHERE Author = 'Jim' ORDER BY TitleAlias";         
+        CmisQueryWalker walker = traverseStatement(statement);
+        QueryObject qo = walker.queryObj;
+        List<SortSpec> sorts = qo.getOrderBys();
+        assertTrue(1 == sorts.size());
+        for (SortSpec sort : sorts) {
+            assertTrue(sort.getSelector() instanceof ColumnReference);
+            ColumnReference colRef = ((ColumnReference) sort.getSelector());
+            assertEquals(colRef.getTypeDefinition(), bookType);
+            assertTrue(colRef.getPropertyQueryName().equals(TITLE_PROP));
+        }
+    }
+
+    @Test
+    public void resolveTypesOrderBy2() throws Exception {
+        String statement = "SELECT Title AS TitleAlias FROM BookType WHERE Author = 'Jim' ORDER BY BookType.Author";         
+        CmisQueryWalker walker = traverseStatement(statement);
+        QueryObject qo = walker.queryObj;
+        List<SortSpec> sorts = qo.getOrderBys();
+        assertTrue(1 == sorts.size());
+        for (SortSpec sort : sorts) {
+            assertTrue(sort.getSelector() instanceof ColumnReference);
+            ColumnReference colRef = ((ColumnReference) sort.getSelector());
+            assertEquals(colRef.getTypeDefinition(), bookType);
+            assertTrue(colRef.getPropertyQueryName().equals(AUTHOR_PROP));
+        }
+    }
+
+    @Test
+    public void resolveTypesOrderBy3() throws Exception {
+        String statement = "SELECT Title FROM BookType WHERE ISBN < '100' ORDER BY Author";         
+        CmisQueryWalker walker = traverseStatement(statement);
+        QueryObject qo = walker.queryObj;
+        List<SortSpec> sorts = qo.getOrderBys();
+        assertTrue(1 == sorts.size());
+        for (SortSpec sort : sorts) {
+            assertTrue(sort.getSelector() instanceof ColumnReference);
+            ColumnReference colRef = ((ColumnReference) sort.getSelector());
+            assertEquals(colRef.getTypeDefinition(), bookType);
+            assertTrue(colRef.getPropertyQueryName().equals(AUTHOR_PROP));
+        }
+    }
+
+    @Test
+    public void resolveJoinTypesSimple() throws Exception {
+        String statement = "SELECT * FROM MyDocType JOIN BookType ON MyDocType.MyStringProp = BookType.Title";         
+        CmisQueryWalker walker = traverseStatement(statement);
+        QueryObject qo = walker.queryObj;
+        List<CmisSelector> joins = qo.getJoinReferences();
+        assertTrue(2 == joins.size());
+        for (CmisSelector join : joins) {
+            assertTrue(join instanceof ColumnReference);
+            ColumnReference colRef = ((ColumnReference) join);
+            if (myType.equals(colRef.getTypeDefinition())) {
+                assertTrue(colRef.getPropertyQueryName().equals(STRING_PROP));
+            } else if (bookType.equals(colRef.getTypeDefinition())) {
+                assertTrue(colRef.getPropertyQueryName().equals(TITLE_PROP));
+            } else 
+                fail("Unexpected type in JOIN reference");
+        }
+    }
+
+}