/* * Copyright (C) 2005-2012 BetaCONCEPT Limited * * This file is part of Astroboa. * * Astroboa is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Astroboa is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Astroboa. If not, see <http://www.gnu.org/licenses/>. */ package org.betaconceptframework.astroboa.test.model.query; import java.util.Arrays; import java.util.Calendar; import javax.jcr.Node; import org.apache.commons.lang.StringUtils; import org.betaconceptframework.astroboa.api.model.CalendarProperty; import org.betaconceptframework.astroboa.api.model.CmsApiConstants; import org.betaconceptframework.astroboa.api.model.ContentObject; import org.betaconceptframework.astroboa.api.model.LongProperty; import org.betaconceptframework.astroboa.api.model.SimpleCmsProperty; import org.betaconceptframework.astroboa.api.model.StringProperty; import org.betaconceptframework.astroboa.api.model.io.FetchLevel; import org.betaconceptframework.astroboa.api.model.io.ResourceRepresentationType; import org.betaconceptframework.astroboa.api.model.query.CacheRegion; import org.betaconceptframework.astroboa.api.model.query.CmsOutcome; import org.betaconceptframework.astroboa.api.model.query.Condition; import org.betaconceptframework.astroboa.api.model.query.QueryOperator; import org.betaconceptframework.astroboa.api.model.query.criteria.ContentObjectCriteria; import org.betaconceptframework.astroboa.api.model.query.criteria.Criterion; import org.betaconceptframework.astroboa.model.factory.CmsCriteriaFactory; import org.betaconceptframework.astroboa.model.factory.CriterionFactory; import org.betaconceptframework.astroboa.model.impl.item.CmsBuiltInItem; import org.betaconceptframework.astroboa.test.engine.AbstractRepositoryTest; import org.betaconceptframework.astroboa.test.util.JcrUtils; import org.testng.Assert; import org.testng.annotations.Test; /** * @author Gregory Chomatas (gchomatas@betaconcept.com) * @author Savvas Triantafyllou (striantafyllou@betaconcept.com) * */ public class CmsCriteriaTest extends AbstractRepositoryTest{ @Test public void testContainsCriterion() throws Exception { checkExpression("systemName CONTAINS \"1\"", CriterionFactory.contains(CmsBuiltInItem.SystemName.getJcrName(), "1")); checkExpression("systemName CONTAINS \"1\"", CriterionFactory.createSimpleCriterion(CmsBuiltInItem.SystemName.getJcrName(), "1", QueryOperator.CONTAINS)); checkExpression("profile.title CONTAINS \"1\"", CriterionFactory.contains("profile.title", "1")); checkExpression("profile.title CONTAINS \"1\"", CriterionFactory.createSimpleCriterion("profile.title", "1", QueryOperator.CONTAINS)); checkExpression("profile CONTAINS \"1\"", CriterionFactory.contains("profile", "1")); checkExpression("profile CONTAINS \"1\"", CriterionFactory.createSimpleCriterion("profile", "1", QueryOperator.CONTAINS)); checkExpression("commentSingle CONTAINS \"1\"", CriterionFactory.contains("commentSingle", "1")); checkExpression("commentSingle CONTAINS \"1\"", CriterionFactory.createSimpleCriterion("commentSingle", "1", QueryOperator.CONTAINS)); checkExpression("comment CONTAINS \"1\"", CriterionFactory.contains("comment", "1")); checkExpression("comment CONTAINS \"1\"", CriterionFactory.createSimpleCriterion("comment", "1", QueryOperator.CONTAINS)); } @Test public void testBaseContentTypeCriterion() throws Exception { checkExpression("objectType=\""+TEST_CONTENT_TYPE+"Type\"", CriterionFactory.equals(CmsBuiltInItem.ContentObjectTypeName.getJcrName(), Condition.OR, Arrays.asList(EXTENDED_TEST_CONTENT_TYPE,DIRECT_EXTENDED_TEST_CONTENT_TYPE,TEST_CONTENT_TYPE))); checkExpression("objectType=\""+EXTENDED_TEST_CONTENT_TYPE+"Type\"", CriterionFactory.equals(CmsBuiltInItem.ContentObjectTypeName.getJcrName(), Condition.OR, Arrays.asList(EXTENDED_TEST_CONTENT_TYPE,DIRECT_EXTENDED_TEST_CONTENT_TYPE))); } @Test public void testSearchText(){ ContentObject testContentObject = createContentObject(repositoryUserService.getRepositoryUser(CmsApiConstants.SYSTEM_REPOSITORY_USER_EXTRENAL_ID), "testSearchText"); ((StringProperty)testContentObject.getCmsProperty("profile.title")).setSimpleTypeValue("Test Content Object 3"); ((CalendarProperty)testContentObject.getCmsProperty("webPublication.webPublicationStartDate")).setSimpleTypeValue(Calendar.getInstance()); ((StringProperty)testContentObject.getCmsProperty("commentSingle.body")).setSimpleTypeValue("Test comment"); ((StringProperty)testContentObject.getCmsProperty("commentSingle.body")).setSimpleTypeValue("Test comment"); ((StringProperty)testContentObject.getCmsProperty("comment.body")).setSimpleTypeValue("Test comment"); ((StringProperty)testContentObject.getCmsProperty("comment.comment.body")).setSimpleTypeValue("Test comment"); testContentObject = contentService.save(testContentObject, false, true, null); markObjectForRemoval(testContentObject); ContentObjectCriteria criteria = CmsCriteriaFactory.newContentObjectCriteria(TEST_CONTENT_TYPE); criteria.doNotCacheResults(); criteria.addCriterion(CriterionFactory.equals("profile.title", "Test Content Object 3")); criteria.addFullTextSearchCriterion("*comment*"); CmsOutcome<ContentObject> results = contentService.searchContentObjects(criteria, ResourceRepresentationType.CONTENT_OBJECT_LIST); Assert.assertTrue(results != null && results.getCount() == 1 && testContentObject.getId().equals(results.getResults().get(0).getId()), "Could not find newly created content object of type test which contains text 'comment' on any property\n"+ " Executed query "+ criteria.getXPathQuery()); assertSearchReturnsNoResult("''commentTest"); assertSearchReturnsNoResult("''commentTest''"); assertSearchReturnsNoResult("commentTest AND ASTROBOA"); assertSearchReturnsNoResult("commentTest OR ASTROBOA"); assertSearchReturnsNoResult("''commentTest AND ASTROBOA"); assertSearchReturnsNoResult("commentTest OR ASTROBOA''"); assertSearchReturnsNoResult("-commentTest ASTROBOA''"); assertSearchReturnsNoResult("-commentTest ASTROBOA"); assertSearchReturnsNoResult("''-commentTest ASTROBOA"); assertSearchReturnsNoResult("-commentTest ASTRO\"\" \"\"BOA"); assertSearchReturnsNoResult("-commentTest ASTROBOA\"\""); assertSearchReturnsNoResult("-commentTest ASTROBOA"); assertSearchReturnsNoResult("\"\"-commentTest ASTROBOA"); assertSearchReturnsNoResult("\"\"''-commentTest ASTROBOA"); assertSearchReturnsNoResult("_commentTest ASTROBOA''"); assertSearchReturnsNoResult("_commentTest ASTROBOA"); assertSearchReturnsNoResult("''_commentTest ASTROBOA"); assertSearchReturnsNoResult("_commentTest ASTROBOA\"\""); assertSearchReturnsNoResult("_commentTest ASTROBOA"); assertSearchReturnsNoResult("_comment\"Test AST\"ROBOA"); assertSearchReturnsNoResult("\"\"_commentTest ASTROBOA"); assertSearchReturnsNoResult("\"\"''_commentTest ASTROBOA"); assertSearchReturnsNoResult("comment\\)Test"); assertSearchReturnsNoResult("comment\\)\\)Test"); assertSearchReturnsNoResult("comment\\(Test"); assertSearchReturnsNoResult("comment\\(\\(Test"); assertSearchReturnsNoResult("comment\\}Test"); assertSearchReturnsNoResult("comment\\}\\}Test"); assertSearchReturnsNoResult("comment\\[Test"); assertSearchReturnsNoResult("comment\\[\\[Test"); assertSearchReturnsNoResult("comment\\]Test"); assertSearchReturnsNoResult("comment\\]\\]Test"); assertSearchReturnsNoResult("comment\\^Test"); assertSearchReturnsNoResult("comment\\^\\^Test"); assertSearchReturnsNoResult("comment\\~\\~Test"); assertSearchReturnsNoResult("comment\\?Test"); assertSearchReturnsNoResult("comment\\?\\?Test"); assertSearchReturnsNoResult("comment\\:Test"); assertSearchReturnsNoResult("comment\\:\\:Test"); assertSearchReturnsNoResult("comment\\Test"); assertSearchReturnsNoResult("comment\\\\Test"); } private void assertSearchReturnsNoResult(String textSearch){ ContentObjectCriteria criteria = CmsCriteriaFactory.newContentObjectCriteria(TEST_CONTENT_TYPE); criteria.doNotCacheResults(); criteria.addFullTextSearchCriterion(textSearch); CmsOutcome<ContentObject> results = contentService.searchContentObjects(criteria, ResourceRepresentationType.CONTENT_OBJECT_LIST); String coNames = ""; if (results!= null && results.getCount() > 0){ for (ContentObject co : results.getResults()){ coNames += " "+ co.getSystemName(); } } Assert.assertTrue(results == null || results.getCount() == 0, "Found " + results.getCount()+ " in a search for text "+textSearch+ " while it should not have returned any result\n"+ " Executed query "+ criteria.getXPathQuery()+ "\n System name of ContentObjects returned in Query :"+coNames); } @Test public void testQueryForNullAndNotNullSimpleAndComplexProperties() throws Throwable{ ContentObject testContentObject = createContentObject(repositoryUserService.getRepositoryUser(CmsApiConstants.SYSTEM_REPOSITORY_USER_EXTRENAL_ID), "testQueryForNullAndNotNull"); long value = (long)9999999; ((LongProperty)testContentObject.getCmsProperty("simpleLong")).addSimpleTypeValue(value); ((StringProperty)testContentObject.getCmsProperty("profile.title")).setSimpleTypeValue("Test Content Object 2"); testContentObject = contentService.save(testContentObject, false, true, null); markObjectForRemoval(testContentObject); ContentObject testContent2Object = contentService.getContentObject(testContentObject.getId(), ResourceRepresentationType.CONTENT_OBJECT_INSTANCE, FetchLevel.ENTITY, CacheRegion.NONE, null, false); testContent2Object.getCmsProperty("profile"); assertQueryReturnsContentObject(testContentObject,"simpleLong", true); assertQueryReturnsContentObject(testContentObject,"simpleString", false); assertQueryReturnsContentObject(testContentObject,"profile.language", true); assertQueryReturnsContentObject(testContentObject,"profile.contributor", false); assertQueryReturnsContentObject(testContentObject,"profile.subject", false); assertQueryReturnsContentObject(testContentObject,"webPublication.webPublicationStartDate", false); ((CalendarProperty)testContentObject.getCmsProperty("webPublication.webPublicationStartDate")).setSimpleTypeValue(Calendar.getInstance()); testContentObject = contentService.save(testContentObject, false, true, null); assertQueryReturnsContentObject(testContentObject,"webPublication.webPublicationStartDate", true); assertQueryReturnsContentObject(testContentObject,"commentSingle.body", false); ((StringProperty)testContentObject.getCmsProperty("commentSingle.body")).setSimpleTypeValue("Test comment"); testContentObject = contentService.save(testContentObject, false, true, null); assertQueryReturnsContentObject(testContentObject,"commentSingle.body", true); } private void assertQueryReturnsContentObject( ContentObject testContentObject, String propertyName, boolean notNull) throws Throwable { ContentObjectCriteria criteria = CmsCriteriaFactory.newContentObjectCriteria(TEST_CONTENT_TYPE); criteria.doNotCacheResults(); criteria.addCriterion(CriterionFactory.equals("profile.title", "Test Content Object 2")); if (notNull){ criteria.addCriterion(CriterionFactory.isNotNull(propertyName)); } else{ criteria.addCriterion(CriterionFactory.isNull(propertyName)); } CmsOutcome<ContentObject> results = contentService.searchContentObjects(criteria, ResourceRepresentationType.CONTENT_OBJECT_LIST); SimpleCmsProperty<?,?,?> property = null; try{ Assert.assertTrue(results != null && results.getCount() == 1 && testContentObject.getId().equals(results.getResults().get(0).getId()), "Could not find newly created content object of type test with "+ (notNull ? " not null" : " null ") + propertyName +" \n"+ " Executed query "+ criteria.getXPathQuery()); if (results != null && results.getCount() > 0){ property = (SimpleCmsProperty<?, ?, ?>) results.getResults().get(0).getCmsProperty(propertyName); } if (notNull){ Assert.assertTrue(property != null && property.hasValues(), "Property "+propertyName + " does not have values nevertheless query returned content object containing this property because it had values"); } else{ Assert.assertTrue(property != null && property.hasNoValues(), "Property "+propertyName + " has values nevertheless query returned content object containing this property because it had no values"); } } catch(Throwable t){ if (property != null && property.hasValues()){ logger.error("Found values for property "+ propertyName); if (property.getPropertyDefinition().isMultiple()){ for (Object value : property.getSimpleTypeValues()){ logger.error(value.toString()); } } else{ logger.error(property.getSimpleTypeValue().toString()); } } //Now dump jcr node for content object Node contentObjectNode = getSession().getNodeByIdentifier(testContentObject.getId()); logger.error(JcrUtils.dumpNode(contentObjectNode, 0)); throw t; } } @Test public void testQueryUsingLongAndStringAsPropertyValues(){ ContentObject testContentObject = createContentObject(repositoryUserService.getRepositoryUser(CmsApiConstants.SYSTEM_REPOSITORY_USER_EXTRENAL_ID), "testQueryUsingLongAndStringAsPropertyValues"); long value = (long)999999; ((LongProperty)testContentObject.getCmsProperty("simpleLong")).addSimpleTypeValue(value); ((StringProperty)testContentObject.getCmsProperty("profile.title")).setSimpleTypeValue("Test Content Object"); testContentObject = contentService.save(testContentObject, false, true, null); markObjectForRemoval(testContentObject); ContentObjectCriteria criteria = CmsCriteriaFactory.newContentObjectCriteria(TEST_CONTENT_TYPE); criteria.doNotCacheResults(); criteria.addCriterion(CriterionFactory.equals("simpleLong", value)); criteria.addCriterion(CriterionFactory.equals("profile.title", "Test Content Object")); CmsOutcome<ContentObject> results = contentService.searchContentObjects(criteria, ResourceRepresentationType.CONTENT_OBJECT_LIST); Assert.assertTrue(results != null && results.getCount() == 1 && testContentObject.getId().equals(results.getResults().get(0).getId()), "Could not find newly created content object of type test with simpleLong="+value+ " \n"+ " Executed query "+ criteria.getXPathQuery()); //Now make the query using string value ContentObjectCriteria criteria2 = CmsCriteriaFactory.newContentObjectCriteria(TEST_CONTENT_TYPE); criteria2.doNotCacheResults(); criteria2.addCriterion(CriterionFactory.equals("simpleLong", String.valueOf(value))); CmsOutcome<ContentObject> results2 = contentService.searchContentObjects(criteria2, ResourceRepresentationType.CONTENT_OBJECT_LIST); Assert.assertTrue(results2 != null && results2.getCount() == 1 && testContentObject.getId().equals(results2.getResults().get(0).getId()), "Could not find newly created content object of type test with simpleLong="+value+ " \n"+ " Executed query "+ criteria2.getXPathQuery()); } private void checkExpression(String expression, Criterion expectedCriterion) throws Exception { try{ ContentObjectCriteria parserContentOjectCriteria = CmsCriteriaFactory.newContentObjectCriteria(); ContentObjectCriteria expectedContentOjectCriteria = CmsCriteriaFactory.newContentObjectCriteria(); expectedContentOjectCriteria.addCriterion(expectedCriterion); CriterionFactory.parse(expression, parserContentOjectCriteria); assertCriterionEquals(parserContentOjectCriteria, expectedContentOjectCriteria); logger.info("Expression : "+ expression + " produced XPATH : "+ parserContentOjectCriteria.getXPathQuery()); } catch (RuntimeException e){ logger.error(expression); throw e; } } private void assertCriterionEquals(ContentObjectCriteria parserContentOjectCriteria, ContentObjectCriteria expectedContentOjectCriteria){ Assert.assertNotNull(parserContentOjectCriteria, "No criteria provided by parser"); Assert.assertNotNull(expectedContentOjectCriteria, "No criteria provided by user"); Assert.assertEquals(StringUtils.deleteWhitespace(parserContentOjectCriteria.getXPathQuery()), StringUtils.deleteWhitespace(expectedContentOjectCriteria.getXPathQuery())); } }