1 /* 2 * Redistribution and use of this software and associated documentation 3 * ("Software"), with or without modification, are permitted provided 4 * that the following conditions are met: 5 * 6 * 1. Redistributions of source code must retain copyright 7 * statements and notices. Redistributions must also contain a 8 * copy of this document. 9 * 10 * 2. Redistributions in binary form must reproduce the 11 * above copyright notice, this list of conditions and the 12 * following disclaimer in the documentation and/or other 13 * materials provided with the distribution. 14 * 15 * 3. The name "Exolab" must not be used to endorse or promote 16 * products derived from this Software without prior written 17 * permission of Intalio, Inc. For written permission, 18 * please contact info@exolab.org. 19 * 20 * 4. Products derived from this Software may not be called "Exolab" 21 * nor may "Exolab" appear in their names without prior written 22 * permission of Intalio, Inc. Exolab is a registered 23 * trademark of Intalio, Inc. 24 * 25 * 5. Due credit should be given to the Exolab Project 26 * (http://www.exolab.org/). 27 * 28 * THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS 29 * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT 30 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 31 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 32 * INTALIO, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 33 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 34 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 35 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 37 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 39 * OF THE POSSIBILITY OF SUCH DAMAGE. 40 * 41 * Copyright 1999-2003 (C) Intalio, Inc. All Rights Reserved. 42 * 43 * $Id$ 44 */ 45 package org.exolab.castor.xml.validators; 46 47 import org.exolab.castor.xml.TypeValidator; 48 import org.exolab.castor.xml.ValidationContext; 49 import org.exolab.castor.xml.ValidationException; 50 import org.exolab.castor.xml.XMLConstants; 51 52 /** 53 * The String Validation class. 54 * 55 * @author <a href="mailto:kvisco@intalio.com">Keith Visco</a> 56 * @version $Revision$ $Date: 2004-12-11 02:13:52 -0700 (Sat, 11 Dec 2004) $ 57 */ 58 public class StringValidator extends PatternValidator implements TypeValidator { 59 60 /** If true, this field must be present. */ 61 private boolean _required = false; 62 /** Whitespace handing for this String. (Really belongs elsewhere.) */ 63 private String _whiteSpace = XMLConstants.WHITESPACE_PRESERVE; 64 /** Exact length required of the string. 0 means no length requirement. */ 65 private int _length = 0; 66 /** Minimum length required of the string. 0 means no minimum length requirement. */ 67 private int _minLength = 0; 68 /** Maximum length required of the string. -1 means no maximum length requirement. */ 69 private int _maxLength = -1; 70 /** Fixed value of this string, null if none is set. */ 71 private String _fixed = null; 72 73 /** 74 * Creates a new StringValidator with no restrictions. 75 */ 76 public StringValidator() { 77 super(); 78 } // -- StringValidator 79 80 /** 81 * Clears the fixed value for this ShortValidator. 82 */ 83 public void clearFixed() { 84 _fixed = null; 85 } // -- clearFixed 86 87 /** 88 * Sets the fixed value in which all valid Strings must match. 89 * 90 * @param fixedValue 91 * the fixed value that all Strings must match 92 */ 93 public void setFixed(final String fixedValue) { 94 this._fixed = fixedValue; 95 } // -- setFixedValue 96 97 /** 98 * Only used for backward compatibility for object model generated with an 99 * old version of Castor. 100 * 101 * @param fixedValue 102 * the fixed value that all Strings must match 103 * 104 * @deprecated since 0.9.4_beta 105 */ 106 public void setFixedValue(final String fixedValue) { 107 setFixed(fixedValue); 108 } 109 110 /** 111 * Sets the maximum string length for String validation. To pass validation, 112 * a String must be shorter than or equal to this length. To remove this 113 * facet, set a negative value. 114 * 115 * @param maxLength 116 * the maximum length for valid Strings 117 */ 118 public void setMaxLength(final int maxLength) { 119 this._maxLength = maxLength; 120 } // -- setMaxLength 121 122 /** 123 * Sets the minimum string length for String validation. To pass validation, 124 * a String must be longer than or equal to this length. To remove this 125 * facet, set a negative value. 126 * 127 * @param minLength 128 * the minimum length for valid Strings 129 */ 130 public void setMinLength(final int minLength) { 131 this._minLength = minLength; 132 } // -- setMinLength 133 134 /** 135 * Sets the required string length for String validation. To pass 136 * validation, a String must be exactly this many characters long. To remove 137 * this facet, set a negative value. 138 * 139 * @param length 140 * the required length for valid Strings 141 */ 142 public void setLength(final int length) { 143 this._length = length; 144 setMaxLength(length); 145 setMinLength(length); 146 } // -- setLength 147 148 /** 149 * Sets whether or not a String is required (non null). 150 * 151 * @param required 152 * the flag indicating whether this string must be non-null. 153 */ 154 public void setRequired(final boolean required) { 155 this._required = required; 156 } // -- setRequired 157 158 /** 159 * Sets the whiteSpace facet of the validator. 160 * <p> 161 * The value of the whiteSpace facet must be one of the following: 162 * <ul> 163 * <li>preserve</li> 164 * <li>replace</li> 165 * <li>collapse</li> 166 * </ul> 167 * any other value will generate a Warning and set the whiteSpace to 168 * preserve. 169 * <p> 170 * FIXME: This is not really a function of validation, but of XML 171 * processing before the string is returned from the XML processor. This 172 * should be moved to the FieldHandler, or somewhere else, but not here. 173 * 174 * @param value 175 * the whiteSpace value 176 */ 177 public void setWhiteSpace(final String value) { 178 if (value.equals(XMLConstants.WHITESPACE_PRESERVE)) { 179 this._whiteSpace = value; 180 } else if (value.equals(XMLConstants.WHITESPACE_REPLACE)) { 181 this._whiteSpace = value; 182 } else if (value.equals(XMLConstants.WHITESPACE_COLLAPSE)) { 183 this._whiteSpace = value; 184 } else { 185 System.out.println("Warning: '" + value 186 + "' is a bad entry for the whiteSpace value"); 187 this._whiteSpace = XMLConstants.WHITESPACE_PRESERVE; 188 } 189 } // -- setWhiteSpace 190 191 /** 192 * Normalizes the given string according to the whiteSpace facet used. 193 * <p> 194 * FIXME: THIS METHOD SHOULD NOT BE HERE..SHOULD BE MOVED TO A FieldHandler 195 * or to the Unmarshaller...but not here!!! (kvisco 20030125) 196 * @param value 197 * the String to normalize 198 * @return the normalized string. 199 */ 200 public String normalize(final String value) { 201 if (value == null) { 202 return null; 203 } 204 205 if (value.length() == 0) { 206 return value; 207 } 208 209 char[] chars = value.toCharArray(); 210 int length = chars.length; 211 212 for (int i = 0; i < length; i++) { 213 switch (chars[i]) { 214 case '\t': 215 case '\r': 216 case '\n': 217 chars[i] = ' '; 218 break; 219 default: 220 continue; 221 } 222 } 223 224 if (_whiteSpace.equals(XMLConstants.WHITESPACE_COLLAPSE)) { 225 // -- heavy method to keep compatibility 226 // -- with JDK 1.1 (can't use Vector.toArray) 227 char[] temp = new char[chars.length]; 228 int tempCount = 0; 229 int i = 0; 230 while (i < length - 1) { 231 if (chars[i] == ' ') { 232 // --put the first space 233 temp[tempCount] = chars[i]; 234 tempCount++; 235 // --skip the others 236 i++; 237 while (i < length - 1 && chars[i] == ' ') { 238 i++; 239 } 240 continue; 241 } 242 temp[tempCount] = chars[i]; 243 tempCount++; 244 i++; 245 } 246 // --we are at the end 247 if (chars[i] != ' ') { 248 temp[tempCount] = chars[i]; 249 } 250 251 length = ++tempCount; 252 chars = temp; 253 } 254 255 return new String(chars, 0, length); 256 } 257 258 /** 259 * Validates the given Object. 260 * 261 * @param value 262 * the string to validate 263 * @param context 264 * the ValidationContext 265 * @throws ValidationException if the object fails validation. 266 */ 267 public void validate(final String value, final ValidationContext context) 268 throws ValidationException { 269 if (value == null) { 270 if (_required && !isNillable()) { 271 String err = "this is a required field and cannot be null."; 272 throw new ValidationException(err); 273 } 274 return; 275 } 276 277 if (_fixed != null && !_fixed.equals(value)) { 278 String err = "strings of this type must be equal to the fixed value of " + _fixed; 279 throw new ValidationException(err); 280 } 281 282 int len = value.length(); 283 284 if (_length > 0 && len != _length) { 285 String err = "Strings of this type must have a length of " + _length + " characters"; 286 throw new ValidationException(err); 287 } 288 289 if (_minLength > 0 && len < _minLength) { 290 String err = "Strings of this type must have a minimum length of " + _minLength 291 + " characters"; 292 throw new ValidationException(err); 293 } 294 295 if (_maxLength >= 0 && len > _maxLength) { 296 String err = "Strings of this type must have a maximum length of " + _maxLength 297 + " characters"; 298 throw new ValidationException(err); 299 } 300 301 if (hasPattern()) { 302 super.validate(value, context); 303 } 304 305 if (!this._whiteSpace.equals(XMLConstants.WHITESPACE_PRESERVE)) { 306 normalize(value); 307 } 308 } // -- validate 309 310 /** 311 * Validates the given Object. 312 * 313 * @param object 314 * the Object to validate 315 * @throws ValidationException if the object fails validation. 316 */ 317 public void validate(final Object object) throws ValidationException { 318 validate(object, (ValidationContext) null); 319 } // -- validate 320 321 /** 322 * Validates the given Object. 323 * 324 * @param object 325 * the Object to validate 326 * @param context 327 * the ValidationContext 328 * @throws ValidationException if the object fails validation. 329 */ 330 public void validate(final Object object, final ValidationContext context) 331 throws ValidationException { 332 if (object == null) { 333 if (_required) { 334 String err = "this is a required field and cannot be null."; 335 throw new ValidationException(err); 336 } 337 return; 338 } 339 340 validate(object.toString(), context); 341 } //-- validate 342 343 } //-- StringValidator