1 /* SimpleType.java -- 2 Copyright (C) 2006 Free Software Foundation, Inc. 3 4 This file is part of GNU Classpath. 5 6 GNU Classpath is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2, or (at your option) 9 any later version. 10 11 GNU Classpath is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GNU Classpath; see the file COPYING. If not, write to the 18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19 02110-1301 USA. 20 21 Linking this library statically or dynamically with other modules is 22 making a combined work based on this library. Thus, the terms and 23 conditions of the GNU General Public License cover the whole 24 combination. 25 26 As a special exception, the copyright holders of this library give you 27 permission to link this library with independent modules to produce an 28 executable, regardless of the license terms of these independent 29 modules, and to copy and distribute the resulting executable under 30 terms of your choice, provided that you also meet, for each linked 31 independent module, the terms and conditions of the license of that 32 module. An independent module is a module which is not derived from 33 or based on this library. If you modify this library, you may extend 34 this exception to your version of the library, but you are not 35 obligated to do so. If you do not wish to do so, delete this 36 exception statement from your version. */ 37 38 package gnu.xml.validation.datatype; 39 40 import java.util.Iterator; 41 import java.util.Set; 42 import java.util.regex.Matcher; 43 import javax.xml.namespace.QName; 44 import org.relaxng.datatype.Datatype; 45 import org.relaxng.datatype.DatatypeException; 46 import org.relaxng.datatype.DatatypeStreamingValidator; 47 import org.relaxng.datatype.ValidationContext; 48 49 /** 50 * An XML Schema simple type. 51 * 52 * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a> 53 */ 54 public class SimpleType 55 extends Type 56 implements Datatype 57 { 58 59 /** 60 * The variety of the <code>anySimpleType</code> datatype. 61 */ 62 public static final int ANY = 0; 63 64 /** 65 * The atomic variety. 66 */ 67 public static final int ATOMIC = 1; 68 69 /** 70 * The list variety. 71 */ 72 public static final int LIST = 2; 73 74 /** 75 * The union variety. 76 */ 77 public static final int UNION = 3; 78 79 public static final int ID_TYPE_NULL = 0; 80 public static final int ID_TYPE_ID = 1; 81 public static final int ID_TYPE_IDREF = 2; 82 public static final int ID_TYPE_IDREFS = 3; 83 84 /** 85 * The variety of this simple type. 86 */ 87 public final int variety; 88 89 /** 90 * The facets of this simple type. 91 */ 92 public Set facets; 93 94 /** 95 * The fundamental facets of this simple type. 96 */ 97 public int fundamentalFacets; 98 99 /** 100 * If this datatype has been derived by restriction, then the component 101 * from which it was derived. 102 */ 103 public final SimpleType baseType; 104 105 /** 106 * Optional annotation. 107 */ 108 public final Annotation annotation; 109 SimpleType(QName name, int variety, Set facets, int fundamentalFacets, SimpleType baseType, Annotation annotation)110 public SimpleType(QName name, int variety, Set facets, 111 int fundamentalFacets, SimpleType baseType, 112 Annotation annotation) 113 { 114 super(name); 115 this.variety = variety; 116 this.facets = facets; 117 this.fundamentalFacets = fundamentalFacets; 118 this.baseType = baseType; 119 this.annotation = annotation; 120 } 121 122 /** 123 * Indicates whether this type permits the specified value. 124 */ isValid(String value, ValidationContext context)125 public boolean isValid(String value, ValidationContext context) 126 { 127 try 128 { 129 checkValid(value, context); 130 return true; 131 } 132 catch (DatatypeException e) 133 { 134 return false; 135 } 136 } 137 checkValid(String value, ValidationContext context)138 public void checkValid(String value, ValidationContext context) 139 throws DatatypeException 140 { 141 if (facets != null && !facets.isEmpty()) 142 { 143 Object parsedValue = createValue(value, context); 144 for (Iterator i = facets.iterator(); i.hasNext(); ) 145 { 146 Facet facet = (Facet) i.next(); 147 switch (facet.type) 148 { 149 case Facet.LENGTH: 150 LengthFacet lf = (LengthFacet) facet; 151 if (value.length() != lf.value) 152 throw new DatatypeException("invalid length"); 153 break; 154 case Facet.MIN_LENGTH: 155 MinLengthFacet nlf = (MinLengthFacet) facet; 156 if (value.length() < nlf.value) 157 throw new DatatypeException("invalid minimum length"); 158 break; 159 case Facet.MAX_LENGTH: 160 MaxLengthFacet xlf = (MaxLengthFacet) facet; 161 if (value.length() > xlf.value) 162 throw new DatatypeException("invalid maximum length"); 163 break; 164 case Facet.PATTERN: 165 PatternFacet pf = (PatternFacet) facet; 166 Matcher matcher = pf.value.matcher(value); 167 if (!matcher.find()) 168 throw new DatatypeException("invalid match for pattern"); 169 break; 170 case Facet.ENUMERATION: 171 // TODO 172 break; 173 case Facet.WHITESPACE: 174 // TODO 175 break; 176 case Facet.MAX_INCLUSIVE: 177 MaxInclusiveFacet xif = (MaxInclusiveFacet) facet; 178 if (!xif.matches(parsedValue)) 179 throw new DatatypeException("beyond upper bound"); 180 break; 181 case Facet.MAX_EXCLUSIVE: 182 MaxExclusiveFacet xef = (MaxExclusiveFacet) facet; 183 if (!xef.matches(parsedValue)) 184 throw new DatatypeException("beyond upper bound"); 185 break; 186 case Facet.MIN_EXCLUSIVE: 187 MinExclusiveFacet nef = (MinExclusiveFacet) facet; 188 if (!nef.matches(parsedValue)) 189 throw new DatatypeException("beyond lower bound"); 190 break; 191 case Facet.MIN_INCLUSIVE: 192 MinInclusiveFacet nif = (MinInclusiveFacet) facet; 193 if (!nif.matches(parsedValue)) 194 throw new DatatypeException("beyond lower bound"); 195 break; 196 case Facet.TOTAL_DIGITS: 197 TotalDigitsFacet tdf = (TotalDigitsFacet) facet; 198 if (countDigits(value, true) > tdf.value) 199 throw new DatatypeException("too many digits"); 200 break; 201 case Facet.FRACTION_DIGITS: 202 FractionDigitsFacet fdf = (FractionDigitsFacet) facet; 203 if (countDigits(value, false) > fdf.value) 204 throw new DatatypeException("too many fraction digits"); 205 break; 206 } 207 } 208 } 209 } 210 countDigits(String value, boolean any)211 private static int countDigits(String value, boolean any) 212 { 213 int count = 0; 214 int len = value.length(); 215 boolean seenDecimal = false; 216 for (int i = 0; i < len; i++) 217 { 218 char c = value.charAt(i); 219 if (c == 0x2e) 220 seenDecimal = true; 221 else if (c >= 0x30 && c <= 0x39 && (any || seenDecimal)) 222 count++; 223 } 224 return count; 225 } 226 227 // TODO createStreamingValidator createStreamingValidator(ValidationContext context)228 public DatatypeStreamingValidator createStreamingValidator(ValidationContext context) 229 { 230 throw new UnsupportedOperationException(); 231 } 232 createValue(String literal, ValidationContext context)233 public Object createValue(String literal, ValidationContext context) { 234 return literal; 235 } 236 sameValue(Object value1, Object value2)237 public boolean sameValue(Object value1, Object value2) { 238 return value1.equals(value2); 239 } 240 valueHashCode(Object value)241 public int valueHashCode(Object value) { 242 return value.hashCode(); 243 } 244 getIdType()245 public int getIdType() 246 { 247 return ID_TYPE_NULL; 248 } 249 isContextDependent()250 public boolean isContextDependent() 251 { 252 return false; 253 } 254 255 } 256