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 public class Content2BeanProcessorImpl implements Content2BeanProcessor {
63 private static final Logger log = LoggerFactory.getLogger(Content2BeanProcessorImpl.class);
64
65 private boolean forceCreation = true;
66
67 public Object toBean(Content node, boolean recursive, final Content2BeanTransformer transformer) throws Content2BeanException{
68 return toBean(new ExtendingContentWrapper(node), recursive, transformer, transformer.newState());
69 }
70
71 protected Object toBean(Content node, boolean recursive, Content2BeanTransformer transformer, TransformationState state) throws Content2BeanException{
72
73 state.pushContent(node);
74
75 TypeDescriptor type = null;
76 try {
77 type = transformer.resolveType(state);
78 }
79 catch (Throwable e) {
80 if(isForceCreation()){
81 log.warn("can't resolve class for node " + node.getHandle(), e);
82 }
83 else{
84 throw new Content2BeanException("can't resolve class for node " + node.getHandle(), e);
85 }
86 }
87
88 Object bean = null;
89 if(type != null){
90 state.pushType(type);
91
92 transformer = resolveTransformer(type, transformer);
93
94 Map<String, Object> values = toMap(node, recursive, transformer, state);
95
96 try {
97 bean = transformer.newBeanInstance(state, values);
98 }
99 catch (Throwable e) {
100 if(isForceCreation()){
101 log.warn("Can't instantiate bean for " + node.getHandle(), e);
102 }
103 else{
104 throw new Content2BeanException("Can't instantiate bean for " + node.getHandle(), e);
105 }
106 }
107
108 if(bean != null){
109 state.pushBean(bean);
110
111 setProperties(values, transformer, state);
112
113 transformer.initBean(state, values);
114
115 state.popBean();
116 }
117 else{
118 if(forceCreation){
119 log.warn("can't instantiate bean of type " + type.getType().getName() + " for node " + node.getHandle());
120 }
121 else{
122 throw new Content2BeanException("can't instantiate bean of type " + type.getType().getName());
123 }
124 }
125
126 state.popType();
127 }
128 state.popContent();
129
130 return bean;
131 }
132
133 public Object setProperties(final Object bean, Content node, boolean recursive, Content2BeanTransformer transformer) throws Content2BeanException {
134
135 node = new ExtendingContentWrapper(node);
136
137 TransformationState state = transformer.newState();
138 state.pushBean(bean);
139 state.pushContent(node);
140
141 TypeDescriptor type = transformer.getTypeMapping().getTypeDescriptor(bean.getClass());
142
143 state.pushType(type);
144
145 transformer = resolveTransformer(type, transformer);
146
147 Map<String, Object> values = toMap(node, recursive, transformer, state);
148
149 setProperties(values, transformer, state);
150
151 transformer.initBean(state, values);
152
153 state.popBean();
154 state.popType();
155 state.popContent();
156
157 return bean;
158 }
159
160
161
162
163 protected Map<String, Object> toMap(Content node, boolean recursive, Content2BeanTransformer transformer, TransformationState state) throws Content2BeanException {
164 Map<String, Object> map = new LinkedHashMap<String, Object>();
165 for (NodeData nd : node.getNodeDataCollection()) {
166 Object val = NodeDataUtil.getValueObject(nd);
167 if (val != null) {
168 map.put(nd.getName(), val);
169 }
170 }
171
172 if(recursive){
173 final Collection<Content> children = transformer.getChildren(node);
174 for (Content childNode : children) {
175
176
177
178 Object childBean = toBean(childNode, true, transformer, state);
179
180 if(childBean != null){
181 String name = childNode.getName();
182 try {
183 if(childNode.getIndex() > 1){
184 name += childNode.getIndex();
185 }
186 }
187 catch (RepositoryException e) {
188 log.error("can't read index of the node [" + childNode + "]", e);
189 }
190 map.put(name, childBean);
191 }
192 }
193 }
194
195 return map;
196 }
197
198
199
200
201
202
203 protected void setProperties(Map<String, Object> values, final Content2BeanTransformer transformer, TransformationState state) throws Content2BeanException {
204 Object bean = state.getCurrentBean();
205 log.debug("will populate bean {} with the values {}", bean.getClass().getName(), values);
206
207 if(bean instanceof Map){
208 ((Map<String, Object>)bean).putAll(values);
209 }
210
211 if(bean instanceof Collection){
212 ((Collection<Object>)bean).addAll(values.values());
213 }
214
215 else{
216 TypeDescriptor beanTypeDescriptor = transformer.getTypeMapping().getTypeDescriptor(bean.getClass());
217 final Collection<PropertyTypeDescriptor> dscrs = beanTypeDescriptor.getPropertyDescriptors().values();
218
219 for (PropertyTypeDescriptor descriptor : dscrs) {
220 transformer.setProperty(state, descriptor, values);
221 }
222 }
223 }
224
225 protected Content2BeanTransformer resolveTransformer(TypeDescriptor type,
226 Content2BeanTransformer transformer) {
227 Content2BeanTransformer customTransformer = type.getTransformer();
228 if(customTransformer != null){
229 transformer = customTransformer;
230 }
231 return transformer;
232 }
233
234 public boolean isForceCreation() {
235 return this.forceCreation;
236 }
237
238
239 public void setForceCreation(boolean handleExceptions) {
240 this.forceCreation = handleExceptions;
241 }
242
243 }