1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package de.smartics.properties.spi.core.metadata;
17
18 import java.lang.reflect.Method;
19 import java.util.HashMap;
20 import java.util.Locale;
21 import java.util.Map;
22
23 import javax.annotation.concurrent.ThreadSafe;
24
25 import org.apache.commons.lang.StringUtils;
26 import org.apache.commons.lang.builder.ToStringBuilder;
27
28 import de.smartics.projectdoc.annotations.Document;
29 import de.smartics.properties.api.core.domain.DocumentName;
30 import de.smartics.properties.api.core.domain.PropertiesContext;
31 import de.smartics.properties.api.core.domain.PropertyDescriptor;
32 import de.smartics.properties.api.core.domain.PropertyKey;
33 import de.smartics.properties.api.core.domain.PropertyProjectdoc;
34 import de.smartics.properties.api.core.domain.PropertySetProjectdoc;
35 import de.smartics.properties.spi.core.metadata.projectdoc.AnnotationHelper;
36 import de.smartics.properties.spi.core.metadata.projectdoc.ProjectdocAnnotationCollector;
37 import de.smartics.properties.spi.core.metadata.projectdoc.ProjectdocAnnotationCollector.Defaults;
38 import de.smartics.properties.spi.core.metadata.projectdoc.PropertyProjectdocParser;
39 import de.smartics.properties.spi.core.metadata.projectdoc.PropertySetProjectdocParser;
40 import de.smartics.properties.spi.core.util.SerializableMethod;
41 import de.smartics.util.lang.Arg;
42
43
44
45
46 @ThreadSafe
47 public final class MetaInfDocumentMetaDataProxy implements
48 DocumentMetaDataProxy
49 {
50
51
52
53
54
55
56
57 private static final long serialVersionUID = 1L;
58
59
60
61
62
63
64
65
66
67
68 private final DocumentName documentName;
69
70
71
72
73
74
75
76 private final PropertiesContext context;
77
78
79
80
81
82
83
84 private final SerializableMethod propertyMethod;
85
86
87
88
89
90
91 private final Map<Locale, PropertyProjectdoc> metaData =
92 new HashMap<Locale, PropertyProjectdoc>();
93
94
95
96
97
98
99 private final Map<Locale, PropertySetProjectdoc> propertySetMetaData =
100 new HashMap<Locale, PropertySetProjectdoc>();
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117 public MetaInfDocumentMetaDataProxy(final PropertyKey key,
118 final PropertiesContext context, final Method propertyMethod)
119 throws NullPointerException
120 {
121 Arg.checkNotNull("key", key);
122
123 this.context = context;
124 this.propertyMethod =
125 new SerializableMethod(Arg.checkNotNull("propertyMethod",
126 propertyMethod));
127 this.documentName = calculateDocumentName(key, propertyMethod);
128 }
129
130
131
132
133
134
135
136
137
138 private static DocumentName calculateDocumentName(final PropertyKey key,
139 final Method propertyMethod)
140 {
141 final Document annotation = propertyMethod.getAnnotation(Document.class);
142 String name = propertyMethod.getName();
143 if (annotation != null)
144 {
145 final String value = annotation.name();
146 if (value != null)
147 {
148 final AnnotationHelper helper = new AnnotationHelper();
149 final String annName = helper.normalizeString(value);
150 if (StringUtils.isNotBlank(annName))
151 {
152 name = annName;
153 }
154 }
155 }
156
157 final String setName = key.getPropertySet();
158 final String fqn = setName != null ? setName + '.' + name : name;
159 final DocumentName documentName = new DocumentName(fqn);
160 return documentName;
161 }
162
163
164
165
166
167
168
169
170
171 @Override
172 public DocumentName getDocumentName()
173 {
174 return documentName;
175 }
176
177
178
179 @Override
180 public PropertySetProjectdoc getProjectdocPropertySet(
181 final PropertyDescriptor descriptor, final Locale locale)
182 {
183 synchronized (propertySetMetaData)
184 {
185 PropertySetProjectdoc metaData = propertySetMetaData.get(locale);
186
187 if (metaData == null)
188 {
189 final Method propertyMethod = this.propertyMethod.getMethod();
190
191 ensureMethodPresent(propertyMethod);
192
193 if (context != null)
194 {
195 final Defaults defaults =
196 PropertyMetaDataDefaults.propertySet(propertyMethod);
197 final PropertySetProjectdocParser parser =
198 new PropertySetProjectdocParser(context, defaults);
199 metaData = parser.parse(descriptor, locale);
200 }
201
202 if (metaData == null)
203 {
204 metaData = new PropertySetProjectdoc();
205 }
206
207 this.propertySetMetaData.put(locale, metaData);
208 }
209
210 return metaData;
211 }
212 }
213
214 @Override
215 public PropertyProjectdoc getProjectdocProperty(
216 final PropertyDescriptor descriptor, final Locale locale)
217 {
218 synchronized (metaData)
219 {
220 PropertyProjectdoc metaData = this.metaData.get(locale);
221
222 if (metaData == null)
223 {
224 final Method propertyMethod = this.propertyMethod.getMethod();
225
226 ensureMethodPresent(propertyMethod);
227
228 if (context != null)
229 {
230 final Defaults defaults =
231 new PropertyMetaDataDefaults(propertyMethod);
232 final PropertyProjectdocParser parser =
233 new PropertyProjectdocParser(context, defaults);
234 metaData = parser.parse(descriptor, locale);
235 }
236
237 if (metaData == null)
238 {
239 final Class<?> declaringType = propertyMethod.getDeclaringClass();
240 final Defaults parentDefaults =
241 new PropertyMetaDataDefaults(declaringType, propertyMethod);
242 final Defaults defaults =
243 new PropertyMetaDataDefaults(propertyMethod);
244 final ProjectdocAnnotationCollector collector =
245 new ProjectdocAnnotationCollector(declaringType, parentDefaults,
246 defaults);
247
248 metaData =
249 PropertyProjectdoc.upgrade(collector
250 .createMetaDataFromAnnotations(propertyMethod));
251 }
252
253 if (metaData != null)
254 {
255 this.metaData.put(locale, metaData);
256 }
257 }
258
259 return metaData;
260 }
261 }
262
263 private void ensureMethodPresent(final Method propertyMethod)
264 {
265 if (propertyMethod == null)
266 {
267 throw new IllegalStateException(
268 "Cannot find documentation for method value 'null'.");
269 }
270 }
271
272
273
274
275
276
277
278
279 @Override
280 public String toString()
281 {
282 return ToStringBuilder.reflectionToString(this);
283 }
284 }