org.betaconceptframework.astroboa.engine.jcr.util.JcrNodeUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.betaconceptframework.astroboa.engine.jcr.util.JcrNodeUtils.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.engine.jcr.util;

import java.util.List;

import javax.jcr.ItemNotFoundException;
import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Value;
import javax.jcr.ValueFactory;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.betaconceptframework.astroboa.api.model.ValueType;
import org.betaconceptframework.astroboa.api.model.exception.CmsException;
import org.betaconceptframework.astroboa.engine.jcr.query.CalendarInfo;
import org.betaconceptframework.astroboa.engine.jcr.query.CmsQueryResult;
import org.betaconceptframework.astroboa.model.impl.ItemQName;
import org.betaconceptframework.astroboa.model.impl.SaveMode;
import org.betaconceptframework.astroboa.model.impl.item.CmsBuiltInItem;
import org.betaconceptframework.astroboa.model.impl.item.JcrBuiltInItem;
import org.betaconceptframework.astroboa.util.CmsConstants;
import org.betaconceptframework.astroboa.util.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author Gregory Chomatas (gchomatas@betaconcept.com)
 * @author Savvas Triantafyllou (striantafyllou@betaconcept.com)
 * 
 */
public class JcrNodeUtils {

    private final static Logger logger = LoggerFactory.getLogger(JcrNodeUtils.class);

    /**
     * Retrieve Content type's Folder Node
     * Creates a new one if not found
     * @param session
     * @param type
     * @return
     * @throws RepositoryException 
     * @throws RepositoryException 
     * @throws 
     */
    public static Node retrieveOrCreateContentTypeFolderNode(Session session, String type)
            throws RepositoryException {
        String typeFolderPath = type + CmsConstants.TYPE_FOLDER;

        Node contentObjectRootNode = getContentObjectRootNode(session);

        try {
            return contentObjectRootNode.getNode(typeFolderPath);
        } catch (PathNotFoundException pnf) {
            //Content Type Folder does not exist. Create one
            return contentObjectRootNode.addNode(typeFolderPath);
        }

    }

    /**
     * 
     * @param parent
     * @param childName
     * @return Child node found with specified childName, null othrewise
     * @throws RepositoryException
     */
    public static Node selectNode(Node parent, String childName) throws RepositoryException {
        try {
            return parent.getNode(childName);
        } catch (PathNotFoundException pnfe) {
            return null;
        }
    }

    public static Node createContentObjectParentNode(Node typeNode, CalendarInfo calendarInfo)
            throws RepositoryException {

        Node secondNode = selectNode(typeNode, calendarInfo.getFullPath());

        if (secondNode != null) {
            return secondNode;
        }

        //Obtain year
        final String year = calendarInfo.getYear();
        final String month = calendarInfo.getMonth();
        final String day = calendarInfo.getDay();
        final String hour = calendarInfo.getHour();
        final String minute = calendarInfo.getMinute();
        final String second = calendarInfo.getSecond();

        Node yearNode = selectNode(typeNode, year);
        if (yearNode == null) {
            yearNode = createYearFolderNode(typeNode, year);
        }

        Node monthNode = selectNode(yearNode, month);
        if (monthNode == null) {
            monthNode = createMonthFolderNode(yearNode, month);
        }

        Node dayNode = selectNode(monthNode, day);
        if (dayNode == null) {
            dayNode = createDayFolderNode(monthNode, day);
        }

        Node hourNode = selectNode(dayNode, hour);
        if (hourNode == null) {
            hourNode = createHourFolderNode(dayNode, hour);
        }

        Node minuteNode = selectNode(hourNode, minute);

        if (minuteNode == null) {
            minuteNode = createMinuteFolderNode(hourNode, minute);
        }
        return createSecondFolderNode(minuteNode, second);
    }

    private static Node createSecondFolderNode(Node minuteNode, String minute) throws RepositoryException {
        if (minuteNode == null)
            throw new ItemNotFoundException("Minute node");

        return minuteNode.addNode(minute, CmsBuiltInItem.GenericSecondFolder.getJcrName());
    }

    private static Node createMinuteFolderNode(Node hourNode, String minute) throws RepositoryException {
        if (hourNode == null)
            throw new ItemNotFoundException("Hour node");

        return hourNode.addNode(minute, CmsBuiltInItem.GenericMinuteFolder.getJcrName());
    }

    private static Node createHourFolderNode(Node dayNode, String hour) throws RepositoryException {
        if (dayNode == null)
            throw new ItemNotFoundException("Day node");

        return dayNode.addNode(hour, CmsBuiltInItem.GenericHourFolder.getJcrName());
    }

    private static Node createDayFolderNode(Node monthNode, String day) throws RepositoryException {
        if (monthNode == null)
            throw new ItemNotFoundException("Month node");

        return monthNode.addNode(day, CmsBuiltInItem.GenericDayFolder.getJcrName());
    }

    private static Node createMonthFolderNode(Node yearNode, String month) throws RepositoryException {
        if (yearNode == null)
            throw new ItemNotFoundException("Year ndoe");

        return yearNode.addNode(month, CmsBuiltInItem.GenericMonthFolder.getJcrName());
    }

    private static Node createYearFolderNode(Node typeNode, String year) throws RepositoryException {
        if (typeNode == null)
            throw new ItemNotFoundException("Type node");

        return typeNode.addNode(year, CmsBuiltInItem.GenericYearFolder.getJcrName());
    }

    public static Node uniqueNode(CmsQueryResult cmsQueryResult) {
        if (cmsQueryResult == null)
            return null;

        long size = cmsQueryResult.getTotalRowCount();

        if (size <= 0)
            return null;

        if (size > 1)
            throw new CmsException("Not unique node");

        try {
            return cmsQueryResult.getNodeIterator().nextNode();
        } catch (Exception e) {
            logger.error("CmsQueryResult has 1 total row count but node iterator has a problem ", e);
            return null;
        }

    }

    public static Node getRepositoryUserRootNode(Session session) throws RepositoryException {
        return getRootNode(session, CmsBuiltInItem.RepositoryUserRoot);
    }

    public static Node getContentObjectRootNode(Session session) throws RepositoryException {
        return getRootNode(session, CmsBuiltInItem.ContentObjectRoot);
    }

    public static Node getTaxonomyRootNode(Session session) throws RepositoryException {
        return getRootNode(session, CmsBuiltInItem.TaxonomyRoot);
    }

    public static Node getCMSSystemNode(Session session) throws RepositoryException {
        return session.getRootNode().getNode(CmsBuiltInItem.SYSTEM.getJcrName());
    }

    public static Node getNodeByNativeRepositoryIdentifier(Session session, String nativeRepositoryIdentifier)
            throws RepositoryException {
        return session.getNodeByIdentifier(nativeRepositoryIdentifier);
    }

    public static Node getRootNode(Session session, ItemQName rootItem) throws RepositoryException {
        if (rootItem != null)
            return getCMSSystemNode(session).getNode(rootItem.getJcrName());

        return null;
    }

    public static void addMultiValueProperty(Node node, ItemQName multiValueProperty, SaveMode saveMode,
            List values, ValueType valueType, ValueFactory valueFactory) throws RepositoryException {
        Value[] newValues = JcrValueUtils.convertListToValueArray(values, valueType, valueFactory);

        addMultiValueProperty(saveMode, node, multiValueProperty, newValues, valueFactory, valueType);
    }

    private static void addMultiValueProperty(SaveMode saveMode, Node node, ItemQName property, Value[] values,
            ValueFactory valueFactory, ValueType valueType) throws RepositoryException {
        if (!ArrayUtils.isEmpty(values)) {

            //It may be the case that property contains a single value and not a single value array.
            //In this case JCR throws an exception. Thus we remove value first and then we add the array of values
            if (node.hasProperty(property.getJcrName())
                    && node.getProperty(property.getJcrName()).getDefinition() != null
                    && !node.getProperty(property.getJcrName()).getDefinition().isMultiple()) {

                if (values != null) {
                    if (values.length > 1) {
                        throw new CmsException("Cannot save more than one values " + generateStringOutput(values)
                                + " to single value property " + node.getProperty(property.getJcrName()).getPath()
                                + ".Probably this property used to be single valued and its definition change to multivalue "
                                + " and now user tries to save more than one values. To correct this propblem "
                                + " you should run a script which modifies existing property values from single value to a value Array");
                    } else if (values.length == 1) {
                        addSimpleProperty(saveMode, node, property, JcrValueUtils.getObjectValue(values[0]),
                                valueFactory, valueType);
                    }
                } else {
                    node.setProperty(property.getJcrName(), JcrValueUtils.getJcrNull());
                }
            } else {
                node.setProperty(property.getJcrName(), values);
            }
        } else if (saveMode == SaveMode.UPDATE) {
            if (node.hasProperty(property.getJcrName())
                    && node.getProperty(property.getJcrName()).getDefinition() != null
                    && !node.getProperty(property.getJcrName()).getDefinition().isMultiple()) {
                removeProperty(node, property, false);
            } else {
                removeProperty(node, property, true);
            }
        }
    }

    private static String generateStringOutput(Value[] values) {
        StringBuilder sb = new StringBuilder();

        try {
            if (!ArrayUtils.isEmpty(values)) {
                for (Value value : values) {
                    if (value != null) {
                        switch (value.getType()) {
                        case PropertyType.BOOLEAN:
                            sb.append(value.getBoolean());
                            break;
                        case PropertyType.DATE:
                            sb.append(DateUtils.format(value.getDate()));
                            break;
                        case PropertyType.DOUBLE:
                            sb.append(value.getDouble());
                            break;
                        case PropertyType.LONG:
                            sb.append(value.getLong());
                            break;
                        case PropertyType.NAME:
                        case PropertyType.PATH:
                        case PropertyType.REFERENCE:
                        case PropertyType.STRING:
                            sb.append(value.getString());
                            break;

                        default:
                            break;
                        }
                    } else {
                        sb.append("NULL");
                    }
                    sb.append(" ");
                }
            }
        } catch (Exception e) {
            logger.warn("While trying to log value array", e);
        }

        return sb.toString();
    }

    public static void addSimpleProperty(SaveMode saveMode, Node node, ItemQName property, Object value,
            ValueFactory valueFactory, ValueType valueType) throws RepositoryException {
        if (value != null) {
            JcrValueUtils.addValue(node, property, JcrValueUtils.getJcrValue(value, valueType, valueFactory),
                    false);
            logger.debug("Added value {} for property {} in node {}",
                    new Object[] { value, property.getJcrName(), node.getPath() });
        } else if (saveMode == SaveMode.UPDATE) {
            removeProperty(node, property, false);
            logger.debug("Removed property {} from node {}",
                    new Object[] { property.getJcrName(), node.getPath() });
        }
    }

    private static void removeProperty(Node node, ItemQName property, boolean multiValue)
            throws RepositoryException {
        if (property != null && node != null) {
            final String propertyName = property.getJcrName();
            if (node.hasProperty(propertyName))
                if (multiValue)
                    node.setProperty(propertyName, JcrValueUtils.getJcrNullForMultiValue());
                else
                    node.setProperty(propertyName, JcrValueUtils.getJcrNull());
        }
    }

    public static void addBinaryProperty(SaveMode saveMode, Node node, ItemQName propertyName, byte[] value,
            ValueFactory valueFactory) throws RepositoryException {
        if (value != null) {
            Value binary = JcrValueUtils.getJcrBinary(value, valueFactory);
            node.setProperty(propertyName.getJcrName(), binary);

            if (binary != null) {
                binary.getBinary().dispose();
            }
        } else if (saveMode == SaveMode.UPDATE) {
            removeProperty(node, propertyName, false);
        }

    }

    public static Node getTaxonomyJcrNode(Node topicNode, boolean throwExceptionIfNotFound)
            throws RepositoryException {
        Node taxonomyNode = topicNode;

        if (!taxonomyNode.isNodeType(CmsBuiltInItem.Taxonomy.getJcrName())) {
            //Try to find  taxonomy node
            taxonomyNode = topicNode.getParent();
            while (taxonomyNode != null && !taxonomyNode.isNodeType(CmsBuiltInItem.Taxonomy.getJcrName()))
                taxonomyNode = taxonomyNode.getParent();

        }

        if (throwExceptionIfNotFound
                && (taxonomyNode == null || !taxonomyNode.isNodeType(CmsBuiltInItem.Taxonomy.getJcrName()))) {
            throw new ItemNotFoundException("Unable to find taxonomy for topic " + topicNode.getPath());
        }

        return taxonomyNode;
    }

    public static Node getContentObjectNode(Node propertyContainerNode) throws RepositoryException {
        Node contentObjectNode = propertyContainerNode;

        if (!contentObjectNode.isNodeType(CmsBuiltInItem.StructuredContentObject.getJcrName())) {
            //Try to find contentObjectNode
            contentObjectNode = propertyContainerNode.getParent();
            while (!contentObjectNode.isNodeType(CmsBuiltInItem.StructuredContentObject.getJcrName()))
                contentObjectNode = contentObjectNode.getParent();

        }

        return contentObjectNode;
    }

    public static Node getOrganizationSpaceNode(Session session) throws RepositoryException {
        return getRootNode(session, CmsBuiltInItem.OrganizationSpace);
    }

    public static Node addContentObjectNode(Node dayNode, String type) throws RepositoryException {
        //Create node
        return dayNode.addNode(type, CmsBuiltInItem.StructuredContentObject.getJcrName());

    }

    public static Node addRepositoryUserNode(Session session) throws RepositoryException {
        Node repositoryUserNode = getRepositoryUserRootNode(session)
                .addNode(CmsBuiltInItem.RepositoryUser.getJcrName(), CmsBuiltInItem.RepositoryUser.getJcrName());

        repositoryUserNode.addNode(CmsBuiltInItem.Folksonomy.getJcrName(), CmsBuiltInItem.Taxonomy.getJcrName());

        return repositoryUserNode;
    }

    public static Node addSpaceNode(Node parentNode, String nodeNeme) throws RepositoryException {

        return parentNode.addNode(nodeNeme, CmsBuiltInItem.Space.getJcrName());
    }

    public static Node addTopicNode(Node parentNode, String nodeNeme) throws RepositoryException {

        return parentNode.addNode(nodeNeme, CmsBuiltInItem.Topic.getJcrName());
    }

    public static Node addBinaryChannelNode(Node binaryParentNode, String name) throws RepositoryException {
        return binaryParentNode.addNode(name, CmsBuiltInItem.BinaryChannel.getJcrName());
    }

    public static Node addNodeForComplexCmsProperty(Node parentComplexPropertyNode, String name)
            throws RepositoryException {

        Node childComplexPropertyNode = parentComplexPropertyNode.addNode(name,
                JcrBuiltInItem.NtUnstructured.getJcrName());

        childComplexPropertyNode.addMixin(JcrBuiltInItem.MixReferenceable.getJcrName());

        return childComplexPropertyNode;

    }

    public static Node addLocalizationNode(Node cmsRepositoryEntityNode) throws RepositoryException {

        return cmsRepositoryEntityNode.addNode(CmsBuiltInItem.Localization.getJcrName(),
                JcrBuiltInItem.NtUnstructured.getJcrName());

    }

    public static String getYearMonthDayPathForContentObjectNode(Node contentObjectNode)
            throws RepositoryException {

        if (contentObjectNode == null || contentObjectNode.getParent() == null) {
            return "";
        }

        //In  releases prior to 3 (2.x.x) content object nodes were stored
        //under path  contentTypeFolder/year/month/day
        //where as from release 3 and onwards content object nodes are stored under path
        //contentTypeFolder/year/month/day/hour/minute

        //This method takes under consideration both structures for compatibility reasons

        //Find content object type folder
        Node contentObjectTypeFolderNode = contentObjectNode.getParent();
        //Try to find contentObjectTypeFolder node
        while (contentObjectTypeFolderNode != null
                && !contentObjectTypeFolderNode.isNodeType(CmsBuiltInItem.GenericContentTypeFolder.getJcrName())) {
            contentObjectTypeFolderNode = contentObjectTypeFolderNode.getParent();
        }

        if (contentObjectTypeFolderNode == null) {
            return "";
        }

        String contentObjectNodeParentPath = contentObjectNode.getParent().getPath();
        String contentObjectTypeFolderPath = contentObjectTypeFolderNode.getPath();
        String path = StringUtils.difference(contentObjectTypeFolderPath + "/", contentObjectNodeParentPath);

        logger.debug("CO Parent Path {} \n Type Folder Path {}\n Difference {}",
                new Object[] { contentObjectNodeParentPath, contentObjectTypeFolderPath, path });

        //Path has either the format  year/month/day or year/month/day/hour/minute
        int count = StringUtils.countMatches(path, "/");

        if (count == 2) {
            return path;
        } else {
            //Must return the first two
            path = StringUtils.substringBeforeLast(path, "/");
            return StringUtils.substringBeforeLast(path, "/");
        }

    }
}