View Javadoc

1   /**
2    * This file Copyright (c) 2003-2010 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.content2bean;
35  
36  import info.magnolia.cms.core.Content;
37  import info.magnolia.cms.util.NodeDataUtil;
38  import info.magnolia.content2bean.impl.Content2BeanTransformerImpl;
39  
40  import java.util.Iterator;
41  import java.util.LinkedHashMap;
42  import java.util.Map;
43  
44  import javax.jcr.RepositoryException;
45  
46  import org.apache.commons.beanutils.BeanUtils;
47  import org.slf4j.Logger;
48  import org.slf4j.LoggerFactory;
49  
50  /**
51   * In case you do not have to customize the transformation, you should use one of these methods
52   * <ul>
53   * <li><code>toMap</code> is used to build a map from a node
54   * <li><code>toBean<code> transforms the nodes to beans
55   * <li><code>setProperties<code> tries to set the properties on the bean passed to the method
56   * <li><code>setNodeData<code> set the nodedatas based on the bean you pass
57   * </ul>
58   * @author philipp
59   * @version $Id: Content2BeanUtil.java 32667 2010-03-13 00:37:06Z gjoseph $
60   */
61  public class Content2BeanUtil {
62      private static final Logger log = LoggerFactory.getLogger(Content2BeanUtil.class);
63  
64      /**
65       * Transforms all nodes to a map
66       */
67      public static final Content2BeanTransformerImpl TO_MAP_TRANSFORMER = new Content2BeanTransformerImpl() {
68  
69          public TypeDescriptor resolveType(TransformationState state) throws ClassNotFoundException {
70              return TypeMapping.MAP_TYPE;
71          }
72      };
73  
74      /**
75       * Provide a default class.
76       */
77      public static final class DefaultClassTransformer extends Content2BeanTransformerImpl {
78  
79          private TypeDescriptor defaultType;
80  
81          public DefaultClassTransformer(Class defaultClass) {
82              this.defaultType = getTypeMapping().getTypeDescriptor(defaultClass);
83          }
84  
85          protected TypeDescriptor onResolveType(TransformationState state, TypeDescriptor resolvedType) {
86              return resolvedType==null? defaultType : resolvedType;
87          }
88      }
89  
90      /**
91       * Get the current processor
92       */
93      public static Content2BeanProcessor getContent2BeanProcessor() {
94          return Content2BeanProcessor.Factory.getProcessor();
95      }
96  
97      /**
98       * Get the current processor
99       */
100     public static Bean2ContentProcessor getBean2ContentProcessor() {
101         return Bean2ContentProcessor.Factory.getProcessor();
102     }
103 
104     /**
105      * Get the current mapping
106      */
107     public static TypeMapping getTypeMapping() {
108         return TypeMapping.Factory.getDefaultMapping();
109     }
110 
111     /**
112      * Get the current transformer
113      */
114     public static Content2BeanTransformer getContent2BeanTransformer() {
115         return Content2BeanTransformer.Factory.getDefaultTransformer();
116     }
117 
118 
119     /**
120      * @see Content2BeanProcessor
121      */
122     public static Object toBean(Content node) throws Content2BeanException {
123         return toBean(node, false);
124     }
125 
126     /**
127      * @see Content2BeanProcessor
128      */
129     public static Object toBean(Content node, final Class defaultClass) throws Content2BeanException {
130         return toBean(node, false, new DefaultClassTransformer(defaultClass));
131     }
132 
133     /**
134      * @see Content2BeanProcessor
135      */
136     public static Object toBean(Content node, boolean recursive, final Class defaultClass) throws Content2BeanException {
137         return toBean(node, recursive, new DefaultClassTransformer(defaultClass));
138     }
139 
140     /**
141      * @see Content2BeanProcessor
142      */
143     public static Object toBean(Content node, boolean recursive) throws Content2BeanException {
144         return toBean(node, recursive, getContent2BeanTransformer());
145     }
146 
147     /**
148      * @see Content2BeanProcessor
149      */
150     public static Object toBean(Content node, boolean recursive, Content2BeanTransformer transformer) throws Content2BeanException {
151         return getContent2BeanProcessor().toBean(node, recursive, transformer);
152     }
153 
154     /**
155      * Transforms the nodes data into a map containting the names and values.
156      * @return a flat map
157      */
158     public static Map toMap(Content node) throws Content2BeanException {
159         return toMap(node, false);
160     }
161 
162 
163     /**
164      * Transforms the nodes data into a map containting the names and values. In case recursive is true the subnodes are
165      * transformed to beans using the transformer. To avoid that use toMaps() instead
166      */
167     public static Map toMap(Content node, boolean recursive) throws Content2BeanException {
168         return (Map) setProperties(new LinkedHashMap(), node, recursive);
169     }
170 
171     public static Map toMap(Content node, boolean recursive, Class defaultClass) throws Content2BeanException {
172         return (Map) setProperties(new LinkedHashMap(), node, recursive, defaultClass);
173     }
174 
175     /**
176      * Transforms the nodes data into a map containting the names and values. In case recursive is true the subnodes are
177      * transformed to maps as well
178      */
179     public static Map toPureMaps(Content node, boolean recursive) throws Content2BeanException {
180         return (Map) toBean(node, recursive, TO_MAP_TRANSFORMER);
181     }
182 
183     /**
184      * @see Content2BeanProcessor
185      */
186     public static Object setProperties(Object bean, Content node) throws Content2BeanException {
187         return setProperties(bean, node, false);
188     }
189 
190     /**
191      * @see Content2BeanProcessor
192      */
193     public static Object setProperties(Object bean, Content node, boolean recursive) throws Content2BeanException {
194         return setProperties(bean, node, recursive, getContent2BeanTransformer());
195     }
196 
197     public static Object setProperties(Object bean, Content node, boolean recursive, Class defaultClass) throws Content2BeanException {
198         return setProperties(bean, node, recursive, new DefaultClassTransformer(defaultClass));
199     }
200     /**
201      * @see Content2BeanProcessor
202      */
203     public static Object setProperties(Object bean, Content node, boolean recursive, Content2BeanTransformer transformer) throws Content2BeanException {
204         return getContent2BeanProcessor().setProperties(bean, node, recursive, transformer);
205     }
206 
207     /**
208      * @see Content2BeanProcessor
209      */
210     public static void addCollectionPropertyMapping(Class type, String name, Class mappedType) {
211         TypeMapping mapping = getTypeMapping();
212         mapping.getPropertyTypeDescriptor(type, name).setCollectionEntryType(mapping.getTypeDescriptor(mappedType));
213     }
214 
215     /**
216      * @todo use the Bean2ContentProcessor
217      */
218     public static void setNodeDatas(Content node, Object bean, String[] excludes) throws Content2BeanException {
219         Map properties = toMap(bean);
220 
221         for (int i = 0; i < excludes.length; i++) {
222             String exclude = excludes[i];
223             properties.remove(exclude);
224         }
225 
226         setNodeDatas(node, properties);
227     }
228 
229     /**
230      * @todo use the Bean2ContentProcessor
231      */
232     public static void setNodeDatas(Content node, Object obj) throws Content2BeanException {
233         setNodeDatas(node, toMap(obj));
234     }
235 
236     /**
237      * @todo use the Bean2ContentProcessor
238      */
239     public static void setNodeDatas(Content node, Map map) throws Content2BeanException {
240         for (Iterator iter = map.keySet().iterator(); iter.hasNext();) {
241             String name = (String) iter.next();
242             try {
243                 NodeDataUtil.getOrCreate(node, name).setValue(map.get(name).toString());
244             }
245             catch (RepositoryException e) {
246                 throw new Content2BeanException("can't set/create nodedata [" + name + "] on node " + node.getHandle(), e);
247             }
248         }
249     }
250 
251     /**
252      * Used to fake the setNodeDatas() methods
253      */
254     static private Map toMap(Object bean) throws Content2BeanException {
255         try {
256             return BeanUtils.describe(bean);
257         }
258         catch (Exception e) {
259             throw new Content2BeanException("can't read properties from bean", e);
260         }
261     }
262 
263 
264 
265 }
266