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.content2bean.Content2BeanTransformer;
37 import info.magnolia.content2bean.PropertyTypeDescriptor;
38 import info.magnolia.content2bean.TypeDescriptor;
39 import info.magnolia.content2bean.TypeMapping;
40
41 import java.beans.PropertyDescriptor;
42 import java.lang.reflect.Method;
43 import java.util.Collection;
44 import java.util.HashMap;
45 import java.util.Map;
46
47 import info.magnolia.objectfactory.ClassFactory;
48 import info.magnolia.objectfactory.Classes;
49 import org.apache.commons.beanutils.PropertyUtils;
50 import org.apache.commons.lang.StringUtils;
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
53
54
55
56
57
58
59
60 public class TypeMappingImpl implements TypeMapping {
61
62
63
64
65 private static Logger log = LoggerFactory.getLogger(TypeMappingImpl.class);
66
67
68
69
70 protected static Map<String, PropertyTypeDescriptor> propertyTypes = new HashMap<String, PropertyTypeDescriptor>();
71
72
73
74
75 protected static Map<Class<?>, TypeDescriptor> types = new HashMap<Class<?>, TypeDescriptor>();
76
77
78
79
80 public Method getAddMethod(Class<?> type, String name, int numberOfParameters) {
81 name = StringUtils.capitalize(name);
82 Method method = getExactMethod(type, "add" + name, numberOfParameters);
83 if (method == null) {
84 method = getExactMethod(type, "add" + StringUtils.removeEnd(name, "s"), numberOfParameters);
85 }
86
87 if (method == null) {
88 method = getExactMethod(type, "add" + StringUtils.removeEnd(name, "es"), numberOfParameters);
89 }
90
91 if (method == null) {
92 method = getExactMethod(type, "add" + StringUtils.removeEnd(name, "ren"), numberOfParameters);
93 }
94
95 if (method == null) {
96 method = getExactMethod(type, "add" + StringUtils.removeEnd(name, "ies") + "y", numberOfParameters);
97 }
98 return method;
99 }
100
101
102
103
104
105 public PropertyTypeDescriptor getPropertyTypeDescriptor(Class<?> beanClass, String propName) {
106 PropertyTypeDescriptor dscr;
107 String key = beanClass.getName() + "." + propName;
108
109 dscr = propertyTypes.get(key);
110 if(dscr != null){
111 return dscr;
112 }
113 TypeMapping defaultMapping = TypeMapping.Factory.getDefaultMapping();
114
115 if (this != defaultMapping) {
116 dscr = defaultMapping.getPropertyTypeDescriptor(beanClass, propName);
117 if (dscr.getType() != null) {
118 return dscr;
119 }
120 }
121
122 dscr = new PropertyTypeDescriptor();
123 dscr.setName(propName);
124
125 PropertyDescriptor[] descriptors = PropertyUtils.getPropertyDescriptors(beanClass);
126 for (int i = 0; i < descriptors.length; i++) {
127 PropertyDescriptor descriptor = descriptors[i];
128 if (descriptor.getName().equals(propName)) {
129 Class<?> propertytype = descriptor.getPropertyType();
130 if (propertytype != null) {
131 dscr.setType(getTypeDescriptor(propertytype));
132 }
133 break;
134 }
135 }
136
137 if(dscr.getType() != null){
138 if(dscr.isMap() || dscr.isCollection()){
139 int numberOfParameters = dscr.isMap() ? 2 : 1;
140 Method method = getAddMethod(beanClass, propName, numberOfParameters);
141 if(method != null){
142 dscr.setAddMethod(method);
143 if(dscr.isMap()){
144 dscr.setCollectionKeyType(getTypeDescriptor(method.getParameterTypes()[0]));
145 dscr.setCollectionEntryType(getTypeDescriptor(method.getParameterTypes()[1]));
146 }
147 else{
148 dscr.setCollectionEntryType(getTypeDescriptor(method.getParameterTypes()[0]));
149 }
150 }
151 }
152 }
153
154
155 propertyTypes.put(key, dscr);
156
157 return dscr;
158 }
159
160 public void addPropertyTypeDescriptor(Class<?> beanClass, String propName, PropertyTypeDescriptor dscr) {
161 propertyTypes.put(beanClass.getName() + "." + propName, dscr);
162 }
163
164 public void addTypeDescriptor(Class<?> beanClass, TypeDescriptor dscr) {
165 types.put(beanClass, dscr);
166 }
167
168 public TypeDescriptor getTypeDescriptor(Class<?> beanClass) {
169 TypeDescriptor dscr = types.get(beanClass);
170 if(dscr != null){
171 return dscr;
172 }
173 dscr = new TypeDescriptor();
174 dscr.setType(beanClass);
175 dscr.setMap(Map.class.isAssignableFrom(beanClass));
176 dscr.setCollection(beanClass.isArray() || Collection.class.isAssignableFrom(beanClass));
177 types.put(beanClass, dscr);
178
179 if (!beanClass.isArray() && !beanClass.isPrimitive()) {
180 try {
181 final ClassFactory classFactory = Classes.getClassFactory();
182 final Class<Content2BeanTransformer> transformerClass = classFactory.forName(beanClass.getName() + "Transformer");
183
184 if(Content2BeanTransformer.class.isAssignableFrom(transformerClass)){
185 try {
186 final Content2BeanTransformer transformer = classFactory.newInstance(transformerClass);
187 dscr.setTransformer(transformer);
188 log.debug("Found a custom transformer [{" + transformerClass + "}] for [{" + beanClass + "}]");
189 } catch (Exception e) {
190 log.error("Can't instantiate custom transformer [{" + transformerClass + "}] for [{" + beanClass + "}]", e);
191 }
192 }
193 } catch (Exception e) {
194
195 log.debug("No custom transformer class {}Transformer class found", beanClass.getName());
196 }
197 }
198
199 return dscr;
200 }
201
202
203
204
205
206 protected Method getExactMethod(Class<?> type, String name, int numberOfParameters) {
207 Method[] methods = type.getMethods();
208 for (int i = 0; i < methods.length; i++) {
209 Method method = methods[i];
210 if (method.getName().equals(name)) {
211 if(method.getParameterTypes().length == numberOfParameters){
212 return method;
213 }
214 }
215 }
216 return null;
217 }
218
219 }