1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.content2bean.impl;
35
36 import info.magnolia.cms.core.Content;
37 import info.magnolia.cms.core.NodeData;
38 import info.magnolia.cms.util.ExtendingContentWrapper;
39 import info.magnolia.cms.util.NodeDataUtil;
40 import info.magnolia.content2bean.Content2BeanException;
41 import info.magnolia.content2bean.Content2BeanProcessor;
42 import info.magnolia.content2bean.Content2BeanTransformer;
43 import info.magnolia.content2bean.PropertyTypeDescriptor;
44 import info.magnolia.content2bean.TransformationState;
45 import info.magnolia.content2bean.TypeDescriptor;
46
47 import java.util.Collection;
48 import java.util.LinkedHashMap;
49 import java.util.Map;
50
51 import javax.jcr.RepositoryException;
52
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
55
56
57
58
59
60
61
62
63 public class Content2BeanProcessorImpl implements Content2BeanProcessor {
64 private static final Logger log = LoggerFactory.getLogger(Content2BeanProcessorImpl.class);
65
66 private boolean forceCreation = true;
67
68 public Object toBean(Content node, boolean recursive, final Content2BeanTransformer transformer) throws Content2BeanException{
69 return toBean(new ExtendingContentWrapper(node), recursive, transformer, transformer.newState());
70 }
71
72 protected Object toBean(Content node, boolean recursive, Content2BeanTransformer transformer, TransformationState state) throws Content2BeanException{
73
74 state.pushContent(node);
75
76 TypeDescriptor type = null;
77 try {
78 type = transformer.resolveType(state);
79 }
80 catch (Throwable e) {
81 if(isForceCreation()){
82 log.warn("can't resolve class for node " + node.getHandle(), e);
83 }
84 else{
85 throw new Content2BeanException("can't resolve class for node " + node.getHandle(), e);
86 }
87 }
88
89 Object bean = null;
90 if(type != null){
91 state.pushType(type);
92
93 transformer = resolveTransformer(type, transformer);
94
95 Map<String, Object> values = toMap(node, recursive, transformer, state);
96
97 try {
98 bean = transformer.newBeanInstance(state, values);
99 }
100 catch (Throwable e) {
101 if(isForceCreation()){
102 log.warn("Can't instantiate bean for " + node.getHandle(), e);
103 }
104 else{
105 throw new Content2BeanException("Can't instantiate bean for " + node.getHandle(), e);
106 }
107 }
108
109 if(bean != null){
110 state.pushBean(bean);
111
112 setProperties(values, transformer, state);
113
114 transformer.initBean(state, values);
115
116 state.popBean();
117 }
118 else{
119 if(forceCreation){
120 log.warn("can't instantiate bean of type " + type.getType().getName() + " for node " + node.getHandle());
121 }
122 else{
123 throw new Content2BeanException("can't instantiate bean of type " + type.getType().getName());
124 }
125 }
126
127 state.popType();
128 }
129 state.popContent();
130
131 return bean;
132 }
133
134 public Object setProperties(final Object bean, Content node, boolean recursive, Content2BeanTransformer transformer) throws Content2BeanException {
135
136 node = new ExtendingContentWrapper(node);
137
138 TransformationState state = transformer.newState();
139 state.pushBean(bean);
140 state.pushContent(node);
141
142 TypeDescriptor type = transformer.getTypeMapping().getTypeDescriptor(bean.getClass());
143
144 state.pushType(type);
145
146 transformer = resolveTransformer(type, transformer);
147
148 Map<String, Object> values = toMap(node, recursive, transformer, state);
149
150 setProperties(values, transformer, state);
151
152 transformer.initBean(state, values);
153
154 state.popBean();
155 state.popType();
156 state.popContent();
157
158 return bean;
159 }
160
161
162
163
164 protected Map<String, Object> toMap(Content node, boolean recursive, Content2BeanTransformer transformer, TransformationState state) throws Content2BeanException {
165 Map<String, Object> map = new LinkedHashMap<String, Object>();
166 for (NodeData nd : node.getNodeDataCollection()) {
167 Object val = NodeDataUtil.getValueObject(nd);
168 if (val != null) {
169 map.put(nd.getName(), val);
170 }
171 }
172
173 if(recursive){
174 final Collection<Content> children = transformer.getChildren(node);
175 for (Content childNode : children) {
176
177
178
179 Object childBean = toBean(childNode, true, transformer, state);
180
181 if(childBean != null){
182 String name = childNode.getName();
183 try {
184 if(childNode.getIndex() > 1){
185 name += childNode.getIndex();
186 }
187 }
188 catch (RepositoryException e) {
189 log.error("can't read index of the node [" + childNode + "]", e);
190 }
191 map.put(name, childBean);
192 }
193 }
194 }
195
196 return map;
197 }
198
199
200
201
202
203
204 protected void setProperties(Map<String, Object> values, final Content2BeanTransformer transformer, TransformationState state) throws Content2BeanException {
205 Object bean = state.getCurrentBean();
206 log.debug("will populate bean {} with the values {}", bean.getClass().getName(), values);
207
208 if(bean instanceof Map){
209 ((Map<String, Object>)bean).putAll(values);
210 }
211
212 if(bean instanceof Collection){
213 ((Collection<Object>)bean).addAll(values.values());
214 }
215
216 else{
217 TypeDescriptor beanTypeDescriptor = transformer.getTypeMapping().getTypeDescriptor(bean.getClass());
218 final Collection<PropertyTypeDescriptor> dscrs = beanTypeDescriptor.getPropertyDescriptors().values();
219
220 for (PropertyTypeDescriptor descriptor : dscrs) {
221 transformer.setProperty(state, descriptor, values);
222 }
223 }
224 }
225
226 protected Content2BeanTransformer resolveTransformer(TypeDescriptor type,
227 Content2BeanTransformer transformer) {
228 Content2BeanTransformer customTransformer = type.getTransformer();
229 if(customTransformer != null){
230 transformer = customTransformer;
231 }
232 return transformer;
233 }
234
235 public boolean isForceCreation() {
236 return this.forceCreation;
237 }
238
239
240 public void setForceCreation(boolean handleExceptions) {
241 this.forceCreation = handleExceptions;
242 }
243
244 }