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 }