org.betaconceptframework.astroboa.util.PropertyExtractor.java Source code

Java tutorial

Introduction

Here is the source code for org.betaconceptframework.astroboa.util.PropertyExtractor.java

Source

/*
 * 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;
        }
    }

}