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 }