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.core.doc;
17  
18  import java.io.Serializable;
19  import java.util.ArrayList;
20  import java.util.Arrays;
21  import java.util.Collections;
22  import java.util.Iterator;
23  import java.util.List;
24  
25  import net.jcip.annotations.GuardedBy;
26  
27  import org.apache.commons.lang.NullArgumentException;
28  
29  /**
30   * The test documentation of a unit under test.
31   *
32   * @author <a href="mailto:robert.reiner@smartics.de">Robert Reiner</a>
33   * @version $Revision:591 $
34   */
35  public final class UnitTestDoc implements Serializable, Comparable<UnitTestDoc>
36  {
37    // ********************************* Fields *********************************
38  
39    // --- constants ------------------------------------------------------------
40  
41    /**
42     * The class version identifier.
43     * <p>
44     * The value of this constant is {@value}.
45     * </p>
46     */
47    private static final long serialVersionUID = 1L;
48  
49    /**
50     * The guard name for synchronization.
51     */
52    private static final String GUARD = "scenarios";
53  
54    // --- members --------------------------------------------------------------
55  
56    /**
57     * The type of the unit-under-test.
58     *
59     * @serial
60     */
61    private final Type uutType;
62  
63    /**
64     * The test documentation of the individual tests of the unit.
65     *
66     * @serial
67     */
68    private final List<ScenarioTestDoc> scenarios;
69  
70    // ****************************** Initializer *******************************
71  
72    // ****************************** Constructors ******************************
73  
74    /**
75     * Convenience constructor with type name as a {@link String}.
76     *
77     * @param uutType the type of the unit-under-test.
78     */
79    public UnitTestDoc(final String uutType)
80    {
81      this(new Type(uutType), (List<ScenarioTestDoc>) null);
82    }
83  
84    /**
85     * Convenience constructor with only a type.
86     *
87     * @param uutType the type of the unit-under-test.
88     */
89    public UnitTestDoc(final Type uutType)
90    {
91      this(uutType, (List<ScenarioTestDoc>) null);
92    }
93  
94    /**
95     * Convenience constructor to allow adding a list of scenarios as varargs.
96     *
97     * @param uutType the type of the unit-under-test.
98     * @param scenarios the test documentation of the individual tests of the
99     *          unit.
100    * @throws IllegalArgumentException if <code>uutType</code> is blank or a
101    *           scenario is a null value.
102    */
103   public UnitTestDoc(final String uutType, final ScenarioTestDoc... scenarios)
104     throws IllegalArgumentException
105   {
106     this(uutType, createScenarioList(scenarios));
107   }
108 
109   /**
110    * Convenience constructor to allow adding a list of scenarios with an UUT
111    * type name as {@link String}.
112    *
113    * @param uutType the type of the unit-under-test.
114    * @param scenarios the test documentation of the individual tests of the
115    *          unit.
116    * @throws IllegalArgumentException if <code>uutType</code> is blank or
117    *           <code>method</code> is empty or contains only whitespaces.
118    */
119   public UnitTestDoc(final String uutType, final List<ScenarioTestDoc> scenarios)
120     throws IllegalArgumentException
121   {
122     this(new Type(uutType), scenarios);
123   }
124 
125   /**
126    * Convenience constructor to allow adding a list of scenarios as varargs.
127    *
128    * @param uutType the type of the unit-under-test.
129    * @param scenarios the test documentation of the individual tests of the
130    *          unit.
131    * @throws IllegalArgumentException if <code>uutType</code> is blank or a
132    *           scenario is a null value.
133    */
134   public UnitTestDoc(final Type uutType, final ScenarioTestDoc... scenarios)
135     throws IllegalArgumentException
136   {
137     this(uutType, createScenarioList(scenarios));
138   }
139 
140   /**
141    * Default constructor to allow adding a list of scenarios.
142    *
143    * @param uutType the type of the unit-under-test.
144    * @param scenarios the test documentation of the individual tests of the
145    *          unit.
146    * @throws IllegalArgumentException if <code>uutType</code> is blank or
147    *           <code>method</code> is empty or contains only whitespaces.
148    */
149   public UnitTestDoc(final Type uutType, final List<ScenarioTestDoc> scenarios)
150     throws IllegalArgumentException
151   {
152     checkArguments(uutType);
153 
154     this.uutType = uutType;
155     this.scenarios =
156         scenarios != null ? new ArrayList<ScenarioTestDoc>(scenarios)
157             : new ArrayList<ScenarioTestDoc>();
158   }
159 
160   // ******************************** Methods *******************************
161 
162   // --- init ---------------------------------------------------------------
163 
164   private void checkArguments(final Type uutType)
165     throws IllegalArgumentException
166   {
167     if (null == uutType)
168     {
169       throw new IllegalArgumentException(
170           "The UUT type is required, but was 'null'.");
171     }
172   }
173 
174   private static List<ScenarioTestDoc> createScenarioList(
175       final ScenarioTestDoc... scenarios) throws IllegalArgumentException
176   {
177     assert scenarios != null : "Scenarios must not be 'null'.";
178 
179     for (final ScenarioTestDoc scenario : scenarios)
180     {
181       if (scenario == null)
182       {
183         throw new IllegalArgumentException("Scenarios must not be 'null'.");
184       }
185     }
186     return Arrays.asList(scenarios);
187   }
188 
189   // --- get&set ------------------------------------------------------------
190 
191   /**
192    * Returns the type of the unit-under-test.
193    *
194    * @return the type of the unit-under-test.
195    */
196   public Type getUutType()
197   {
198     return uutType;
199   }
200 
201   /**
202    * Returns the test documentation of the individual tests of the unit.
203    *
204    * @return the test documentation of the individual tests of the unit.
205    */
206   @GuardedBy(GUARD)
207   public List<ScenarioTestDoc> getScenarios()
208   {
209     synchronized (scenarios)
210     {
211       return new ArrayList<ScenarioTestDoc>(scenarios);
212     }
213   }
214 
215   @GuardedBy(GUARD)
216   public List<ScenarioTestDoc> getSortedScenarios()
217   {
218     final List<ScenarioTestDoc> defaultSort = new ArrayList<ScenarioTestDoc>();
219     final List<ScenarioTestDoc> sortedList =
220         new ArrayList<ScenarioTestDoc>(scenarios.size());
221 
222     synchronized (scenarios)
223     {
224       for (final ScenarioTestDoc scenario : scenarios)
225       {
226         if (scenario.getSortKey().isDefault())
227         {
228           defaultSort.add(scenario);
229         }
230         else
231         {
232           sortedList.add(scenario);
233         }
234       }
235     }
236 
237     Collections.sort(sortedList);
238     sortedList.addAll(defaultSort);
239     return sortedList;
240   }
241 
242   /**
243    * Returns the number of registered scenarios.
244    *
245    * @return the number of registered scenarios.
246    */
247   @GuardedBy(GUARD)
248   public int getScenarioCount()
249   {
250     synchronized (scenarios)
251     {
252       return scenarios.size();
253     }
254   }
255 
256   // --- business -------------------------------------------------------------
257 
258   /**
259    * Adds the test documentation to the documentation of the unit-under-test.
260    *
261    * @param scenario the documentation to be added.
262    */
263   @GuardedBy(GUARD)
264   public void addScenario(final ScenarioTestDoc scenario)
265   {
266     synchronized (scenarios)
267     {
268       if (!this.scenarios.contains(scenario))
269       {
270         this.scenarios.add(scenario);
271       }
272     }
273   }
274 
275   /**
276    * Adds all scenarios of the given test doc to this instance.
277    *
278    * @param testDoc the test doc whose UUT type is identical to this'.
279    * @throws IllegalArgumentException if the UUT type of this instance is not
280    *           identical to the passed one.
281    */
282   @GuardedBy(GUARD)
283   public void addScenarios(final UnitTestDoc testDoc)
284     throws IllegalArgumentException
285   {
286     if (this.uutType.equals(testDoc.getUutType()))
287     {
288       for (final ScenarioTestDoc scenario : testDoc.getScenarios())
289       {
290         addScenario(scenario);
291       }
292     }
293     else
294     {
295       throw new IllegalArgumentException(
296           "The names of the UUTs differ. This is '" + uutType
297               + "' the passed value is '" + testDoc.getUutType() + "'.");
298     }
299   }
300 
301   /**
302    * Removes all scenarios that are associated with the given test case.
303    *
304    * @param testCaseType the type of test case whose scenarios are to be
305    *          removed.
306    * @throws NullArgumentException if <code>testCaseType</code> is
307    *           <code>null</code>.
308    */
309   @GuardedBy(GUARD)
310   public void removeScenarios(final Type testCaseType)
311     throws NullArgumentException
312   {
313     if (testCaseType == null)
314     {
315       throw new NullArgumentException("testCaseType");
316     }
317 
318     synchronized (scenarios)
319     {
320       for (final Iterator<ScenarioTestDoc> i = scenarios.iterator(); i
321           .hasNext();)
322       {
323         final ScenarioTestDoc scenario = i.next();
324         final Type scenarioTestCaseType = scenario.getTestCaseType();
325         if (testCaseType.equals(scenarioTestCaseType))
326         {
327           i.remove();
328         }
329       }
330     }
331   }
332 
333   // --- object basics --------------------------------------------------------
334 
335   /**
336    * {@inheritDoc}
337    *
338    * @see java.lang.Comparable#compareTo(java.lang.Object)
339    */
340   @Override
341   public int compareTo(final UnitTestDoc o)
342   {
343     return this.uutType.compareTo(o.uutType);
344   }
345 
346   /**
347    * Returns the hash code of the object.
348    *
349    * @return the hash code.
350    */
351   @Override
352   public int hashCode()
353   {
354     return uutType.hashCode();
355   }
356 
357   /**
358    * Returns <code>true</code> if the given object is semantically equal to the
359    * given object, <code>false</code> otherwise.
360    *
361    * @param object the instance to compare to.
362    * @return <code>true</code> if the given object is semantically equal to the
363    *         given object, <code>false</code> otherwise.
364    */
365   @Override
366   @GuardedBy(GUARD)
367   public boolean equals(final Object object)
368   {
369     if (this == object)
370     {
371       return true;
372     }
373     else if (object == null || getClass() != object.getClass())
374     {
375       return false;
376     }
377 
378     final UnitTestDoc other = (UnitTestDoc) object;
379 
380     synchronized (scenarios)
381     {
382       return (this.uutType.equals(other.uutType) && this.scenarios
383           .equals(other.scenarios));
384     }
385 
386   }
387 
388   /**
389    * Returns the string representation of the object.
390    *
391    * @return the string representation of the object.
392    */
393   @Override
394   @GuardedBy(GUARD)
395   public String toString()
396   {
397     final StringBuilder buffer = new StringBuilder();
398 
399     buffer.append("The scenarios of UUT '").append(this.uutType).append('\'')
400         .append(" are:\n");
401     synchronized (scenarios)
402     {
403       for (final ScenarioTestDoc scenario : scenarios)
404       {
405         buffer.append(scenario).append('\n');
406       }
407     }
408     return buffer.toString();
409   }
410 }