info.magnolia.jcr.util.PropertyUtil.java Source code

Java tutorial

Introduction

Here is the source code for info.magnolia.jcr.util.PropertyUtil.java

Source

/**
 * This file Copyright (c) 2011-2012 Magnolia International
 * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
 *
 *
 * This file is dual-licensed under both the Magnolia
 * Network Agreement and the GNU General Public License.
 * You may elect to use one or the other of these licenses.
 *
 * This file is distributed in the hope that it will be
 * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
 * implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
 * Redistribution, except as permitted by whichever of the GPL
 * or MNA you select, is prohibited.
 *
 * 1. For the GPL license (GPL), you can redistribute and/or
 * modify this file under the terms of the GNU General
 * Public License, Version 3, as published by the Free Software
 * Foundation.  You should have received a copy of the GNU
 * General Public License, Version 3 along with this program;
 * if not, write to the Free Software Foundation, Inc., 51
 * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * 2. For the Magnolia Network Agreement (MNA), this file
 * and the accompanying materials are made available under the
 * terms of the MNA which accompanies this distribution, and
 * is available at http://www.magnolia-cms.com/mna.html
 *
 * Any modifications to this file must keep this entire header
 * intact.
 *
 */
package info.magnolia.jcr.util;

import info.magnolia.cms.core.Content;
import info.magnolia.cms.util.DateUtil;
import info.magnolia.context.MgnlContext;

import java.io.InputStream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TimeZone;

import javax.jcr.Binary;
import javax.jcr.Node;
import javax.jcr.Property;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
import javax.jcr.ValueFactory;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.FastDateFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Property-related utility methods.
 */
public class PropertyUtil {

    private static final Logger log = LoggerFactory.getLogger(PropertyUtil.class);

    public static void renameProperty(Property property, String newName) throws RepositoryException {
        Node node = property.getParent();
        node.setProperty(newName, property.getValue());
        property.remove();
    }

    /**
     * Allows setting a Node's property from an object.
     */
    @SuppressWarnings("unchecked")
    public static void setProperty(Node node, String propertyName, Object propertyValue)
            throws RepositoryException {
        if (node == null) {
            throw new IllegalArgumentException("Cannot set a property on a null-node!");
        }
        if (propertyName == null) {
            throw new IllegalArgumentException("Cannot set a property without a provided name");
        }

        if (propertyValue == null) {
            node.setProperty(propertyName, (Value) null);
        } else if (propertyValue instanceof Value) {
            node.setProperty(propertyName, (Value) propertyValue);
        } else if (propertyValue instanceof Node) {
            node.setProperty(propertyName, (Node) propertyValue);
        } else if (propertyValue instanceof Binary) {
            node.setProperty(propertyName, (Binary) propertyValue);
        } else if (propertyValue instanceof Calendar) {
            node.setProperty(propertyName, (Calendar) propertyValue);
        } else if (propertyValue instanceof Date) {
            Calendar cal = Calendar.getInstance();
            cal.setTime((Date) propertyValue);
            node.setProperty(propertyName, cal);
        } else if (propertyValue instanceof BigDecimal) {
            node.setProperty(propertyName, (BigDecimal) propertyValue);
        } else if (propertyValue instanceof String) {
            node.setProperty(propertyName, (String) propertyValue);
        } else if (propertyValue instanceof Long) {
            node.setProperty(propertyName, ((Long) propertyValue).longValue());
        } else if (propertyValue instanceof Double) {
            node.setProperty(propertyName, (Double) propertyValue);
        } else if (propertyValue instanceof Boolean) {
            node.setProperty(propertyName, (Boolean) propertyValue);
        } else if (propertyValue instanceof InputStream) {
            node.setProperty(propertyName, (InputStream) propertyValue);
        } else if (propertyValue instanceof Collection) {
            String[] list = new String[((Collection<Object>) propertyValue).size()];
            int pos = 0;
            for (Object value : (Collection<Object>) propertyValue) {
                list[pos] = value.toString();
                pos += 1;
            }
            node.setProperty(propertyName, list);
        } else {
            // TODO dlipp: verify if this is desired default-behavior: NodeDataUtil#setValue sets propertyValue.toString() as default!
            throw new IllegalArgumentException(
                    "Cannot set property to a value of type " + propertyValue.getClass());
        }
    }

    /**
     * Transforms a string to a jcr value object.
     */
    public static Value createValue(String valueStr, int type, ValueFactory valueFactory) {
        Value value = null;
        if (type == PropertyType.STRING) {
            value = valueFactory.createValue(valueStr);
        } else if (type == PropertyType.BOOLEAN) {
            value = valueFactory.createValue(BooleanUtils.toBoolean(valueStr));
        } else if (type == PropertyType.DOUBLE) {
            try {
                value = valueFactory.createValue(Double.parseDouble(valueStr));
            } catch (NumberFormatException e) {
                value = valueFactory.createValue(0d);
            }
        } else if (type == PropertyType.LONG) {
            try {
                value = valueFactory.createValue(Long.parseLong(valueStr));
            } catch (NumberFormatException e) {
                value = valueFactory.createValue(0L);
            }
        } else if (type == PropertyType.DATE) {
            try {
                Calendar date = new GregorianCalendar();
                try {
                    String newDateAndTime = valueStr;
                    String[] dateAndTimeTokens = newDateAndTime.split("T");
                    String newDate = dateAndTimeTokens[0];
                    String[] dateTokens = newDate.split("-");
                    int hour = 0;
                    int minute = 0;
                    int second = 0;
                    int year = Integer.parseInt(dateTokens[0]);
                    int month = Integer.parseInt(dateTokens[1]) - 1;
                    int day = Integer.parseInt(dateTokens[2]);
                    if (dateAndTimeTokens.length > 1) {
                        String newTime = dateAndTimeTokens[1];
                        String[] timeTokens = newTime.split(":");
                        hour = Integer.parseInt(timeTokens[0]);
                        minute = Integer.parseInt(timeTokens[1]);
                        second = Integer.parseInt(timeTokens[2]);
                    }
                    date.set(year, month, day, hour, minute, second);
                    // this is used in the searching
                    date.set(Calendar.MILLISECOND, 0);
                    date.setTimeZone(TimeZone.getTimeZone("GMT"));
                }
                // todo time zone??
                catch (Exception e) {
                    // ignore, it sets the current date / time
                }
                value = valueFactory.createValue(date);
            } catch (Exception e) {
                log.debug("Exception caught: " + e.getMessage(), e);
            }
        }

        return value;

    }

    /**
     * @return JCR-PropertyType corresponding to provided Object.
     */
    public static int getJCRPropertyType(Object obj) {
        if (obj instanceof String) {
            return PropertyType.STRING;
        }
        if (obj instanceof Double) {
            return PropertyType.DOUBLE;
        }
        if (obj instanceof Float) {
            return PropertyType.DOUBLE;
        }
        if (obj instanceof Long) {
            return PropertyType.LONG;
        }
        if (obj instanceof Integer) {
            return PropertyType.LONG;
        }
        if (obj instanceof Boolean) {
            return PropertyType.BOOLEAN;
        }
        if (obj instanceof Calendar) {
            return PropertyType.DATE;
        }
        if (obj instanceof Binary) {
            return PropertyType.BINARY;
        }
        if (obj instanceof InputStream) {
            return PropertyType.BINARY;
        }
        if (obj instanceof Content) {
            return PropertyType.REFERENCE;
        }
        return PropertyType.UNDEFINED;
    }

    /**
     * Updates existing property or creates a new one if it doesn't exist already.
     */
    public static void updateOrCreate(Node node, String string, GregorianCalendar gregorianCalendar)
            throws RepositoryException {
        if (node.hasProperty(string)) {
            node.getProperty(string).setValue(gregorianCalendar);
        } else {
            node.setProperty(string, gregorianCalendar);
        }
    }

    public static String getDateFormat() {
        try {
            return FastDateFormat.getDateInstance(FastDateFormat.SHORT, MgnlContext.getLocale()).getPattern();
        } catch (IllegalStateException e) {
            // this happens if the context is not (yet) set
            return DateUtil.YYYY_MM_DD;
        }
    }

    public static List<String> getValuesStringList(Value[] values) {
        ArrayList<String> list = new ArrayList<String>();
        for (Value value : values) {
            list.add(getValueString(value));
        }
        return list;
    }

    /**
     * Returns value of the property converted to string no matter what it's type actually is. In case of dates, value if formatted according to format returned by {@link #getDateFormat()}. Binary and reference values are converted to empty string. In case of error during conversion, null will be returned instead. Works only for single value properties.
     */
    public static String getValueString(Property property) {
        try {
            return getValueString(property.getValue());
        } catch (RepositoryException e) {
            log.debug("RepositoryException caught: " + e.getMessage(), e);
            return null;
        }
    }

    /**
     * Returns value converted to string no matter what it's type actually is. In case of dates, value if formatted according to format returned by {@link #getDateFormat()}. Binary and reference values are converted to empty string. In case of error during conversion, null will be returned instead.
     */
    public static String getValueString(Value value) {
        try {
            switch (value.getType()) {
            case (PropertyType.STRING):
                return value.getString();
            case (PropertyType.DOUBLE):
                return Double.toString(value.getDouble());
            case (PropertyType.LONG):
                return Long.toString(value.getLong());
            case (PropertyType.BOOLEAN):
                return Boolean.toString(value.getBoolean());
            case (PropertyType.DATE):
                Date valueDate = value.getDate().getTime();
                return DateUtil.format(valueDate, PropertyUtil.getDateFormat());
            case (PropertyType.BINARY):
                // for lack of better solution, fall through to the default - empty string
            default:
                return StringUtils.EMPTY;
            }
        } catch (RepositoryException e) {
            log.debug("RepositoryException caught: " + e.getMessage(), e);
        }
        return null;

    }

    public static Value createValue(Object obj, ValueFactory valueFactory) throws RepositoryException {
        switch (PropertyUtil.getJCRPropertyType(obj)) {
        case PropertyType.STRING:
            return valueFactory.createValue((String) obj);
        case PropertyType.BOOLEAN:
            return valueFactory.createValue((Boolean) obj);
        case PropertyType.DATE:
            return valueFactory.createValue((Calendar) obj);
        case PropertyType.LONG:
            return obj instanceof Long ? valueFactory.createValue(((Long) obj).longValue())
                    : valueFactory.createValue(((Integer) obj).longValue());
        case PropertyType.DOUBLE:
            return obj instanceof Double ? valueFactory.createValue((Double) obj)
                    : valueFactory.createValue(((Float) obj).doubleValue());
        case PropertyType.BINARY:
            return valueFactory.createValue((InputStream) obj);
        case PropertyType.REFERENCE:
            return valueFactory.createValue(((Content) obj).getJCRNode());
        default:
            return (obj != null ? valueFactory.createValue(obj.toString())
                    : valueFactory.createValue(StringUtils.EMPTY));
        }
    }

    /**
     * Return the Calendar representing the node property value.
     * If the Node did not contain such a Property,
     * then return <b>null</b>.
     */
    public static Calendar getDate(Node node, String name) {
        return getDate(node, name, null);
    }

    /**
     * Return the Calendar representing the node property value.
     * If the Node did not contain such a Property,
     * then return the default value.
     */
    public static Calendar getDate(Node node, String name, Calendar defaultValue) {
        try {
            if (node.hasProperty(name)) {
                return node.getProperty(name).getDate();
            }
        } catch (RepositoryException e) {
            log.error("can't read value '" + name + "' of the Node '" + node.toString()
                    + "' will return default value", e);
        }
        return defaultValue;
    }

    /**
     * Return the String representing the node property value.
     * If the Node did not contain such a Property,
     * then return <b>null</b>.
     */
    public static String getString(Node node, String name) {
        return getString(node, name, null);
    }

    /**
     * Return the String representing the node property value.
     * If the Node did not contain such a Property,
     * then return the default value.
     */
    public static String getString(Node node, String name, String defaultValue) {
        try {
            if (node.hasProperty(name)) {
                return node.getProperty(name).getString();
            }
        } catch (RepositoryException e) {
            log.error("can't read value '" + name + "' of the Node '" + node.toString()
                    + "' will return default value", e);
        }
        return defaultValue;
    }

    /**
     * Return the boolean representing the node property value.
     * If the Node did not contain such a Property,
     * then return the default value.
     */
    public static boolean getBoolean(Node node, String name, boolean defaultValue) {
        try {
            if (node.hasProperty(name)) {
                return node.getProperty(name).getBoolean();
            }
        } catch (RepositoryException e) {
            log.error("can't read value '" + name + "' of the Node '" + node.toString()
                    + "' will return default value", e);
        }
        return defaultValue;
    }

    /**
     * Return the Property relative to the Node or null if it's not existing or in case of any RepositoryException.
     */
    public static Property getPropertyOrNull(Node node, String relativePath) {
        try {
            return node.hasProperty(relativePath) ? node.getProperty(relativePath) : null;
        } catch (RepositoryException e) {
            log.debug("Could not retrieve property " + relativePath, e);
        }
        return null;
    }

    /**
     * @deprecated since 4.5 - use getPropertyOrNull instead
     */
    public static Property getProperty(Node node, String relativePath) {
        return getPropertyOrNull(node, relativePath);
    }

    /**
     * Return the Value Object from a property.
     * Return null in case of exception.
     * The returned Object could be a basic {@link PropertyType} type or in case
     * of multivalue, a Set of {@link PropertyType} type objects.
     *
     */
    public static Object getPropertyValueObject(Node node, String relativePath) {
        final Property property = getPropertyOrNull(node, relativePath);
        if (property != null) {
            try {
                //Handle Multivalue fields
                if (property.isMultiple()) {
                    Value[] values = property.getValues();
                    Set<Object> res = new HashSet<Object>();
                    for (Value value : values) {
                        res.add(getValueObject(value));
                    }
                    return res;
                } else {
                    return getValueObject(property.getValue());
                }

            } catch (Exception e) {
                log.warn("Exception during casting the property value", e);
            }
        }
        return null;
    }

    /**
     * Return the Value Object from a {@link Value}.
     * Return null in case of exception.
     */
    public static Object getValueObject(Value value) {
        try {
            switch (value.getType()) {
            case (PropertyType.DECIMAL):
                return value.getDecimal();
            case (PropertyType.STRING):
                return value.getString();
            case (PropertyType.DOUBLE):
                return Double.valueOf(value.getDouble());
            case (PropertyType.LONG):
                return Long.valueOf(value.getLong());
            case (PropertyType.BOOLEAN):
                return Boolean.valueOf(value.getBoolean());
            case (PropertyType.DATE):
                return value.getDate().getTime();
            case (PropertyType.BINARY):
                return IOUtils.toByteArray(value.getBinary().getStream());
            default:
                return null;
            }
        } catch (Exception e) {
            log.warn("Exception during casting the property value", e);
        }
        return null;
    }

}