1 package org.weda.property.impl;
2
3 import java.beans.IntrospectionException;
4 import java.beans.Introspector;
5 import java.lang.annotation.Annotation;
6 import java.lang.reflect.Method;
7 import java.util.ArrayList;
8 import java.util.Collections;
9 import java.util.HashMap;
10 import java.util.List;
11 import java.util.Map;
12 import org.weda.converter.ValueTypeConverter;
13 import org.weda.enhance.InjectHivemindObject;
14 import org.weda.property.Constraint;
15 import org.weda.property.ConstraintException;
16 import org.weda.property.ConstraintsRegistry;
17 import org.weda.property.PropertyDescriptorException;
18 import org.weda.property.annotations.Constraints;
19 import org.weda.property.annotations.Description;
20 import org.weda.property.ObjectDescriptorRegistry;
21 import org.weda.property.PropertyDescriptor;
22 import org.weda.property.annotations.ConstraintId;
23
24 /**Цель: возвращать название свойства заданного класса
25 * в результате возвращается значение атрибута name аннотации description или
26 * название свойства если нет аннотации
27 *
28 * @author tim
29 */
30
31 public class ObjectDescriptor {
32 private Class objectClass;
33
34 @InjectHivemindObject private ObjectDescriptorRegistry objDescRegistry;
35 @InjectHivemindObject private ConstraintsRegistry constraintsRegistry;
36
37 private Map<String, PropertyDescriptorImpl> properties =
38 new HashMap<String, PropertyDescriptorImpl>();
39 private Map<String, PropertyDescriptor> additionalPropertiesInfo =
40 new HashMap<String, PropertyDescriptor>();
41 private Map<String, java.beans.PropertyDescriptor> beanDescriptorCache;
42
43 public void init() throws ObjectDescriptorException {
44 try {
45 for (PropertyDescriptor descriptor
46 : additionalPropertiesInfo.values())
47 {
48 PropertyDescriptorImpl desc =
49 (PropertyDescriptorImpl)descriptor;
50 desc.setObjectClass(objectClass);
51 desc.init();
52 }
53 } catch (PropertyDescriptorException ex) {
54 throw new ObjectDescriptorException(
55 String.format(
56 "Can't initialize object descriptor for target class (%s)"
57 , objectClass.getName()));
58 }
59 }
60
61 public Class getObjectClass() {
62 return objectClass;
63 }
64
65 public void setObjectClass(Class value) {
66 this.objectClass = value;
67 }
68
69 public void addAdditionalPropertyInfo(PropertyDescriptor property){
70 additionalPropertiesInfo.put(property.getName(), property);
71 }
72
73 public PropertyDescriptor getPropertyDescriptor(String propertyName)
74 throws ObjectDescriptorException
75 {
76 PropertyDescriptorImpl propertyDescriptor =
77 properties.get(propertyName);
78 if (propertyDescriptor==null){
79 try{
80 java.beans.PropertyDescriptor d =
81 getJavaBeansPropertyDescriptor(propertyName);
82 propertyDescriptor = new PropertyDescriptorImpl();
83 propertyDescriptor.setName(propertyName);
84 propertyDescriptor.setObjectClass(getObjectClass());
85 propertyDescriptor.setPropertyClass(d.getPropertyType());
86 processAnnotaions(propertyDescriptor, d);
87 if (d.getPropertyType().isEnum())
88 addEnumConstraint(propertyDescriptor);
89 if (additionalPropertiesInfo.containsKey(propertyName)){
90 PropertyDescriptor pinfo =
91 additionalPropertiesInfo.get(propertyName);
92 propertyDescriptor.setDisplayName(pinfo.getDisplayName());
93 }
94 propertyDescriptor.init();
95 properties.put(propertyName, propertyDescriptor);
96 }catch(Exception e){
97 throw new ObjectDescriptorException(
98 String.format(
99 "Can't get property descriptor for property (%s) " +
100 "of class (%s)"
101 , propertyName, objectClass.getName())
102 , e);
103 }
104 }
105 return propertyDescriptor;
106 }
107
108 private void addEnumConstraint(PropertyDescriptorImpl desc)
109 throws ConstraintException
110 {
111 Object[] constants = desc.getPropertyClass().getEnumConstants();
112 StaticSetConstraint constraint = new StaticSetConstraint();
113 constraint.setValuesAliased(true);
114 for (Object obj: constants){
115 Enum cons = (Enum)obj;
116 constraint.addSetValue(new SetValueImpl(cons, cons.name()));
117 }
118 constraint.init();
119 desc.addConstraint(constraint);
120 }
121
122 private void processAnnotaions(
123 PropertyDescriptorImpl desc
124 , java.beans.PropertyDescriptor javaDesc)
125 throws Exception
126 {
127
128 Description descriptionAnn = null;
129 Constraints constraintsAnn = null;
130 Method[] methods =
131 new Method[]{
132 javaDesc.getReadMethod(), javaDesc.getWriteMethod()};
133 for (Method method: methods){
134 if (method!=null){
135 if (method.isAnnotationPresent(Description.class))
136 descriptionAnn = method.getAnnotation(Description.class);
137 if (method.isAnnotationPresent(Constraints.class))
138 constraintsAnn = method.getAnnotation(Constraints.class);
139 }
140 }
141 processDescriptionAnnotaion(desc, descriptionAnn);
142 processConstraintsAnnotations(desc, constraintsAnn);
143 }
144
145 private void processDescriptionAnnotaion(
146 PropertyDescriptorImpl propertyDescriptor
147 , Description descriptionAnn)
148 {
149 if (descriptionAnn!=null){
150 propertyDescriptor.setDisplayName(
151 returnNullIfEmpty(descriptionAnn.displayName()));
152 propertyDescriptor.setPattern(
153 returnNullIfEmpty(descriptionAnn.pattern()));
154 propertyDescriptor.setMimeType(
155 returnNullIfEmpty(descriptionAnn.mimeType()));
156 }
157 }
158
159 private void processConstraintsAnnotations(
160 PropertyDescriptorImpl desc
161 , Constraints constraintsAnn)
162 throws Exception
163 {
164 if (constraintsAnn != null){
165 ConstraintId[] ids = constraintsAnn.value();
166 if (ids != null)
167 for (ConstraintId id: ids)
168 desc.addConstraint(
169 constraintsRegistry.getConstraint(id.value()));
170 }
171 }
172
173
174 /**Метод возвращает имена свойств которые можно читать и устананавливать.
175 */
176 public List<String> getReadWriteProperties()
177 throws ObjectDescriptorException
178 {
179 try{
180 List<String> names = new ArrayList<String>();
181 if (beanDescriptorCache==null)
182 cacheJavaBeansPropertyDescriptors();
183 for (java.beans.PropertyDescriptor desc
184 : beanDescriptorCache.values())
185 {
186 if (desc.getWriteMethod()!=null && desc.getReadMethod()!=null)
187 names.add(desc.getName());
188 }
189 return names;
190 }catch(Exception e){
191 throw new ObjectDescriptorException(
192 String.format(
193 "Can't create list of writable properties for class (%s)"
194 , objectClass.getName()));
195 }
196 }
197
198 public void setRegistry(ObjectDescriptorRegistry registry) {
199
200 }
201
202 private java.beans.PropertyDescriptor getJavaBeansPropertyDescriptor(
203 String propertyName)
204 throws ObjectDescriptorException
205 {
206 try{
207 if (beanDescriptorCache==null)
208 cacheJavaBeansPropertyDescriptors();
209 java.beans.PropertyDescriptor desc =
210 beanDescriptorCache.get(propertyName);
211 if (desc==null)
212 throw new ObjectDescriptorException(
213 String.format(
214 "Property name (%s) does not exist in class (%s)"
215 , propertyName, objectClass.getName()));
216 return desc;
217 }catch(IntrospectionException e){
218 throw new ObjectDescriptorException(
219 String.format(
220 "Can't extract java beans property descriptors. " +
221 "Object class (%d), property name(%s)"
222 , objectClass.getName(), propertyName)
223 , e);
224 }
225 }
226
227 private void cacheJavaBeansPropertyDescriptors()
228 throws IntrospectionException
229 {
230 java.beans.PropertyDescriptor[] descs =
231 Introspector.getBeanInfo(objectClass).getPropertyDescriptors();
232 beanDescriptorCache=
233 new HashMap<String, java.beans.PropertyDescriptor>();
234 for (java.beans.PropertyDescriptor desc: descs)
235 beanDescriptorCache.put(desc.getName(), desc);
236 }
237
238 private String returnNullIfEmpty(String value){
239 if (value==null || value.length()==0)
240 return null;
241 else
242 return value;
243 }
244
245 public void setConverter(ValueTypeConverter converter) {
246
247 }
248
249 }