/* * 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.util; import org.apache.commons.lang.StringUtils; import org.betaconceptframework.astroboa.api.model.*; import org.betaconceptframework.astroboa.api.model.definition.CmsPropertyDefinition; import org.betaconceptframework.astroboa.api.model.exception.CmsException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.List; /** * Class responsible to return a property of an object using the * path provided. * * The path may contain identifiers instead of indices to indicate which of the property to use. * * All the parts of the path represent a complex property except from the last part which * represents a simple property. In this part, if the property is a multiple value property, * users have to use indices to specify which value of the * property to return . In the case of a binary property they may use the identifier of the * binary channel as well. * * The path follows the pattern {@link CmsConstants#PROPERTY_PATH_WITH_ID_REG_EXP_FOR_RESTEASY} * * @author Gregory Chomatas (gchomatas@betaconcept.com) * @author Savvas Triantafyllou (striantafyllou@betaconcept.com) * */ public class PropertyExtractor { private static final Logger logger = LoggerFactory.getLogger(PropertyExtractor.class); private String identifierOfTheValueOfTheProperty = null; private int indexOfTheValueOfTheProperty = 0; private CmsProperty<?,?> property = null; public PropertyExtractor(ContentObject contentObject, String propertyPath) throws Exception{ if (StringUtils.isNotBlank(propertyPath) && contentObject != null){ property = contentObject.getComplexCmsRootProperty(); String[] pathParts = StringUtils.split(propertyPath, CmsConstants.PERIOD_DELIM); int count = 0; for (String pathPart : pathParts){ boolean lastPart = ++count == pathParts.length; String parentPropertyPermanentPath = property.getFullPath(); String childPropertyName = StringUtils.substringBeforeLast(pathPart, CmsConstants.LEFT_BRACKET); if (lastPart){ String identifierOrIndexOfTheValue = retrieveIdentifierOrIndexFromPath(pathPart); property = ((ComplexCmsProperty)property).getChildProperty(childPropertyName); if (property == null){ throw new CmsException("Cannot retrieve property "+pathPart + " from parent property "+ parentPropertyPermanentPath); } if (identifierOrIndexOfTheValue != null){ if (CmsConstants.UUIDPattern.matcher(identifierOrIndexOfTheValue).matches()){ identifierOfTheValueOfTheProperty = identifierOrIndexOfTheValue; } else{ indexOfTheValueOfTheProperty = Integer.parseInt(identifierOrIndexOfTheValue); } } } else{ //We are in the middle of the path. String identifierOfTheChildProperty = retrieveIdentifierOrIndexFromPath(pathPart); boolean childPropertyIsDefined = ((ComplexCmsProperty)property).isChildPropertyDefined(childPropertyName); if (! childPropertyIsDefined){ throw new Exception("Could not locate definition for property " + childPropertyName); } //Retrieve definition CmsPropertyDefinition childPropertyDefinition = ((ComplexCmsProperty)property).getPropertyDefinition().getChildCmsPropertyDefinition(childPropertyName); if (childPropertyDefinition == null){ //Property has been defined. Since no definition is found check if this property is an aspect if (property instanceof ComplexCmsRootProperty && ((ComplexCmsRootProperty)property).hasAspect(childPropertyName)){ childPropertyDefinition = ((ComplexCmsRootProperty)property).getAspectDefinitions().get(childPropertyName); } } if (childPropertyDefinition == null){ throw new Exception("Could not locate definition for property " + childPropertyName); } if (childPropertyDefinition.getValueType() == ValueType.Complex){ //Child property is a multiple value property //Iterate through the returned properties to //match the property with the provided identifier if any if (childPropertyDefinition.isMultiple()){ property = retrieveChildComplexCmsPropertyFromAListOfProperties(identifierOfTheChildProperty,childPropertyName); } else{ //Child property is a single value property CmsProperty<?,?> childProperty = ((ComplexCmsProperty)property).getChildProperty(childPropertyName); if (identifierOfTheChildProperty != null){ //User has an identifier. Check that this is valid if (StringUtils.equals(identifierOfTheChildProperty, childProperty.getId())){ property = childProperty; } else{ throw new Exception("Property " + childPropertyName + " has been retrieved from parent property "+ parentPropertyPermanentPath + " but its identifier "+ childProperty.getId() + " does not match with the one provided "+ identifierOfTheChildProperty); } } else{ property = childProperty; } } } else{ throw new CmsException("Property "+pathPart + " does not correspond to a complex property of the property "+parentPropertyPermanentPath); } } } } } private CmsProperty<?, ?> retrieveChildComplexCmsPropertyFromAListOfProperties( String identifierOfChildProperty, String childPropertyName) throws Exception { List<CmsProperty<?,?>> childProperties = ((ComplexCmsProperty)property).getChildPropertyList(childPropertyName); logger.info("Checking if child property {}[{}] is in property list", childPropertyName, identifierOfChildProperty, childProperties); if (childProperties == null || childProperties.isEmpty()) { throw new Exception("Empty property list returned"); } //No identifier is provided. Return the first from the list if (identifierOfChildProperty == null) { return childProperties.get(0); } else{ Integer childPropertyIndex = getIndex(identifierOfChildProperty); if (childPropertyIndex == -1) { // it is an identifier for (CmsProperty childProperty : childProperties) { if (StringUtils.equals(identifierOfChildProperty, childProperty.getId())) { return childProperty; } } } else { return childProperties.get(childPropertyIndex); } } throw new Exception("Could not locate child property "+childPropertyName + " with identifier "+identifierOfChildProperty + " in parent property "+property.getFullPath()); } private String retrieveIdentifierOrIndexFromPath(String pathPart) { if (StringUtils.isBlank(pathPart)){ return null; } return StringUtils.substringBetween(pathPart, CmsConstants.LEFT_BRACKET, CmsConstants.RIGHT_BRACKET); } public String getIdentifierOfTheValueOfTheProperty() { return identifierOfTheValueOfTheProperty; } public int getIndexOfTheValueOfTheProperty() { return indexOfTheValueOfTheProperty; } public CmsProperty<?, ?> getProperty() { return property; } private Integer getIndex(String identifierOrIndex) { try { return Integer.parseInt(identifierOrIndex); } catch (NumberFormatException e) { return -1; } } }