View Javadoc

1   /***
2    * Copyright (c) 2003, 2004, Chess iT
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without modification,
6    * are permitted provided that the following conditions are met:
7    * 
8    * - Redistributions of source code must retain the above copyright notice, this
9    *   list of conditions and the following disclaimer.
10   *
11   * - Redistributions in binary form must reproduce the above copyright notice,
12   *   this list of conditions and the following disclaimer in the documentation
13   *   and/or other materials provided with the distribution.
14   *
15   * - Neither the name of Chess iT, nor the names of its contributors may be used 
16   *   to endorse or promote products derived from this software without specific
17   *   prior written permission.
18   *
19   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
20   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
21   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
22   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
23   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
24   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
25   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
26   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
27   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
28   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
29   * POSSIBILITY OF SUCH DAMAGE.
30   * 
31   */
32  package nl.chess.it.util.config;
33  
34  import java.lang.reflect.InvocationTargetException;
35  
36  import java.util.ArrayList;
37  import java.util.Collections;
38  import java.util.HashSet;
39  import java.util.List;
40  import java.util.Set;
41  
42  /***
43   * This is the result of a check on the validity of the properties in a
44   * {@link nl.chess.it.util.config.Config}object. It's basically a wrapper around a list of Strings,
45   * with some helper methods like {@link #addError(String, Throwable)}. It can also store a second
46   * list, with unused properties.
47   * 
48   * @author Guus Bosman (Chess iT)
49   * @version $Revision: 1.1.1.1 $
50   */
51  public class ConfigValidationResult {
52  
53      /***
54       * Describes the source of the configuration (such as a filename).
55       */
56      private String sourceDescription;
57  
58      /***
59       * List of Strings that describe the errors that occurred.
60       */
61      private final List errors = new ArrayList();
62  
63      /***
64       * List of Strings that describe the properties that are available but not used by the Config.
65       */
66      private Set unusedProperties = new HashSet();
67  
68      /***
69       * Set of {PropertyDisplayItem PropertyDisplayItems} that shows which properties are in use.
70       */
71      private Set usedProperties = new HashSet();
72  
73      /***
74       * Makes a nice description of an error that happens when calling a method and adds this
75       * description to the list with errors.
76       * 
77       * @param methodName Methodname that was called.
78       * @param e Throwable that was thrown.
79       */
80      public void addError(String methodName, Throwable e) {
81          if ((e instanceof InvocationTargetException) && (e.getCause() != null)) {
82              e = e.getCause();
83          }
84  
85          if (e instanceof MissingPropertyException) {
86              MissingPropertyException mpe = ((MissingPropertyException) e);
87              String missingPropertyDescription = "Missing property " + mpe.getPropertyname();
88  
89              if (mpe.getExpectedType() != null) {
90                  missingPropertyDescription += " which must be " + getAorAn(mpe.getExpectedType()) + " "
91                          + mpe.getExpectedType() + " value";
92              }
93  
94              missingPropertyDescription += ".";
95              errors.add(missingPropertyDescription);
96  
97              return;
98          }
99  
100         if (e instanceof InvalidPropertyException) {
101             InvalidPropertyException ipe = ((InvalidPropertyException) e);
102             errors.add("Property " + ipe.getPropertyname() + " had value '" + ipe.getValue() + "' which is not "
103                     + getAorAn(ipe.getExpectedtype()) + " " + ipe.getExpectedtype() + " value.");
104 
105             return;
106         }
107 
108         errors.add("Couldn't call " + methodName + ": " + e);
109     }
110 
111     private String getAorAn(String word) {
112         if (word == null) return "";
113         if (word.startsWith("i") || word.startsWith("e") || word.startsWith("o") || word.startsWith("a")) {
114             return "an";
115         } else {
116             return "a";
117         }
118     }
119 
120     /***
121      * Whether or not any exceptions occured when validating the configuration.
122      * 
123      * @return <code>true</code> if something serious went wrong during validation of the getXxx()
124      *         methods, <code>false</code> otherwise.
125      */
126     public boolean thereAreErrors() {
127         return (!errors.isEmpty());
128     }
129 
130     /***
131      * Indicates whether or not there are unused properties.
132      * 
133      * @return <code>true</code> if there are any properties in the Properties object that have
134      *         not been used while validation the various getXxx() methods, <code>false</code>
135      *         otherwise.
136      */
137     public boolean thereAreUnusedProperties() {
138         return (!unusedProperties.isEmpty());
139     }
140 
141     /***
142      * Returns a List with Strings that indicate any errors that might have occured.
143      * 
144      * @return List. Never <code>null</code>, unmodifiable.
145      */
146     public List getErrors() {
147         return Collections.unmodifiableList(errors);
148     }
149 
150     /***
151      * Returns a Set with the unused properties. These are properties in the Properties object that
152      * have not been used while validating the various getXxx() methods, and thus seem to have no
153      * function in the original property-file or Properties object.
154      * 
155      * @return Unmodiafable set. Never <code>null</code>. Elements are of type String.
156      */
157     public Set getUnusedProperties() {
158         return Collections.unmodifiableSet(unusedProperties);
159     }
160 
161     public String toString() {
162         String toReturn = "";
163         if (thereAreErrors()) {
164             toReturn += "Configuration errors: " + errors + ".";
165         } else {
166             toReturn += "No configuration errors. Unused properties: " + unusedProperties.size()
167                     + ", used properties: " + usedProperties.size() + ".";
168         }
169         if (sourceDescription != null) {
170             toReturn += " Source description: " + sourceDescription + ".";
171         }
172         return toReturn;
173     }
174 
175     /***
176      * Sets the set with unusedProperties. It is highly unlikely that an application would want to
177      * use this method; it is only used by Config itself.
178      * 
179      * @param set Set with unusedProperties. Cannot be <code>null</code>. Elements must be of
180      *            type String.
181      */
182     public void setUnusedProperties(Set set) {
183         if (set == null) {
184             throw new NullPointerException("set cannot be null here.");
185         }
186         unusedProperties = set;
187     }
188 
189     /***
190      * Allows replacement of the set with usedProperties. There is no reason any application should
191      * want to overwrite those, so this method should probably never be used. In Config it is not
192      * used either (instead, {#getUsedProperties()} is used to get access to the set)
193      * 
194      * @param usedProperties. Cannot be <code>null</code>. Item must be of type
195      *            {PropertyDisplayItem}.
196      */
197     public void setUsedProperties(Set usedProperties) {
198         if (usedProperties == null) {
199             throw new NullPointerException("usedProperties cannot be null here.");
200         }
201         this.usedProperties = usedProperties;
202     }
203 
204     /***
205      * Returns a set of {PropertyDisplayItem PropertyDisplayItems} that shows which properties are
206      * in use.
207      * 
208      * @return Set. Never <code>null</code>.
209      */
210     public Set getUsedProperties() {
211         return usedProperties;
212     }
213 
214     /***
215      * Describes the location where the properties come from. Human readable String.
216      * 
217      * @return String. Might be <code>null</code>, if it is unknown.
218      */
219     public String getSourceDescription() {
220         return sourceDescription;
221     }
222 
223     /***
224      * Set the location where the properties come from. Human readable String.
225      * 
226      * @param sourceDescription Can be <code>null</code>.
227      */
228     public void setSourceDescription(String sourceDescription) {
229         this.sourceDescription = sourceDescription;
230     }
231 
232 }