/**
* This file Copyright (c) 2003-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.cms.util;
import info.magnolia.cms.core.Content;
import info.magnolia.cms.core.HierarchyManager;
import info.magnolia.cms.core.NodeData;
import info.magnolia.cms.i18n.Messages;
import info.magnolia.cms.i18n.MessagesManager;
import info.magnolia.cms.i18n.MessagesUtil;
import info.magnolia.cms.security.AccessDeniedException;
import info.magnolia.context.MgnlContext;
import info.magnolia.jcr.util.PropertyUtil;
import info.magnolia.repository.RepositoryConstants;
import java.io.InputStream;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
import javax.jcr.ValueFactory;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Util to work with {@link NodeData}.
* @author Sameer Charles
* @version $Revision$ ($Author$)
*/
public class NodeDataUtil {
private static final Logger log = LoggerFactory.getLogger(NodeDataUtil.class);
/**
* Same as getValueString(nd, dateFormat) but using the users short date format.
*/
public static String getValueString(NodeData nodeData) {
String dateFormat = null;
if(nodeData.getType() == PropertyType.DATE){
dateFormat = PropertyUtil.getDateFormat();
}
return getValueString(nodeData, dateFormat);
}
/**
* Returns a String representation of the value. In case of a binary the path including filename and extension is returned
* @param nodeData
* @param dateFormat date format to use in the case it is a date
* @return
*/
public static String getValueString(NodeData nodeData, String dateFormat) {
// we can't use FileProperties since this class is in the GUI package
if(nodeData.getType()==PropertyType.BINARY){
String filename = nodeData.getAttribute("fileName");
String ext = nodeData.getAttribute("extension");
String fullName = filename;
String fullExt = StringUtils.EMPTY;
if (StringUtils.isNotEmpty(ext)) {
fullExt = "." + ext;
fullName += fullExt;
}
return nodeData.getHandle() + "/" + fullName;
}
else if (nodeData.isMultiValue() == NodeData.MULTIVALUE_TRUE){
return StringUtils.join(getValuesStringList(nodeData.getValues()), ",");
} else {
return getValueString(nodeData.getValue(), dateFormat);
}
}
/**
* Same as value.getString(), but using custom date format.
*/
public static String getValueString(Value value, String dateFormat) {
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, dateFormat);
case (PropertyType.BINARY):
// ???
default:
return StringUtils.EMPTY;
}
}
catch (Exception e) {
log.debug("Exception caught: " + e.getMessage(), e); //$NON-NLS-1$
}
return StringUtils.EMPTY;
}
/**
* Inherit a value. Uses the string value. The "inherit" means that the method will look for the value in the content itself and if not found
* it will go up in the tree and try to locate value in one of the parents of the content until reaching the root. The first value found while
* traversing the tree way up is the one that will be returned.
* @param node Node expected to define or inherit the searched node value.
* @param name Name of the nodeData.
*/
public static String inheritString(Content node, String name) throws RepositoryException{
String value = "";
if (node.hasNodeData(name)) {
value = NodeDataUtil.getString(node, name);
}
if(StringUtils.isEmpty(value) && node.getLevel() > 0){
value = inheritString(node.getParent(), name);
}
return value;
}
/**
* Inherit a value. You can provide a default value if not found
*/
public static String inheritString(Content node, String name, String dflt) throws RepositoryException{
String value = inheritString(node, name);
if(StringUtils.isEmpty(value)){
return dflt;
}
return value;
}
/**
* Inherit a value. Uses the string value
*/
public static Object inherit(Content node, String name) throws RepositoryException{
Object value = null;
if (node.hasNodeData(name)) {
value = NodeDataUtil.getValueObject(node.getNodeData(name));
}
if(value == null && node.getLevel() > 0){
value = inherit(node.getParent(), name);
}
return value;
}
/**
* Inherit a value. You can provide a default value if not found
*/
public static Object inherit(Content node, String name, Object dflt) throws RepositoryException{
Object value = inherit(node, name);
if(value == null){
return dflt;
}
return value;
}
/**
* Returns the value as an Object.
* @return Object
*/
public static Object getValueObject(NodeData nd) {
try {
switch (nd.getType()) {
case (PropertyType.STRING):
return nd.getString();
case (PropertyType.DOUBLE):
return Double.valueOf(nd.getDouble());
case (PropertyType.LONG):
return Long.valueOf(nd.getLong());
case (PropertyType.BOOLEAN):
return Boolean.valueOf(nd.getBoolean());
case (PropertyType.DATE):
return nd.getDate().getTime();
case (PropertyType.BINARY):
return null;
default:
return null;
}
}
catch (Exception e) {
log.debug("Exception caught: " + e.getMessage(), e); //$NON-NLS-1$
}
return null;
}
/**
* Calls the correct setValue method based on object type. If the value is null an empty string is set.
*/
public static NodeData setValue(NodeData nodeData, Object valueObj) throws AccessDeniedException, RepositoryException{
if(valueObj == null){
nodeData.setValue(StringUtils.EMPTY);
}
else{
switch (PropertyUtil.getJCRPropertyType(valueObj)) {
case PropertyType.STRING:
nodeData.setValue((String)valueObj);
break;
case PropertyType.BOOLEAN:
nodeData.setValue(((Boolean)valueObj).booleanValue());
break;
case PropertyType.DATE:
nodeData.setValue((Calendar)valueObj);
break;
case PropertyType.LONG:
// can either be a Long or Integer - see #getJCRPropertyType(Object)
long longToSet = (valueObj instanceof Integer) ? ((Integer) valueObj).longValue() : ((Long) valueObj).longValue();
nodeData.setValue(longToSet);
break;
case PropertyType.DOUBLE:
// can either be a Double or Float - see #getJCRPropertyType(Object)
double doubleToSet = (valueObj instanceof Float) ? ((Float) valueObj).doubleValue() : ((Double) valueObj).doubleValue();
nodeData.setValue(doubleToSet);
break;
case PropertyType.BINARY:
nodeData.setValue((InputStream)valueObj);
break;
case PropertyType.REFERENCE:
nodeData.setValue((Content)valueObj);
break;
default:
nodeData.setValue(valueObj.toString());
}
}
return nodeData;
}
/**
* String representation of the jcr property type.
*/
public static String getTypeName(NodeData nd) {
return PropertyType.nameFromValue(nd.getType());
}
/**
* Simple method to get strings like configuration informations.
*/
public static String getString(String repository, String path) {
return getString(repository, path, null);
}
/**
* Get the string or the empty string if not existing.
*/
public static String getString(Content node, String name) {
return getString(node, name, "");
}
/**
* You can define a default value if not found.
*/
public static String getString(String repository, String path, String defaultValue) {
try {
String name = StringUtils.substringAfterLast(path, "/");
String nodeHandle = StringUtils.substringBeforeLast(path, "/");
Content node = MgnlContext.getHierarchyManager(repository).getContent(nodeHandle);
return getString(node, name);
}
catch (Exception e) {
return defaultValue;
}
}
/**
* You can define a default value if not found.
*/
public static String getString(Content node, String name, String defaultValue) {
try {
if (node.hasNodeData(name)) {
return getValueString(node.getNodeData(name));
}
return defaultValue;
}
catch (Exception e) {
return defaultValue;
}
}
public static long getLong(Content node, String name, long defaultValue) {
try {
if(node.hasNodeData(name)){
return node.getNodeData(name).getLong();
}
}
// should not happen
catch (RepositoryException e) {
log.error("can't read value will return default value", e);
}
return defaultValue;
}
public static Calendar getDate(Content node, String name, Calendar defaultValue) {
try {
if(node.hasNodeData(name)){
return node.getNodeData(name).getDate();
}
}
// should not happen
catch (RepositoryException e) {
log.error("can't read value will return default value", e);
}
return defaultValue;
}
public static boolean getBoolean(Content node, String name, boolean defaultValue) {
try {
if(node.hasNodeData(name)){
return node.getNodeData(name).getBoolean();
}
}
// should not happen
catch (RepositoryException e) {
log.error("can't read value will return default value", e);
}
return defaultValue;
}
/**
* If the NodeData does not exist yet, just create it.
* @param node
* @param name
* @return the found or created NodeData
* @throws AccessDeniedException
* @throws RepositoryException
*/
public static NodeData getOrCreate(Content node, String name) throws AccessDeniedException, RepositoryException {
return getOrCreate(node, name, PropertyType.STRING);
}
/**
* If the NodeData does not exist yet, just create it.
* @param node
* @param name
* @return the found or created NodeData
* @throws AccessDeniedException
* @throws RepositoryException
*/
public static NodeData getOrCreate(Content node, String name, int type) throws AccessDeniedException,
RepositoryException {
if (node.hasNodeData(name)) {
return node.getNodeData(name);
}
return node.createNodeData(name, type);
}
public static NodeData getOrCreate(Content node, String name, Object obj) throws AccessDeniedException,
RepositoryException {
return getOrCreate(node, name, PropertyUtil.getJCRPropertyType(obj));
}
public static NodeData getOrCreateAndSet(Content node, String name, Object obj) throws AccessDeniedException, RepositoryException {
// TODO we should not use the jcr node
ValueFactory valueFactory = node.getJCRNode().getSession().getValueFactory();
NodeData nd = getOrCreate(node, name, PropertyUtil.getJCRPropertyType(obj));
nd.setValue(createValue(obj, valueFactory));
return nd;
}
public static NodeData getOrCreateAndSet(Content node, String name, long value) throws AccessDeniedException, RepositoryException {
return getOrCreateAndSet(node, name, Long.valueOf(value));
}
public static NodeData getOrCreateAndSet(Content node, String name, Value[] value) throws AccessDeniedException, RepositoryException {
if (node.hasNodeData(name)) {
node.setNodeData(name, value);
return node.getNodeData(name);
}
return node.createNodeData(name, value);
}
public static NodeData getOrCreateAndSet(Content node, String name, int value) throws AccessDeniedException, RepositoryException {
return getOrCreateAndSet(node, name, Long.valueOf(value));
}
public static NodeData getOrCreateAndSet(Content node, String name, boolean value) throws AccessDeniedException, RepositoryException {
return getOrCreateAndSet(node, name, Boolean.valueOf(value));
}
/**
* Uses the i18n mechanism to translate the message if the resulting string is a key.
*/
public static String getI18NString(Content node, String str) {
Messages msgs = MessagesManager.getMessages();
String key = getString(node, str);
String i18nBasename = null;
try {
i18nBasename = NodeDataUtil.inheritString(node, "i18nBasename");
}
catch (RepositoryException e) {
log.error("can't read i18nBasename value, will default back", e);
}
if (StringUtils.isNotEmpty(i18nBasename)) {
msgs = MessagesUtil.chainWithDefault(i18nBasename);
}
return msgs.getWithDefault(key, key);
}
/**
* Uses the i18n mechanism to translate the message if the resulting string is a key.
*/
public static String getI18NString(Content node, String str, String basename) {
String key = getString(node, str);
return MessagesManager.getMessages(basename).getWithDefault(key, key);
}
/**
* Uses the default value factory.
*/
public static Value createValue(String valueStr, int type) throws RepositoryException {
HierarchyManager hm = MgnlContext.getSystemContext().getHierarchyManager(RepositoryConstants.CONFIG);
ValueFactory valueFactory = hm.getWorkspace().getSession().getValueFactory();
return createValue(valueStr, type, valueFactory);
}
/**
* @deprecated since 4.5 - use {@link PropertyUtil#createValue(Object, ValueFactory)} instead
*/
@Deprecated
public static Value createValue(Object obj, ValueFactory valueFactory) throws RepositoryException {
return PropertyUtil.createValue(obj, valueFactory);
}
/**
* Transforms a string to a jcr value object.
*
* @deprecated since 4.5 - directly use {@link PropertyUtil#createValue(String, int, ValueFactory)} instead.
*/
@Deprecated
public static Value createValue(String valueStr, int type, ValueFactory valueFactory) {
return PropertyUtil.createValue(valueStr, type, valueFactory);
}
/**
* @deprecated since 4.5 - use {@link PropertyUtil#getJCRPropertyType(Object)} instead
*/
@Deprecated
public static int getJCRPropertyType(Object obj) {
return PropertyUtil.getJCRPropertyType(obj);
}
/**
* @deprecated since 4.5 - use {@link PropertyUtil#getValuesStringList(Value[])} instead
*/
@Deprecated
public static List<String> getValuesStringList(Value[] values) {
return PropertyUtil.getValuesStringList(values);
}
/**
* @deprecated since 4.5 - use {@link PropertyUtil#getDateFormat()} instead
*/
@Deprecated
public static String getDateFormat() {
return PropertyUtil.getDateFormat();
}
}