1. Project Clover database Tue Dec 20 2016 21:24:09 CET
  2. Package org.xwiki.properties.internal

File DefaultBeanDescriptor.java

 

Coverage histogram

../../../../img/srcFileCovDistChart10.png
0% of files have more coverage

Code metrics

32
66
8
1
272
149
29
0.44
8.25
8
3.62

Classes

Class Line # Actions
DefaultBeanDescriptor 49 66 0% 29 6
0.943396294.3%
 

Contributing tests

This file is covered by 330 tests. .

Source view

1    /*
2    * See the NOTICE file distributed with this work for additional
3    * information regarding copyright ownership.
4    *
5    * This is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU Lesser General Public License as
7    * published by the Free Software Foundation; either version 2.1 of
8    * the License, or (at your option) any later version.
9    *
10    * This software is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13    * Lesser General Public License for more details.
14    *
15    * You should have received a copy of the GNU Lesser General Public
16    * License along with this software; if not, write to the Free
17    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19    */
20    package org.xwiki.properties.internal;
21   
22    import java.beans.BeanInfo;
23    import java.beans.Introspector;
24    import java.lang.annotation.Annotation;
25    import java.lang.reflect.Field;
26    import java.lang.reflect.Method;
27    import java.lang.reflect.Modifier;
28    import java.text.MessageFormat;
29    import java.util.Collection;
30    import java.util.LinkedHashMap;
31    import java.util.Map;
32   
33    import org.slf4j.Logger;
34    import org.slf4j.LoggerFactory;
35    import org.xwiki.properties.BeanDescriptor;
36    import org.xwiki.properties.PropertyDescriptor;
37    import org.xwiki.properties.annotation.PropertyDescription;
38    import org.xwiki.properties.annotation.PropertyHidden;
39    import org.xwiki.properties.annotation.PropertyId;
40    import org.xwiki.properties.annotation.PropertyMandatory;
41    import org.xwiki.properties.annotation.PropertyName;
42   
43    /**
44    * Default implementation for BeanDescriptor.
45    *
46    * @version $Id: c5672651e7e93af42b8fc379e2d9a3cbee127df0 $
47    * @since 2.0M2
48    */
 
49    public class DefaultBeanDescriptor implements BeanDescriptor
50    {
51    /**
52    * The logger to use to log.
53    */
54    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultBeanDescriptor.class);
55   
56    /**
57    * @see #getBeanClass()
58    */
59    private Class<?> beanClass;
60   
61    /**
62    * The properties of the bean.
63    */
64    private Map<String, PropertyDescriptor> parameterDescriptorMap = new LinkedHashMap<String, PropertyDescriptor>();
65   
66    /**
67    * @param beanClass the class of the JAVA bean.
68    */
 
69  940 toggle public DefaultBeanDescriptor(Class<?> beanClass)
70    {
71  940 this.beanClass = beanClass;
72   
73  940 extractBeanDescriptor();
74    }
75   
76    /**
77    * Extract informations form the bean.
78    */
 
79  940 toggle protected void extractBeanDescriptor()
80    {
81  940 Object defaultInstance = null;
82   
83  940 try {
84  940 defaultInstance = getBeanClass().newInstance();
85    } catch (Exception e) {
86  38 LOGGER.debug("Failed to create a new default instance for class " + this.beanClass
87    + ". The BeanDescriptor will not contains any default value information.", e);
88    }
89   
90  940 try {
91    // Get public fields
92  4186 for (Class<?> currentClass = this.beanClass; currentClass != null; currentClass =
93    currentClass.getSuperclass()) {
94  3246 Field[] fields = currentClass.getFields();
95  3246 for (Field field : fields) {
96  4771 if (!Modifier.isStatic(field.getModifiers())) {
97  196 extractPropertyDescriptor(field, defaultInstance);
98    }
99    }
100    }
101   
102    // Get getter/setter based properties
103  940 BeanInfo beanInfo = Introspector.getBeanInfo(this.beanClass);
104  940 java.beans.PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
105  940 if (propertyDescriptors != null) {
106  940 for (java.beans.PropertyDescriptor propertyDescriptor : propertyDescriptors) {
107  6449 if (propertyDescriptor != null) {
108  6449 extractPropertyDescriptor(propertyDescriptor, defaultInstance);
109    }
110    }
111    }
112    } catch (Exception e) {
113  0 LOGGER.error("Failed to load bean descriptor for class " + this.beanClass, e);
114    }
115    }
116   
117    /**
118    * Extract provided properties information and insert it in {@link #parameterDescriptorMap}.
119    *
120    * @param propertyDescriptor the JAVA bean property descriptor.
121    * @param defaultInstance the default instance of bean class.
122    */
 
123  6449 toggle protected void extractPropertyDescriptor(java.beans.PropertyDescriptor propertyDescriptor, Object defaultInstance)
124    {
125  6449 DefaultPropertyDescriptor desc = new DefaultPropertyDescriptor();
126   
127  6449 Method writeMethod = propertyDescriptor.getWriteMethod();
128   
129  6449 if (writeMethod != null) {
130  5201 Method readMethod = propertyDescriptor.getReadMethod();
131   
132    // is parameter hidden
133  5201 PropertyHidden parameterHidden = extractPropertyAnnotation(writeMethod, readMethod, PropertyHidden.class);
134   
135  5201 if (parameterHidden == null) {
136    // get parameter id
137  4914 PropertyId propertyId = extractPropertyAnnotation(writeMethod, readMethod, PropertyId.class);
138  4914 desc.setId(propertyId != null ? propertyId.value() : propertyDescriptor.getName());
139   
140    // set parameter type
141  4914 desc.setPropertyType(readMethod.getGenericReturnType());
142   
143    // get parameter display name
144  4914 PropertyName parameterName = extractPropertyAnnotation(writeMethod, readMethod, PropertyName.class);
145   
146  4914 desc.setName(parameterName != null ? parameterName.value() : desc.getId());
147   
148    // get parameter description
149  4914 PropertyDescription parameterDescription =
150    extractPropertyAnnotation(writeMethod, readMethod, PropertyDescription.class);
151   
152  4914 desc.setDescription(parameterDescription != null ? parameterDescription.value() : propertyDescriptor
153    .getShortDescription());
154   
155    // is parameter mandatory
156  4914 PropertyMandatory parameterMandatory =
157    extractPropertyAnnotation(writeMethod, readMethod, PropertyMandatory.class);
158   
159  4914 desc.setMandatory(parameterMandatory != null);
160   
161  4914 if (defaultInstance != null) {
162    // get default value
163  4846 try {
164  4846 desc.setDefaultValue(readMethod.invoke(defaultInstance));
165    } catch (Exception e) {
166  0 LOGGER.error(MessageFormat.format(
167    "Failed to get default property value from getter {0} in class {1}", readMethod.getName(),
168    this.beanClass), e);
169    }
170    }
171   
172  4914 desc.setWriteMethod(writeMethod);
173   
174  4914 desc.setReadMethod(readMethod);
175   
176  4914 this.parameterDescriptorMap.put(desc.getId(), desc);
177    }
178    }
179    }
180   
181    /**
182    * Extract provided properties informations and insert it in {@link #parameterDescriptorMap}.
183    *
184    * @param field the JAVA bean property descriptor.
185    * @param defaultInstance the default instance of bean class.
186    */
 
187  196 toggle protected void extractPropertyDescriptor(Field field, Object defaultInstance)
188    {
189  196 DefaultPropertyDescriptor desc = new DefaultPropertyDescriptor();
190   
191    // is parameter hidden
192  196 PropertyHidden parameterHidden = field.getAnnotation(PropertyHidden.class);
193   
194  196 if (parameterHidden == null) {
195    // get parameter id
196  196 PropertyId propertyId = field.getAnnotation(PropertyId.class);
197  196 desc.setId(propertyId != null ? propertyId.value() : field.getName());
198   
199    // set parameter type
200  196 desc.setPropertyType(field.getGenericType());
201   
202    // get parameter name
203  196 PropertyName parameterName = field.getAnnotation(PropertyName.class);
204   
205  196 desc.setName(parameterName != null ? parameterName.value() : desc.getId());
206   
207    // get parameter description
208  196 PropertyDescription parameterDescription = field.getAnnotation(PropertyDescription.class);
209   
210  196 desc.setDescription(parameterDescription != null ? parameterDescription.value() : desc.getId());
211   
212    // is parameter mandatory
213  196 PropertyMandatory parameterMandatory = field.getAnnotation(PropertyMandatory.class);
214   
215  196 desc.setMandatory(parameterMandatory != null);
216   
217  196 if (defaultInstance != null) {
218    // get default value
219  52 try {
220  52 desc.setDefaultValue(field.get(defaultInstance));
221    } catch (Exception e) {
222  0 LOGGER.error(
223    MessageFormat.format("Failed to get default property value from field {0} in class {1}",
224    field.getName(), this.beanClass), e);
225    }
226    }
227   
228  196 desc.setField(field);
229   
230  196 this.parameterDescriptorMap.put(desc.getId(), desc);
231    }
232    }
233   
234    /**
235    * Get the parameter annotation. Try first on the setter then on the getter if no annotation has been found.
236    *
237    * @param <T> the Class object corresponding to the annotation type.
238    * @param writeMethod the method that should be used to write the property value.
239    * @param readMethod the method that should be used to read the property value.
240    * @param annotationClass the Class object corresponding to the annotation type.
241    * @return this element's annotation for the specified annotation type if present on this element, else null.
242    */
 
243  24857 toggle protected <T extends Annotation> T extractPropertyAnnotation(Method writeMethod, Method readMethod,
244    Class<T> annotationClass)
245    {
246  24857 T parameterDescription = writeMethod.getAnnotation(annotationClass);
247   
248  24857 if (parameterDescription == null && readMethod != null) {
249  23652 parameterDescription = readMethod.getAnnotation(annotationClass);
250    }
251   
252  24857 return parameterDescription;
253    }
254   
 
255  18221 toggle @Override
256    public Class<?> getBeanClass()
257    {
258  18221 return this.beanClass;
259    }
260   
 
261  105474 toggle @Override
262    public Collection<PropertyDescriptor> getProperties()
263    {
264  105474 return this.parameterDescriptorMap.values();
265    }
266   
 
267  14 toggle @Override
268    public PropertyDescriptor getProperty(String propertyName)
269    {
270  14 return this.parameterDescriptorMap.get(propertyName);
271    }
272    }