/**
* 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.content2bean;
import info.magnolia.cms.core.Content;
import info.magnolia.cms.util.NodeDataUtil;
import info.magnolia.content2bean.impl.Content2BeanTransformerImpl;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.jcr.RepositoryException;
import info.magnolia.objectfactory.ComponentProvider;
import info.magnolia.objectfactory.Components;
import org.apache.commons.beanutils.BeanUtils;
/**
* Utility class for content to bean transformations.
* In case you do not have to customize the transformation, you should use one of these methods:
* <ul>
* <li><code>toMap</code> is used to build a map from a node
* <li><code>toBean</code> transforms the nodes to beans
* <li><code>setProperties</code> tries to set the properties on the bean passed to the method
* <li><code>setNodeData</code> set the nodedatas based on the bean you pass
* </ul>
* @author philipp
* @version $Id$
*/
public class Content2BeanUtil {
/**
* Transforms all nodes to a map.
* @deprecated since 4.5 - use {@link ToMapTransformer}.
*/
public static final Content2BeanTransformerImpl TO_MAP_TRANSFORMER = new ToMapTransformer();
/**
* Provide a default class.
*/
public static final class DefaultClassTransformer extends Content2BeanTransformerImpl {
// private TypeDescriptor defaultType;
private final Class defaultClass;
public DefaultClassTransformer(Class defaultClass) {
// TODO - can't do this anymore since typeMapping is @Inject or passed, i.e not here yet.
// this.defaultType = getTypeMapping().getTypeDescriptor(defaultClass);
this.defaultClass = defaultClass;
}
@Override
protected TypeDescriptor onResolveType(TypeMapping typeMapping, TransformationState state, TypeDescriptor resolvedType, ComponentProvider componentProvider) {
// return resolvedType==null? defaultType : resolvedType;
return resolvedType==null? typeMapping.getTypeDescriptor(defaultClass) : resolvedType;
}
}
/**
* A {@link Content2BeanTransformer} transforming all nodes to Maps.
*/
public static class ToMapTransformer extends Content2BeanTransformerImpl {
public ToMapTransformer() {
}
@Override
public TypeDescriptor resolveType(TypeMapping typeMapping, TransformationState state, ComponentProvider componentProvider) throws ClassNotFoundException {
return TypeMapping.MAP_TYPE;
}
}
/**
* Get the current processor.
* @deprecated since 4.5, use IoC. - TODO only used locally
*/
public static Content2BeanProcessor getContent2BeanProcessor() {
return Components.getSingleton(Content2BeanProcessor.class);
}
/**
* Get the current processor.
* @deprecated since 4.5 - unused, Bean2Content is not implemented yet.
*/
public static Bean2ContentProcessor getBean2ContentProcessor() {
return Bean2ContentProcessor.Factory.getProcessor();
}
/**
* Get the current mapping.
* @deprecated since 4.5, use IoC.
*/
public static TypeMapping getTypeMapping() {
return Components.getSingleton(TypeMapping.class);
}
/**
* Get the current transformer.
* @deprecated since 4.5, use IoC.
*/
public static Content2BeanTransformer getContent2BeanTransformer() {
return Components.getSingleton(Content2BeanTransformer.class);
}
/**
* @see Content2BeanProcessor
* @deprecated since 4.5 - only used in tests - use {@link Content2Bean}
*/
public static Object toBean(Content node) throws Content2BeanException {
return toBean(node, false);
}
/**
* @see Content2BeanProcessor
* @deprecated since 4.5 - only used in tests - use {@link Content2Bean}
*/
public static Object toBean(Content node, final Class defaultClass) throws Content2BeanException {
return toBean(node, false, defaultClass);
}
/**
* @see Content2BeanProcessor
* @deprecated since 4.5 - TODO used in FilterManagerImpl, ParagraphManager and TemplateManager - use {@link Content2Bean}
*/
public static Object toBean(Content node, boolean recursive, final Class defaultClass) throws Content2BeanException {
return toBean(node, recursive, new Content2BeanTransformerImpl(){
@Override
protected TypeDescriptor onResolveType(TypeMapping typeMapping, TransformationState state, TypeDescriptor resolvedType, ComponentProvider componentProvider) {
if(resolvedType==null && state.getLevel() == 1){
return typeMapping.getTypeDescriptor(defaultClass);
}
return resolvedType;
}
});
}
/**
* @see Content2BeanProcessor
* @deprecated since 4.5- only used in DelegateVoter - use {@link Content2Bean}
*/
public static Object toBean(Content node, boolean recursive) throws Content2BeanException {
return toBean(node, recursive, getContent2BeanTransformer());
}
/**
* @see Content2BeanProcessor
* @deprecated since 4.5- only used in DelegateVoter - use {@link Content2Bean}
*/
public static Object toBean(Content node, boolean recursive, ComponentProvider componentProvider) throws Content2BeanException {
return toBean(node, recursive, componentProvider.getComponent(Content2BeanTransformer.class), componentProvider);
}
/**
* @see Content2BeanProcessor
* @deprecated since 4.5 use {@link Content2Bean}
* TODO -- this method has a bunch of usage points
*/
public static Object toBean(Content node, boolean recursive, Content2BeanTransformer transformer) throws Content2BeanException {
return toBean(node, recursive, transformer, Components.getComponentProvider());
}
/**
* @see Content2BeanProcessor
* @deprecated since 4.5 use {@link Content2Bean}
* TODO -- this method has a bunch of usage points
*/
public static Object toBean(Content node, boolean recursive, Content2BeanTransformer transformer, ComponentProvider componentProvider) throws Content2BeanException {
return componentProvider.getComponent(Content2BeanProcessor.class).toBean(node, recursive, transformer, componentProvider);
}
/**
* Transforms the nodes data into a map containing the names and values.
* @return a flat map
* @deprecated since 4.5 - not used - use {@link Content2Bean}
*/
public static Map toMap(Content node) throws Content2BeanException {
return toMap(node, false);
}
/**
* Transforms the nodes data into a map containing the names and values. In case recursive is true the sub-nodes are
* transformed to beans using the transformer. To avoid that use toMaps() instead
* @deprecated since 4.5 - only used in info.magnolia.setup.for3_5.UpdateI18nConfiguration - use {@link Content2Bean}
*/
public static Map toMap(Content node, boolean recursive) throws Content2BeanException {
return (Map) setProperties(new LinkedHashMap(), node, recursive);
}
/**
* @deprecated since 4.5 - TODO only used in DefaultMessagesManager - use {@link Content2Bean}
*/
public static <K, V> Map<K, V> toMap(Content node, boolean recursive, Class defaultClass) throws Content2BeanException {
return (Map<K, V>) setProperties(new LinkedHashMap(), node, recursive, defaultClass);
}
/**
* Transforms the nodes data into a map containing the names and values. In case recursive is true the sub-nodes are
* transformed to maps as well
* @deprecated since 4.5 - TODO only used in info.magnolia.setup.for3_5.CheckAndUpdateExistingFilters - use {@link Content2Bean}
*/
public static Map toPureMaps(Content node, boolean recursive) throws Content2BeanException {
return (Map) toBean(node, recursive, new ToMapTransformer());
}
/**
* @see Content2BeanProcessor
* @deprecated since 4.5 - unused - use {@link Content2Bean}
*/
public static Object setProperties(Object bean, Content node) throws Content2BeanException {
return setProperties(bean, node, false);
}
/**
* @see Content2BeanProcessor
* @deprecated since 4.5 - TODO - only used locally and by ModuleManagerImpl and TreeHandlerManager
*/
public static Object setProperties(Object bean, Content node, boolean recursive) throws Content2BeanException {
return setProperties(bean, node, recursive, getContent2BeanTransformer());
}
/**
* @deprecated since 4.5 - TODO - only used locally - use {@link Content2Bean}
*/
public static Object setProperties(Object bean, Content node, boolean recursive, final Class defaultClass) throws Content2BeanException {
return setProperties(bean, node, recursive, new Content2BeanTransformerImpl(){
@Override
protected TypeDescriptor onResolveType(TypeMapping typeMapping, TransformationState state, TypeDescriptor resolvedType, ComponentProvider componentProvider) {
if(resolvedType==null && state.getLevel() == 2){
return typeMapping.getTypeDescriptor(defaultClass);
}
return resolvedType;
}
});
}
/**
* @see Content2BeanProcessor
* @deprecated since 4.5 - use {@link Content2Bean}
*/
public static Object setProperties(Object bean, Content node, boolean recursive, Content2BeanTransformer transformer) throws Content2BeanException {
return setProperties(bean, node, recursive, transformer, Components.getComponentProvider());
}
/**
* @see Content2BeanProcessor
* @deprecated since 4.5 - use {@link Content2Bean}
*/
public static Object setProperties(Object bean, Content node, boolean recursive, Content2BeanTransformer transformer, ComponentProvider componentProvider) throws Content2BeanException {
return componentProvider.getComponent(Content2BeanProcessor.class).setProperties(bean, node, recursive, transformer, componentProvider);
}
/**
* @see Content2BeanProcessor
* @deprecated since 4.5 - only used in tests
*/
public static void addCollectionPropertyMapping(Class type, String name, Class mappedType) {
TypeMapping mapping = getTypeMapping();
mapping.getPropertyTypeDescriptor(type, name).setCollectionEntryType(mapping.getTypeDescriptor(mappedType));
}
/**
* TODO use the <code>Bean2ContentProcessor</code>.
* @deprecated since 4.5 - unused - use {@link Content2Bean}
*/
public static void setNodeDatas(Content node, Object bean, String[] excludes) throws Content2BeanException {
Map properties = toMap(bean);
for (int i = 0; i < excludes.length; i++) {
String exclude = excludes[i];
properties.remove(exclude);
}
setNodeDatas(node, properties);
}
/**
* TODO use the <code>Bean2ContentProcessor</code>.
* @deprecated since 4.5 - unused - use {@link Content2Bean}
*/
public static void setNodeDatas(Content node, Object obj) throws Content2BeanException {
setNodeDatas(node, toMap(obj));
}
/**
* TODO use the <code>Bean2ContentProcessor</code>.
* @deprecated since 4.5 - TODO - only used locally - use {@link Content2Bean}
*/
public static void setNodeDatas(Content node, Map map) throws Content2BeanException {
for (Iterator iter = map.keySet().iterator(); iter.hasNext();) {
String name = (String) iter.next();
try {
NodeDataUtil.getOrCreate(node, name).setValue(map.get(name).toString());
}
catch (RepositoryException e) {
throw new Content2BeanException("can't set/create nodedata [" + name + "] on node " + node.getHandle(), e);
}
}
}
/**
* Used to fake the <code>setNodeDatas()</code> methods.
* @deprecated since 4.5 - TODO - only used locally - use {@link Content2Bean}
*/
static private Map toMap(Object bean) throws Content2BeanException {
try {
return BeanUtils.describe(bean);
}
catch (Exception e) {
throw new Content2BeanException("can't read properties from bean", e);
}
}
}