View Javadoc

1   /*
2    * Copyright 2012-2013 smartics, Kronseder & Reiner GmbH
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package de.smartics.properties.spi.core.metadata;
17  
18  import java.lang.reflect.Method;
19  
20  import org.apache.commons.lang.StringUtils;
21  
22  import de.smartics.projectdoc.annotations.Document;
23  import de.smartics.properties.api.core.annotations.PropertyKeyName;
24  import de.smartics.properties.api.core.annotations.PropertySet;
25  import de.smartics.properties.spi.core.metadata.projectdoc.ProjectdocAnnotationCollector.Defaults;
26  import de.smartics.util.lang.Arg;
27  
28  /**
29   * Implementation to provide defaults from the project set annotation.
30   */
31  public final class PropertyMetaDataDefaults implements Defaults
32  {
33    // ******************************** Fields ********************************
34  
35    // --- constants ----------------------------------------------------------
36  
37    // --- members ------------------------------------------------------------
38  
39    /**
40     * The default title.
41     */
42    private final String title;
43  
44    /**
45     * The default name.
46     */
47    private final String name;
48  
49    /**
50     * The default space.
51     */
52    private final String space;
53  
54    // ***************************** Initializer ******************************
55  
56    // ***************************** Constructors *****************************
57  
58    /**
59     * Default constructor using the declaring type. The default lack the method
60     * name specifics.
61     *
62     * @param type the type to extract default values for title, name and space.
63     * @throws NullPointerException if {@code type} is <code>null</code>.
64     */
65    public PropertyMetaDataDefaults(final Class<?> type)
66      throws NullPointerException
67    {
68      this.space = createSpace(type);
69      final PropertySet annotation = type.getAnnotation(PropertySet.class);
70      this.title = annotation != null ? annotation.value() : type.getSimpleName();
71      this.name = this.title;
72    }
73  
74    /**
75     * Default constructor using the declaring and method type.
76     *
77     * @param type the type to extract default values for title, name and space.
78     * @param propertyMethod the method to check for a property set annotation
79     *          that overrides the one of the type.
80     * @throws NullPointerException if {@code type} is <code>null</code>.
81     */
82    public PropertyMetaDataDefaults(final Class<?> type,
83        final Method propertyMethod) throws NullPointerException
84    {
85      this.space = createSpace(type);
86      this.title = determineTitle(type, propertyMethod);
87      this.name = determineName(type, propertyMethod);
88    }
89  
90    /**
91     * Default constructor using the method and adding the name of the method.
92     *
93     * @param propertyMethod the method to derive default values.
94     */
95    public PropertyMetaDataDefaults(final Method propertyMethod)
96    {
97      final Class<?> type = propertyMethod.getDeclaringClass();
98      this.space = createSpace(type);
99      this.title = determinePropertyTitle(type, propertyMethod);
100     this.name = determinePropertyName(type, propertyMethod);
101   }
102 
103   private PropertyMetaDataDefaults(final String space, final String name,
104       final String title) throws NullPointerException
105   {
106     this.space = Arg.checkNotBlank("space", space);
107     this.name = name;
108     this.title = title;
109   }
110 
111   // ***************************** Inner Classes ****************************
112 
113   // ******************************** Methods *******************************
114 
115   // --- init ---------------------------------------------------------------
116 
117   private static String createSpace(final Class<?> type)
118   {
119     return "property:" + type.getName();
120   }
121 
122   private static String determineTitle(final Class<?> type,
123       final Method propertyMethod)
124   {
125     final Document document =
126         determineDocumentTitleAnnotation(type, propertyMethod);
127     final String title;
128     if (document != null && document.title() != null)
129     {
130       title = document.title();
131     }
132     else
133     {
134       final PropertySet annotation =
135           determinePropertySetAnnotation(type, propertyMethod);
136       title = annotation != null ? annotation.value() : type.getSimpleName();
137     }
138     return title;
139   }
140 
141   private static String determinePropertyTitle(final Class<?> type,
142       final Method propertyMethod)
143   {
144     final Document document =
145         determineDocumentTitleAnnotation(type, propertyMethod);
146     final String prefix;
147     if (document != null && document.title() != null)
148     {
149       prefix = document.title();
150     }
151     else
152     {
153       final PropertySet annotation =
154           determinePropertySetAnnotation(type, propertyMethod);
155       prefix = annotation != null ? annotation.value() : null;
156     }
157 
158     final String property;
159     final PropertyKeyName keyAnnotation =
160         propertyMethod.getAnnotation(PropertyKeyName.class);
161     if (keyAnnotation != null && keyAnnotation.value() != null)
162     {
163       property = keyAnnotation.value();
164     }
165     else
166     {
167       property = propertyMethod.getName();
168     }
169 
170     final String title = prefix != null ? prefix + '.' + property : property;
171     return title;
172   }
173 
174   private static String determineName(final Class<?> type,
175       final Method propertyMethod)
176   {
177     final Document document =
178         determineDocumentNameAnnotation(type, propertyMethod);
179     final String title;
180     if (document != null && document.name() != null)
181     {
182       title = document.title();
183     }
184     else
185     {
186       final PropertySet annotation =
187           determinePropertySetAnnotation(type, propertyMethod);
188       title = annotation != null ? annotation.value() : type.getSimpleName();
189     }
190     return title;
191   }
192 
193   private static String determinePropertyName(final Class<?> type,
194       final Method propertyMethod)
195   {
196     final Document document =
197         determineDocumentNameAnnotation(type, propertyMethod);
198     final String prefix;
199     if (document != null && document.name() != null)
200     {
201       prefix = document.name();
202     }
203     else
204     {
205       final PropertySet annotation =
206           determinePropertySetAnnotation(type, propertyMethod);
207       prefix = annotation != null ? annotation.value() : null;
208     }
209 
210     final String property = propertyMethod.getName();
211 
212     final String name =
213         StringUtils.isNotBlank(prefix) ? prefix + '.' + property : property;
214     return name;
215   }
216 
217   private static PropertySet determinePropertySetAnnotation(
218       final Class<?> type, final Method propertyMethod)
219   {
220     PropertySet annotation = propertyMethod.getAnnotation(PropertySet.class);
221     if (annotation == null)
222     {
223       annotation = type.getAnnotation(PropertySet.class);
224     }
225     return annotation;
226   }
227 
228   private static Document determineDocumentNameAnnotation(final Class<?> type,
229       final Method propertyMethod)
230   {
231     Document annotation = propertyMethod.getAnnotation(Document.class);
232     if (annotation == null || StringUtils.isBlank(annotation.name()))
233     {
234       annotation = type.getAnnotation(Document.class);
235     }
236     return annotation;
237   }
238 
239   private static Document determineDocumentTitleAnnotation(final Class<?> type,
240       final Method propertyMethod)
241   {
242     Document annotation = propertyMethod.getAnnotation(Document.class);
243     if (annotation == null || StringUtils.isBlank(annotation.title()))
244     {
245       annotation = type.getAnnotation(Document.class);
246     }
247     return annotation;
248   }
249 
250   // --- factory ------------------------------------------------------------
251 
252   /**
253    * Retruns the property set metadata defaults.
254    *
255    * @param propertyMethod the method of the property whose set defaults are
256    *          requested.
257    * @return the defaults for the set referenced by the property identified by
258    *         the given method.
259    */
260   public static PropertyMetaDataDefaults propertySet(final Method propertyMethod)
261   {
262     final Class<?> type = propertyMethod.getDeclaringClass();
263     final String space = createSpace(type);
264 
265     final PropertySet annotation = getPropertySetAnnotation(propertyMethod);
266     final String title =
267         annotation != null ? x(type, annotation) : type.getSimpleName();
268     final String name = title;
269 
270     final PropertyMetaDataDefaults defaults =
271         new PropertyMetaDataDefaults(space, name, title);
272     return defaults;
273   }
274 
275   private static String x(final Class<?> type, final PropertySet annotation)
276   {
277     String name = annotation.value();
278     if (name == null)
279     {
280       name = type.getSimpleName();
281     }
282     else if (" ".equals(name))
283     {
284       name = "";
285     }
286     return name;
287   }
288 
289   private static PropertySet getPropertySetAnnotation(
290       final Method propertyMethod)
291   {
292     PropertySet annotation = propertyMethod.getAnnotation(PropertySet.class);
293     if (annotation == null)
294     {
295       final Class<?> type = propertyMethod.getDeclaringClass();
296       annotation = type.getAnnotation(PropertySet.class);
297     }
298     return annotation;
299   }
300 
301   // --- get&set ------------------------------------------------------------
302 
303   @Override
304   public String getTitle()
305   {
306     return title;
307   }
308 
309   @Override
310   public String getName()
311   {
312     return name;
313   }
314 
315   @Override
316   public String getSpace()
317   {
318     return space;
319   }
320 
321   // --- business -----------------------------------------------------------
322 
323   // --- object basics ------------------------------------------------------
324 
325   /**
326    * Returns the string representation of the object.
327    *
328    * @return the string representation of the object.
329    */
330   @Override
331   public String toString()
332   {
333     return space + '/' + title + '/' + name;
334   }
335 }