collection = DefaultTypeConverter.INSTANCE.getCollection(Boolean.class, sValue);
            assertEquals(2, collection.size());
            Boolean[] members = new Boolean[2];
            members = collection.toArray(members);
            assertEquals(Boolean.TRUE, members[0]);
            assertEquals(Boolean.FALSE, members[1]);
            column = rs.getResultSetMetaData().getColumn("test:multipleBoolean");
            assertEquals(PropertyType.BOOLEAN, column.getCMISDataType());
            assertEquals(Cardinality.MULTI, column.getCMISPropertyDefinition().getPropertyDefinition().getCardinality());
        }
        rs.close();
        // d:boolean single
        testQuery("SELECT * FROM test:extendedContent WHERE test:singleBoolean = TRUE", 1, false, "cmis:name", new String(), false);
        testQuery("SELECT * FROM test:extendedContent WHERE test:singleBoolean = true", 1, false, "cmis:name", new String(), false);
        testQuery("SELECT * FROM test:extendedContent WHERE test:singleBoolean = FALSE", 0, false, "cmis:name", new String(), false);
        testQuery("SELECT * FROM test:extendedContent WHERE test:singleBoolean = false", 0, false, "cmis:name", new String(), false);
        // not strictly compliant...
        testQuery("SELECT * FROM test:extendedContent WHERE test:singleBoolean = TRue", 1, false, "cmis:name", new String(), false);
        testQuery("SELECT * FROM test:extendedContent WHERE test:singleBoolean <> TRUE", 0, false, "cmis:name", new String(), true);
        testQuery("SELECT * FROM test:extendedContent WHERE test:singleBoolean <> FALSE", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT * FROM test:extendedContent WHERE test:singleBoolean < TRUE", 0, false, "cmis:name", new String(), true);
        testQuery("SELECT * FROM test:extendedContent WHERE test:singleBoolean < FALSE", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT * FROM test:extendedContent WHERE test:singleBoolean <= TRUE", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT * FROM test:extendedContent WHERE test:singleBoolean <= FALSE", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT * FROM test:extendedContent WHERE test:singleBoolean > TRUE", 0, false, "cmis:name", new String(), true);
        testQuery("SELECT * FROM test:extendedContent WHERE test:singleBoolean > FALSE", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT * FROM test:extendedContent WHERE test:singleBoolean >= TRUE", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT * FROM test:extendedContent WHERE test:singleBoolean >= FALSE", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT * FROM test:extendedContent WHERE test:singleBoolean LIKE 'TRUE'", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT * FROM test:extendedContent WHERE test:singleBoolean NOT LIKE 'FALSE'", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT * FROM test:extendedContent WHERE test:singleBoolean IN (TRUE)", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT * FROM test:extendedContent WHERE test:singleBoolean NOT IN (FALSE)", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT * FROM test:extendedContent WHERE TRUE =  ANY test:singleBoolean ", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT * FROM test:extendedContent WHERE FALSE =  ANY test:singleBoolean ", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT * FROM test:extendedContent WHERE ANY test:singleBoolean IN (TRUE)", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT * FROM test:extendedContent WHERE ANY test:singleBoolean NOT IN (FALSE)", 1, false, "cmis:name", new String(), true);
        // d:boolean single by alias
        testQuery("SELECT test:singleBoolean alias FROM test:extendedContent WHERE alias = TRUE", 1, false, "cmis:name", new String(), false);
        testQuery("SELECT test:singleBoolean alias FROM test:extendedContent WHERE alias = true", 1, false, "cmis:name", new String(), false);
        testQuery("SELECT test:singleBoolean alias FROM test:extendedContent WHERE alias = FALSE", 0, false, "cmis:name", new String(), false);
        testQuery("SELECT test:singleBoolean alias FROM test:extendedContent WHERE alias = false", 0, false, "cmis:name", new String(), false);
        // not strictly compliant...
        testQuery("SELECT test:singleBoolean alias FROM test:extendedContent WHERE alias = TRue", 1, false, "cmis:name", new String(), false);
        testQuery("SELECT test:singleBoolean alias FROM test:extendedContent WHERE alias <> TRUE", 0, false, "cmis:name", new String(), true);
        testQuery("SELECT test:singleBoolean alias FROM test:extendedContent WHERE alias <> FALSE", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT test:singleBoolean alias FROM test:extendedContent WHERE alias < TRUE", 0, false, "cmis:name", new String(), true);
        testQuery("SELECT test:singleBoolean alias FROM test:extendedContent WHERE alias < FALSE", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT test:singleBoolean alias FROM test:extendedContent WHERE alias <= TRUE", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT test:singleBoolean alias FROM test:extendedContent WHERE alias <= FALSE", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT test:singleBoolean alias FROM test:extendedContent WHERE alias > TRUE", 0, false, "cmis:name", new String(), true);
        testQuery("SELECT test:singleBoolean alias FROM test:extendedContent WHERE alias > FALSE", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT test:singleBoolean alias FROM test:extendedContent WHERE alias >= TRUE", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT test:singleBoolean alias FROM test:extendedContent WHERE alias >= FALSE", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT test:singleBoolean alias FROM test:extendedContent WHERE alias LIKE 'TRUE'", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT test:singleBoolean alias FROM test:extendedContent WHERE alias NOT LIKE 'FALSE'", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT test:singleBoolean alias FROM test:extendedContent WHERE alias IN (TRUE)", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT test:singleBoolean alias FROM test:extendedContent WHERE alias NOT IN (FALSE)", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT test:singleBoolean alias FROM test:extendedContent WHERE TRUE =  ANY alias ", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT test:singleBoolean alias FROM test:extendedContent WHERE FALSE =  ANY alias ", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT test:singleBoolean alias FROM test:extendedContent WHERE ANY alias IN (TRUE)", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT test:singleBoolean alias FROM test:extendedContent WHERE ANY alias NOT IN (FALSE)", 1, false, "cmis:name", new String(), true);
        // d:boolean multiple
        testQuery("SELECT * FROM test:extendedContent WHERE test:multipleBoolean = 1", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT * FROM test:extendedContent WHERE test:multipleBoolean = 2", 0, false, "cmis:name", new String(), true);
        testQuery("SELECT * FROM test:extendedContent WHERE test:multipleBoolean <> 1", 0, false, "cmis:name", new String(), true);
        testQuery("SELECT * FROM test:extendedContent WHERE test:multipleBoolean <> 2", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT * FROM test:extendedContent WHERE test:multipleBoolean < 1", 0, false, "cmis:name", new String(), true);
        testQuery("SELECT * FROM test:extendedContent WHERE test:multipleBoolean < 2", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT * FROM test:extendedContent WHERE test:multipleBoolean <= 1", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT * FROM test:extendedContent WHERE test:multipleBoolean <= 2", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT * FROM test:extendedContent WHERE test:multipleBoolean > 1", 0, false, "cmis:name", new String(), true);
        testQuery("SELECT * FROM test:extendedContent WHERE test:multipleBoolean > 0", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT * FROM test:extendedContent WHERE test:multipleBoolean >= 1", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT * FROM test:extendedContent WHERE test:multipleBoolean >= 0", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT * FROM test:extendedContent WHERE test:multipleBoolean LIKE '1'", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT * FROM test:extendedContent WHERE test:multipleBoolean NOT LIKE '2'", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT * FROM test:extendedContent WHERE test:multipleBoolean IN (1, 2)", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT * FROM test:extendedContent WHERE test:multipleBoolean NOT IN (2)", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT * FROM test:extendedContent WHERE '1' =  ANY test:multipleBoolean ", 1, false, "cmis:name", new String(), false);
        testQuery("SELECT * FROM test:extendedContent WHERE '2' =  ANY test:multipleBoolean ", 1, false, "cmis:name", new String(), false);
        testQuery("SELECT * FROM test:extendedContent WHERE ANY test:multipleBoolean IN (1, 2)", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT * FROM test:extendedContent WHERE ANY test:multipleBoolean IN (2, 3)", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT * FROM test:extendedContent WHERE ANY test:multipleBoolean NOT IN (1, 2)", 0, false, "cmis:name", new String(), true);
        testQuery("SELECT * FROM test:extendedContent WHERE ANY test:multipleBoolean NOT IN (2, 3)", 0, false, "cmis:name", new String(), true);
        testQuery("SELECT * FROM test:extendedContent WHERE ANY test:multipleBoolean NOT IN (3, 4)", 1, false, "cmis:name", new String(), true);
        // d:boolean multiple by alias
        testQuery("SELECT test:multipleBoolean as alias FROM test:extendedContent WHERE alias = 1", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT test:multipleBoolean as alias FROM test:extendedContent WHERE alias = 2", 0, false, "cmis:name", new String(), true);
        testQuery("SELECT test:multipleBoolean as alias FROM test:extendedContent WHERE alias <> 1", 0, false, "cmis:name", new String(), true);
        testQuery("SELECT test:multipleBoolean as alias FROM test:extendedContent WHERE alias <> 2", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT test:multipleBoolean as alias FROM test:extendedContent WHERE alias < 1", 0, false, "cmis:name", new String(), true);
        testQuery("SELECT test:multipleBoolean as alias FROM test:extendedContent WHERE alias < 2", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT test:multipleBoolean as alias FROM test:extendedContent WHERE alias <= 1", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT test:multipleBoolean as alias FROM test:extendedContent WHERE alias <= 2", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT test:multipleBoolean as alias FROM test:extendedContent WHERE alias > 1", 0, false, "cmis:name", new String(), true);
        testQuery("SELECT test:multipleBoolean as alias FROM test:extendedContent WHERE alias > 0", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT test:multipleBoolean as alias FROM test:extendedContent WHERE alias >= 1", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT test:multipleBoolean as alias FROM test:extendedContent WHERE alias >= 0", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT test:multipleBoolean as alias FROM test:extendedContent WHERE alias LIKE '1'", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT test:multipleBoolean as alias FROM test:extendedContent WHERE alias NOT LIKE '2'", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT test:multipleBoolean as alias FROM test:extendedContent WHERE alias IN (1, 2)", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT test:multipleBoolean as alias FROM test:extendedContent WHERE alias NOT IN (2)", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT test:multipleBoolean as alias FROM test:extendedContent WHERE '1' =  ANY alias ", 1, false, "cmis:name", new String(), false);
        testQuery("SELECT test:multipleBoolean as alias FROM test:extendedContent WHERE '2' =  ANY alias ", 1, false, "cmis:name", new String(), false);
        testQuery("SELECT test:multipleBoolean as alias FROM test:extendedContent WHERE ANY alias IN (1, 2)", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT test:multipleBoolean as alias FROM test:extendedContent WHERE ANY alias IN (2, 3)", 1, false, "cmis:name", new String(), true);
        testQuery("SELECT test:multipleBoolean as alias FROM test:extendedContent WHERE ANY alias NOT IN (1, 2)", 0, false, "cmis:name", new String(), true);
        testQuery("SELECT test:multipleBoolean as alias FROM test:extendedContent WHERE ANY alias NOT IN (2, 3)", 0, false, "cmis:name", new String(), true);
        testQuery("SELECT test:multipleBoolean as alias FROM test:extendedContent WHERE ANY alias NOT IN (3, 4)", 1, false, "cmis:name", new String(), true);
    }
    public void testBasicContainsSyntax() throws Exception
    {
        testQuery("SELECT * FROM cmis:document WHERE CONTAINS('quick')", 1, false, "cmis:name", new String(), false);
        testQuery("SELECT * FROM cmis:document WHERE CONTAINS('one')", 1, false, "cmis:name", new String(), false);
        testQuery("SELECT * FROM cmis:document WHERE CONTAINS('-quick')", doc_count-1, false, "cmis:name", new String(), false);
        testQuery("SELECT * FROM cmis:document WHERE CONTAINS('quick brown fox')", 1, false, "cmis:name", new String(), false);
        testQuery("SELECT * FROM cmis:document WHERE CONTAINS('quick one')", 0, false, "cmis:name", new String(), false);
        testQuery("SELECT * FROM cmis:document WHERE CONTAINS('quick -one')", 1, false, "cmis:name", new String(), false);
        testQuery("SELECT * FROM cmis:document WHERE CONTAINS('-quick one')", 1, false, "cmis:name", new String(), false);
        testQuery("SELECT * FROM cmis:document WHERE CONTAINS('-quick -one')", doc_count-2, false, "cmis:name", new String(), false);
        testQuery("SELECT * FROM cmis:document WHERE CONTAINS('fox brown quick')", 1, false, "cmis:name", new String(), false);
        testQuery("SELECT * FROM cmis:document WHERE CONTAINS('quick OR one')", 2, false, "cmis:name", new String(), false);
        testQuery("SELECT * FROM cmis:document WHERE CONTAINS('quick OR -one')", doc_count-1, false, "cmis:name", new String(), false);
        testQuery("SELECT * FROM cmis:document WHERE CONTAINS('-quick OR -one')", doc_count, false, "cmis:name", new String(), false);
        testQuery("SELECT * FROM cmis:document WHERE CONTAINS('\\'quick brown fox\\'')", 1, false, "cmis:name", new String(), false);
        testQuery("SELECT * FROM cmis:document WHERE CONTAINS('\\'fox brown quick\\'')", 0, false, "cmis:name", new String(), false);
        testQuery("SELECT * FROM cmis:document WHERE CONTAINS('\\'quick brown fox\\' one')", 0, false, "cmis:name", new String(), false);
        testQuery("SELECT * FROM cmis:document WHERE CONTAINS('\\'quick brown fox\\' -one')", 1, false, "cmis:name", new String(), false);
        testQuery("SELECT * FROM cmis:document WHERE CONTAINS('-\\'quick brown fox\\' one')", 1, false, "cmis:name", new String(), false);
        testQuery("SELECT * FROM cmis:document WHERE CONTAINS('-\\'quick brown fox\\' -one')", doc_count-2, false, "cmis:name", new String(), false);
        // escaping
        testExtendedQuery("SELECT * FROM cmis:folder WHERE CONTAINS('cmis:name:\\'Folder 9\\\\\\'\\'')", 1, false, "cmis:name", new String(), false);
        // precedence
        testQuery("SELECT * FROM cmis:document WHERE CONTAINS('quick OR brown one')", 1, false, "cmis:name", new String(), false);
        testExtendedQuery("SELECT * FROM cmis:document WHERE CONTAINS('quick OR brown AND one')", 1, false, "cmis:name", new String(), false);
        testExtendedQuery("SELECT * FROM cmis:document WHERE CONTAINS('quick OR (brown AND one)')", 1, false, "cmis:name", new String(), false);
        testExtendedQuery("SELECT * FROM cmis:document WHERE CONTAINS('(quick OR brown) AND one')", 0, false, "cmis:name", new String(), false);
        testQuery("SELECT * FROM cmis:document WHERE CONTAINS('quick OR brown OR one')", 2, false, "cmis:name", new String(), false);
        testQuery("SELECT * FROM cmis:document WHERE CONTAINS('quick OR brown one')", 1, false, "cmis:name", new String(), false);
    }
    public void testOrderableProperties()
    {
        addTypeSortTestData();
        assertTrue(cmisDictionaryService.findPropertyByQueryName("test:singleTextUntokenised").getPropertyDefinition().isOrderable());
        assertFalse(cmisDictionaryService.findPropertyByQueryName("test:singleTextTokenised").getPropertyDefinition().isOrderable());
        assertTrue(cmisDictionaryService.findPropertyByQueryName("test:singleTextBoth").getPropertyDefinition().isOrderable());
        testOrderableProperty("test:singleTextUntokenised");
        testOrderablePropertyFail("test:singleTextTokenised");
        testOrderableProperty("test:singleTextBoth");
        assertFalse(cmisDictionaryService.findPropertyByQueryName("test:multipleTextUntokenised").getPropertyDefinition().isOrderable());
        assertFalse(cmisDictionaryService.findPropertyByQueryName("test:multipleTextTokenised").getPropertyDefinition().isOrderable());
        assertFalse(cmisDictionaryService.findPropertyByQueryName("test:multipleTextBoth").getPropertyDefinition().isOrderable());
        testOrderablePropertyFail("test:multipleTextUntokenised");
        testOrderablePropertyFail("test:multipleTextTokenised");
        testOrderablePropertyFail("test:multipleTextBoth");
        assertTrue(cmisDictionaryService.findPropertyByQueryName("test:singleMLTextUntokenised").getPropertyDefinition().isOrderable());
        assertFalse(cmisDictionaryService.findPropertyByQueryName("test:singleMLTextTokenised").getPropertyDefinition().isOrderable());
        assertTrue(cmisDictionaryService.findPropertyByQueryName("test:singleMLTextBoth").getPropertyDefinition().isOrderable());
        testOrderableProperty("test:singleMLTextUntokenised");
        testOrderablePropertyFail("test:singleMLTextTokenised");
        testOrderableProperty("test:singleMLTextBoth");
        assertFalse(cmisDictionaryService.findPropertyByQueryName("test:multipleMLTextUntokenised").getPropertyDefinition().isOrderable());
        assertFalse(cmisDictionaryService.findPropertyByQueryName("test:multipleMLTextTokenised").getPropertyDefinition().isOrderable());
        assertFalse(cmisDictionaryService.findPropertyByQueryName("test:multipleMLTextBoth").getPropertyDefinition().isOrderable());
        testOrderablePropertyFail("test:multipleMLTextUntokenised");
        testOrderablePropertyFail("test:multipleMLTextTokenised");
        testOrderablePropertyFail("test:multipleMLTextBoth");
        assertTrue(cmisDictionaryService.findPropertyByQueryName("test:singleFloat").getPropertyDefinition().isOrderable());
        assertFalse(cmisDictionaryService.findPropertyByQueryName("test:multipleFloat").getPropertyDefinition().isOrderable());
        testOrderableProperty("test:singleFloat");
        testOrderablePropertyFail("test:multipleFloat");
        assertTrue(cmisDictionaryService.findPropertyByQueryName("test:singleDouble").getPropertyDefinition().isOrderable());
        assertFalse(cmisDictionaryService.findPropertyByQueryName("test:multipleDouble").getPropertyDefinition().isOrderable());
        testOrderableProperty("test:singleDouble");
        testOrderablePropertyFail("test:multipleDouble");
        assertTrue(cmisDictionaryService.findPropertyByQueryName("test:singleInteger").getPropertyDefinition().isOrderable());
        assertFalse(cmisDictionaryService.findPropertyByQueryName("test:multipleInteger").getPropertyDefinition().isOrderable());
        testOrderableProperty("test:singleInteger");
        testOrderablePropertyFail("test:multipleInteger");
        assertTrue(cmisDictionaryService.findPropertyByQueryName("test:singleLong").getPropertyDefinition().isOrderable());
        assertFalse(cmisDictionaryService.findPropertyByQueryName("test:multipleLong").getPropertyDefinition().isOrderable());
        testOrderableProperty("test:singleLong");
        testOrderablePropertyFail("test:multipleLong");
        assertTrue(cmisDictionaryService.findPropertyByQueryName("test:singleDate").getPropertyDefinition().isOrderable());
        assertFalse(cmisDictionaryService.findPropertyByQueryName("test:multipleDate").getPropertyDefinition().isOrderable());
        testOrderableProperty("test:singleDate");
        testOrderablePropertyFail("test:multipleDate");
        assertTrue(cmisDictionaryService.findPropertyByQueryName("test:singleDatetime").getPropertyDefinition().isOrderable());
        assertFalse(cmisDictionaryService.findPropertyByQueryName("test:multipleDatetime").getPropertyDefinition().isOrderable());
        testOrderableProperty("test:singleDatetime");
        testOrderablePropertyFail("test:multipleDatetime");
        assertTrue(cmisDictionaryService.findPropertyByQueryName("test:singleBoolean").getPropertyDefinition().isOrderable());
        assertFalse(cmisDictionaryService.findPropertyByQueryName("test:multipleBoolean").getPropertyDefinition().isOrderable());
        testOrderableProperty("test:singleBoolean");
        testOrderablePropertyFail("test:multipleBoolean");
    }
    /**
     * MNT-11163 test:
     * 
     * Assume there is a folder 'A' with admin access only and subfolder 'B' with permissions EVERYONE Contributor.
     * The folder's structure:
     *
     *  repository
     *           |
     *            -A
     *             |
     *              -B
     *
     * The CMIS query SELECT * FROM cmis:folder should not raise CmisPermissionDeniedException. Returned path for 'A' or 'B' nodes should be null.
     */
    public void testParentWithPermissions() throws Exception
    {
        String userName = "cmis";
        final String forAdminFolderName = "For admin folder";
        forAdminFolder = nodeService.createNode(base, ContentModel.ASSOC_CONTAINS,
                                                QName.createQName("cm", forAdminFolderName, namespaceService),
                                                ContentModel.TYPE_FOLDER).getChildRef();
        nodeService.setProperty(forAdminFolder, ContentModel.PROP_NAME, forAdminFolderName);
        // deny access for test user to 'forAdminFolder'
        permissionService.setPermission(forAdminFolder, userName, PermissionService.ALL_PERMISSIONS, false);
        String forEveryoneFolderName = "For everyone folder";
        forEveryoneFolder = nodeService.createNode(forAdminFolder,
                                                   ContentModel.ASSOC_CONTAINS,
                                                   QName.createQName("cm", forEveryoneFolderName, namespaceService),
                                                   ContentModel.TYPE_FOLDER).getChildRef();
        nodeService.setProperty(forEveryoneFolder, ContentModel.PROP_NAME, forEveryoneFolderName);
        // set access for test to 'forEveryOneFOlder'
        permissionService.setPermission(forEveryoneFolder, userName, PermissionService.ALL_PERMISSIONS, true);
        final CMISQueryOptions options = new CMISQueryOptions("SELECT * FROM cmis:folder", rootNodeRef.getStoreRef());
        AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork()
        {
            @Override
            public Serializable doWork() throws Exception
            {
                CMISResultSet rs = cmisQueryService.query(options);
                for (CMISResultSetRow row : rs)
                {
                    if (!row.getNodeRef().equals(base))
                    {
                        NodeRef ref = row.getNodeRef();
                        if (ref.equals(forEveryoneFolder))
                        {
                            Serializable sValue = row.getValue("cmis:path");
                            assertEquals("The path for '" + forAdminFolderName + "' should be null", null, sValue);
                        }
                        else if (ref.equals(forAdminFolder))
                        {
                            assertTrue("Should not get the path for '" + forAdminFolderName + "'",false);
                        }
                    }
                }
                return null;
            }
        }, userName);
    }
    public void testNonQueryableTypes() throws Exception
    {
        testQuery("SELECT * FROM cmis:policy", 0, false, "cmis:name", new String(), true);
        testQuery("SELECT * FROM cmis:relationship ", 0, false, "cmis:name", new String(), true);
        testQuery("SELECT * FROM cm:ownable ", 0, false, "cmis:name", new String(), true);
        testExtendedQuery("SELECT * FROM cm:ownable ", 1, false, "cmis:name", new String(), false);
    }
    
    public void testTitled() throws Exception
    {
    	 testExtendedQuery("SELECT * FROM cm:titled where cm:title is null ", 0, false, "cmis:name", new String(), false);
    	 testExtendedQuery("SELECT * FROM cm:titled where cm:title is not null ", 11, false, "cmis:name", new String(), false);
    	 nodeService.setProperty(c10, ContentModel.PROP_TITLE, null);
    	 testExtendedQuery("SELECT * FROM cm:titled where cm:title is null ", 1, false, "cmis:name", new String(), false);
    	 testExtendedQuery("SELECT * FROM cm:titled where cm:title is not null ", 10, false, "cmis:name", new String(), false);
    	 nodeService.setProperty(c10, ContentModel.PROP_TITLE, "meep");
    	 testExtendedQuery("SELECT * FROM cm:titled where cm:title is null ", 0, false, "cmis:name", new String(), false);
    	 testExtendedQuery("SELECT * FROM cm:titled where cm:title is not null ", 11, false, "cmis:name", new String(), false);
    	 nodeService.removeProperty(c10, ContentModel.PROP_TITLE);
    	 testExtendedQuery("SELECT * FROM cm:titled where cm:title is null ", 1, false, "cmis:name", new String(), false);
    	 testExtendedQuery("SELECT * FROM cm:titled where cm:title is not null ", 10, false, "cmis:name", new String(), false);
    }
    
    public void testNotKeyword() throws Exception
    {
    	final String folderName = "testfolder" + GUID.generate();
        final String docName = "testdoc." + GUID.generate();
        final FileInfo fileInfo = transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback()
        {
            @Override
            public FileInfo execute() throws Throwable
            {
                FileInfo folderInfo = fileFolderService.create(base, folderName, ContentModel.TYPE_FOLDER);
                nodeService.setProperty(folderInfo.getNodeRef(), ContentModel.PROP_NAME, folderName);
               
                FileInfo fileInfo = fileFolderService.create(folderInfo.getNodeRef(), docName, ContentModel.TYPE_CONTENT);
                nodeService.setProperty(fileInfo.getNodeRef(), ContentModel.PROP_NAME, docName);
                nodeService.addAspect(fileInfo.getNodeRef(), ContentModel.ASPECT_VERSIONABLE, null);
                return fileInfo;
            }
        });
        
        String query = "SELECT * FROM cmis:document WHERE NOT cmis:name = '" + docName + "'";
        CMISQueryOptions options = new CMISQueryOptions(query, rootNodeRef.getStoreRef());
        
        CMISResultSet rs = cmisQueryService.query(options);
        
        assertEquals(doc_count, rs.length());
        for (CMISResultSetRow row : rs)
        {
            Serializable sValue = row.getValue("cmis:name");
            assertFalse(sValue.equals(docName));
        }
        
        query = "SELECT cmis:name FROM cmis:document WHERE cmis:name = '" + docName + "'";
        options = new CMISQueryOptions(query, rootNodeRef.getStoreRef());
        
        rs = cmisQueryService.query(options);
        
        assertEquals(1, rs.length());
        CMISResultSetRow row = rs.iterator().next();
        
        Serializable sValue = row.getValue("cmis:name");
        assertTrue(sValue.equals(docName));
        
        fileFolderService.delete(fileInfo.getNodeRef());
        
    }
    
    private void testOrderableProperty(String propertyQueryName)
    {
        testOrderBy("SELECT " + propertyQueryName + " FROM test:extendedContent ORDER BY " + propertyQueryName + " ASC", 13, false, Order.ASCENDING, CMISQueryMode.CMS_STRICT,
                propertyQueryName);
        testOrderBy("SELECT " + propertyQueryName + " FROM test:extendedContent ORDER BY " + propertyQueryName + " DESC", 13, false, Order.DESCENDING, CMISQueryMode.CMS_STRICT,
                propertyQueryName);
        testOrderBy("SELECT " + propertyQueryName + " FROM test:extendedContent ORDER BY " + propertyQueryName + " DESC", 13, true, Order.ASCENDING, CMISQueryMode.CMS_STRICT,
                propertyQueryName);
    }
    private void testOrderablePropertyFail(String propertyQueryName)
    {
        testOrderBy("SELECT " + propertyQueryName + " FROM test:extendedContent ORDER BY " + propertyQueryName + " ASC", 13, true, Order.ASCENDING, CMISQueryMode.CMS_STRICT,
                propertyQueryName);
        testOrderBy("SELECT " + propertyQueryName + " FROM test:extendedContent ORDER BY " + propertyQueryName + " DESC", 13, true, Order.DESCENDING, CMISQueryMode.CMS_STRICT,
                propertyQueryName);
        testOrderBy("SELECT " + propertyQueryName + " FROM test:extendedContent ORDER BY " + propertyQueryName + " DESC", 13, true, Order.ASCENDING, CMISQueryMode.CMS_STRICT,
                propertyQueryName);
    }
    private void addTypeTestDataModel()
    {
        // load in the test model
        ClassLoader cl = BaseNodeServiceTest.class.getClassLoader();
        InputStream modelStream = cl.getResourceAsStream("org/alfresco/cmis/search/CMIS-query-test-model.xml");
        assertNotNull(modelStream);
        M2Model model = M2Model.createModel(modelStream);
        dictionaryDAO.putModel(model);
        ((CMISAbstractDictionaryService) cmisDictionaryService).afterDictionaryDestroy();
        ((CMISAbstractDictionaryService) cmisDictionaryService).afterDictionaryInit();
    }
    private void addTypeSortTestData()
    {
        addTypeTestDataModel();
        addSortableNull("start");
        for (int i = 0; i < 10; i++)
        {
            addSortableNode(i);
            if (i == 5)
            {
                addSortableNull("mid");
            }
        }
        addSortableNull("end");
    }
    private NodeRef addSortableNull(String id)
    {
        Map properties = new HashMap();
        MLText ml = new MLText();
        ml.addValue(Locale.ENGLISH, "Test null");
        properties.put(ContentModel.PROP_DESCRIPTION, ml);
        properties.put(ContentModel.PROP_TITLE, ml);
        properties.put(ContentModel.PROP_NAME, "Test null "+id);
        properties.put(ContentModel.PROP_CREATED, new Date());
        NodeRef c0 = nodeService.createNode(f0, ContentModel.ASSOC_CONTAINS, QName.createQName("cm", "Test One", namespaceService), extendedContent, properties).getChildRef();
        return c0;
    }
    private static String[] orderable = new String[] { "zero loons", "one banana", "two apples", "three fruit", "four lemurs", "five rats", "six badgers", "seven cards",
            "eight cabbages", "nine zebras", "ten lemons" };
    private NodeRef addSortableNode(int position)
    {
        Map properties = new HashMap();
        MLText ml = new MLText();
        ml.addValue(Locale.ENGLISH, "Test " + position);
        properties.put(ContentModel.PROP_DESCRIPTION, ml);
        properties.put(ContentModel.PROP_TITLE, ml);
        properties.put(ContentModel.PROP_NAME, "Test " + position);
        properties.put(ContentModel.PROP_CREATED, new Date());
        properties.put(singleTextUntokenised, orderable[position]);
        properties.put(singleTextTokenised, orderable[position]);
        properties.put(singleTextBoth, orderable[position]);
        properties.put(multipleTextUntokenised, asArray(orderable[position], orderable[position + 1]));
        properties.put(multipleTextTokenised, asArray(orderable[position], orderable[position + 1]));
        properties.put(multipleTextBoth, asArray(orderable[position], orderable[position + 1]));
        properties.put(singleMLTextUntokenised, makeMLText(position));
        properties.put(singleMLTextTokenised, makeMLText(position));
        properties.put(singleMLTextBoth, makeMLText(position));
        properties.put(multipleMLTextUntokenised, makeMLTextMVP(position));
        properties.put(multipleMLTextTokenised, makeMLTextMVP(position));
        properties.put(multipleMLTextBoth, makeMLTextMVP(position));
        properties.put(singleFloat, 1.1f * position);
        properties.put(multipleFloat, asArray(1.1f * position, 2.2f * position));
        properties.put(singleDouble, 1.1d * position);
        properties.put(multipleDouble, asArray(1.1d * position, 2.2d * position));
        properties.put(singleInteger, 1 * position);
        properties.put(multipleInteger, asArray(1 * position, 2 * position));
        properties.put(singleLong, 1l * position);
        properties.put(multipleLong, asArray(1l * position, 2l * position));
        GregorianCalendar cal = new GregorianCalendar();
        cal.setTime(new Date());
        cal.add(Calendar.DAY_OF_MONTH, position);
        Date d1 = cal.getTime();
        cal.add(Calendar.DAY_OF_MONTH, -1);
        // Date d0 = cal.getTime();
        cal.add(Calendar.DAY_OF_MONTH, 2);
        Date d2 = cal.getTime();
        properties.put(singleDate, d1);
        properties.put(multipleDate, asArray(d1, d2));
        properties.put(singleDatetime, d1);
        properties.put(multipleDatetime, asArray(d1, d2));
        properties.put(singleBoolean, position % 2 == 0 ? true : false);
        properties.put(multipleBoolean, asArray(true, false));
        NodeRef c0 = nodeService.createNode(f0, ContentModel.ASSOC_CONTAINS, QName.createQName("cm", "Test One", namespaceService), extendedContent, properties).getChildRef();
        return c0;
    }
    private NodeRef addTypeTestData()
    {
        addTypeTestDataModel();
        I18NUtil.setLocale(Locale.UK);
        Map properties = new HashMap();
        MLText ml = new MLText();
        ml.addValue(Locale.ENGLISH, "Test one");
        ml.addValue(Locale.US, "Test 1");
        properties.put(ContentModel.PROP_DESCRIPTION, ml);
        properties.put(ContentModel.PROP_TITLE, ml);
        properties.put(ContentModel.PROP_NAME, "Test one");
        properties.put(ContentModel.PROP_CREATED, new Date());
        properties.put(singleTextUntokenised, "Un tokenised");
        properties.put(singleTextTokenised, "Un tokenised");
        properties.put(singleTextBoth, "Un tokenised");
        properties.put(multipleTextUntokenised, asArray("Un tokenised", "two parts"));
        properties.put(multipleTextTokenised, asArray("Un tokenised", "two parts"));
        properties.put(multipleTextBoth, asArray("Un tokenised", "two parts"));
        properties.put(singleMLTextUntokenised, makeMLText());
        properties.put(singleMLTextTokenised, makeMLText());
        properties.put(singleMLTextBoth, makeMLText());
        properties.put(multipleMLTextUntokenised, makeMLTextMVP());
        properties.put(multipleMLTextTokenised, makeMLTextMVP());
        properties.put(multipleMLTextBoth, makeMLTextMVP());
        properties.put(singleFloat, 1f);
        properties.put(multipleFloat, asArray(1f, 1.1f));
        properties.put(singleDouble, 1d);
        properties.put(multipleDouble, asArray(1d, 1.1d));
        properties.put(singleInteger, 1);
        properties.put(multipleInteger, asArray(1, 2));
        properties.put(singleLong, 1l);
        properties.put(multipleLong, asArray(1l, 2l));
        date1 = new Date();
        GregorianCalendar cal = new GregorianCalendar();
        cal.setTime(date1);
        cal.add(Calendar.DAY_OF_MONTH, -1);
        date0 = cal.getTime();
        cal.add(Calendar.DAY_OF_MONTH, 2);
        date2 = cal.getTime();
        properties.put(singleDate, date1);
        properties.put(multipleDate, asArray(date1, date2));
        properties.put(singleDatetime, date1);
        properties.put(multipleDatetime, asArray(date1, date2));
        properties.put(singleBoolean, true);
        properties.put(multipleBoolean, asArray(true, false));
        NodeRef c0 = nodeService.createNode(f0, ContentModel.ASSOC_CONTAINS, QName.createQName("cm", "Test One", namespaceService), extendedContent, properties).getChildRef();
        return c0;
    }
    private static String[] mlOrderable_en = new String[] { "AAAA BBBB", "EEEE FFFF", "II", "KK", "MM", "OO", "QQ", "SS", "UU", "AA", "CC" };
    private static String[] mlOrderable_fr = new String[] { "CCCC DDDD", "GGGG HHHH", "JJ", "LL", "NN", "PP", "RR", "TT", "VV", "BB", "DD" };
    private MLText makeMLText()
    {
        return makeMLText(0);
    }
    private MLText makeMLText(int position)
    {
        MLText ml = new MLText();
        ml.addValue(Locale.ENGLISH, mlOrderable_en[position]);
        ml.addValue(Locale.FRENCH, mlOrderable_fr[position]);
        return ml;
    }
    private ArrayList makeMLTextMVP()
    {
        return makeMLTextMVP(0);
    }
    private ArrayList makeMLTextMVP(int position)
    {
        MLText m1 = new MLText();
        m1.addValue(Locale.ENGLISH, mlOrderable_en[position]);
        MLText m2 = new MLText();
        m2.addValue(Locale.FRENCH, mlOrderable_fr[position]);
        ArrayList answer = new ArrayList(2);
        answer.add(m1);
        answer.add(m2);
        return answer;
    }
    private  ArrayList asArray(T... ts)
    {
        ArrayList list = new ArrayList(ts.length);
        for (T t : ts)
        {
            list.add(t);
        }
        return list;
    }
}