View Javadoc

1   /*
2    * Copyright 2010-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.testdoc.collect.extractor;
17  
18  import java.util.Map;
19  
20  import javax.lang.model.element.AnnotationMirror;
21  import javax.lang.model.element.AnnotationValue;
22  import javax.lang.model.element.Element;
23  import javax.lang.model.element.ExecutableElement;
24  
25  import org.apache.commons.lang.StringUtils;
26  
27  import de.smartics.testdoc.annotations.Uut;
28  
29  /**
30   * Extracts {@link Uut} annotation information.
31   *
32   * @author <a href="mailto:robert.reiner@smartics.de">Robert Reiner</a>
33   * @version $Revision:591 $
34   */
35  class TestDocAnnotationExtractor
36  {
37    // ********************************* Fields *********************************
38  
39    // --- constants ------------------------------------------------------------
40  
41    // --- members --------------------------------------------------------------
42  
43    // ****************************** Initializer *******************************
44  
45    // ****************************** Constructors ******************************
46  
47    // ****************************** Inner Classes *****************************
48  
49    /**
50     * The unit under test (UUT) information from the annotation.
51     */
52    static final class UutInfo
53    {
54      /**
55       * The type of the UUT.
56       */
57      private String type;
58  
59      /**
60       * The method of the UUT.
61       */
62      private String method;
63  
64      /**
65       * Returns the type of the UUT.
66       *
67       * @return the type of the UUT.
68       */
69      public String getType()
70      {
71        return type;
72      }
73  
74      /**
75       * Returns the method of the UUT.
76       *
77       * @return the method of the UUT.
78       */
79      public String getMethod()
80      {
81        return method;
82      }
83  
84      /**
85       * Checks if the UUT annotation provides a type property.
86       *
87       * @return <code>true</code> if a type property is provided,
88       *         <code>false</code> if the type property is <code>null</code>.
89       */
90      public boolean hasType()
91      {
92        return type != null;
93      }
94  
95      /**
96       * Checks if the UUT annotation provides a non-blank method name.
97       *
98       * @return <code>true</code> if a non-blank method name is provided,
99       *         <code>false</code> if the method name is blank.
100      */
101     public boolean hasMethod()
102     {
103       return StringUtils.isNotBlank(method);
104     }
105   }
106 
107   // ********************************* Methods ********************************
108 
109   // --- init -----------------------------------------------------------------
110 
111   // --- get&set --------------------------------------------------------------
112 
113   // --- business -------------------------------------------------------------
114 
115   /**
116    * Reads the UUT information from the annotation.
117    *
118    * @param testMethod the test method to check for {@link Uut} annotations.
119    * @return the information of the annotation. The value is never
120    *         <code>null</code>, but the info instance may provide no
121    *         information.
122    * @throws IllegalArgumentException if the extractor does not support all
123    *           annotation properties provided.
124    */
125   UutInfo read(final Element testCaseType) throws IllegalArgumentException
126   {
127     final UutInfo info = new UutInfo();
128     for (final AnnotationMirror annotation : testCaseType
129         .getAnnotationMirrors())
130     {
131       if (isAnnotation(Uut.class, annotation))
132       {
133         return read(info, annotation);
134       }
135     }
136 
137     return info;
138   }
139 
140   private boolean isAnnotation(final Class<?> type,
141       final AnnotationMirror annotation)
142   {
143     return type.getName().equals(annotation.getAnnotationType().toString());
144   }
145 
146   private static UutInfo read(final UutInfo info,
147       final AnnotationMirror annotation) throws IllegalArgumentException
148   {
149     final Map<? extends ExecutableElement, ? extends AnnotationValue> map =
150         annotation.getElementValues();
151     for (final Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : map
152         .entrySet())
153     {
154       addInfo(info, entry);
155     }
156     return info;
157   }
158 
159   private static void addInfo(
160       final UutInfo info,
161       final Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry)
162     throws IllegalArgumentException
163   {
164     final String key = entry.getKey().toString();
165     if (isType(key))
166     {
167       final String value = entry.getValue().toString();
168       final String typeName = typeNameFix(value);
169       if (!Object.class.getName().equals(typeName))
170       {
171         info.type = typeName;
172       }
173     }
174     else if (isMethod(key))
175     {
176       final Object value = entry.getValue().getValue();
177       if (value instanceof String)
178       {
179         info.method = (String) value;
180       }
181     }
182     else
183     {
184       throw new IllegalArgumentException(
185           "Cannot support UUT annotation field '" + key + "'.");
186     }
187   }
188 
189   private static boolean isType(final String key)
190   {
191     return key != null && key.contains("type()");
192   }
193 
194   private static boolean isMethod(final String key)
195   {
196     return key != null && key.contains("method()");
197   }
198 
199   /**
200    * Dependent on the implementation the value contains the <code>.class</code>
201    * (Sun) suffix, or not (eclipse).
202    */
203   static String typeNameFix(final String typeNameString)
204   {
205     if (typeNameString.endsWith(".class"))
206     {
207       return typeNameString.substring(0, typeNameString.length() - 6);
208     }
209     else
210     {
211       return typeNameString;
212     }
213   }
214 
215   // --- object basics --------------------------------------------------------
216 
217 }