| /* SimpleType.java -- |
| Copyright (C) 2006 Free Software Foundation, Inc. |
| |
| This file is part of GNU Classpath. |
| |
| GNU Classpath is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 2, or (at your option) |
| any later version. |
| |
| GNU Classpath is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with GNU Classpath; see the file COPYING. If not, write to the |
| Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
| 02110-1301 USA. |
| |
| Linking this library statically or dynamically with other modules is |
| making a combined work based on this library. Thus, the terms and |
| conditions of the GNU General Public License cover the whole |
| combination. |
| |
| As a special exception, the copyright holders of this library give you |
| permission to link this library with independent modules to produce an |
| executable, regardless of the license terms of these independent |
| modules, and to copy and distribute the resulting executable under |
| terms of your choice, provided that you also meet, for each linked |
| independent module, the terms and conditions of the license of that |
| module. An independent module is a module which is not derived from |
| or based on this library. If you modify this library, you may extend |
| this exception to your version of the library, but you are not |
| obligated to do so. If you do not wish to do so, delete this |
| exception statement from your version. */ |
| |
| package gnu.xml.validation.datatype; |
| |
| import java.util.Iterator; |
| import java.util.Set; |
| import java.util.regex.Matcher; |
| import javax.xml.XMLConstants; |
| import javax.xml.namespace.QName; |
| import org.relaxng.datatype.Datatype; |
| import org.relaxng.datatype.DatatypeException; |
| import org.relaxng.datatype.DatatypeStreamingValidator; |
| import org.relaxng.datatype.ValidationContext; |
| |
| /** |
| * An XML Schema simple type. |
| * |
| * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a> |
| */ |
| public class SimpleType |
| extends Type |
| implements Datatype |
| { |
| |
| /** |
| * The variety of the <code>anySimpleType</code> datatype. |
| */ |
| public static final int ANY = 0; |
| |
| /** |
| * The atomic variety. |
| */ |
| public static final int ATOMIC = 1; |
| |
| /** |
| * The list variety. |
| */ |
| public static final int LIST = 2; |
| |
| /** |
| * The union variety. |
| */ |
| public static final int UNION = 3; |
| |
| public static final int ID_TYPE_NULL = 0; |
| public static final int ID_TYPE_ID = 1; |
| public static final int ID_TYPE_IDREF = 2; |
| public static final int ID_TYPE_IDREFS = 3; |
| |
| /** |
| * The variety of this simple type. |
| */ |
| public final int variety; |
| |
| /** |
| * The facets of this simple type. |
| */ |
| public Set facets; |
| |
| /** |
| * The fundamental facets of this simple type. |
| */ |
| public int fundamentalFacets; |
| |
| /** |
| * If this datatype has been derived by restriction, then the component |
| * from which it was derived. |
| */ |
| public final SimpleType baseType; |
| |
| /** |
| * Optional annotation. |
| */ |
| public final Annotation annotation; |
| |
| public SimpleType(QName name, int variety, Set facets, |
| int fundamentalFacets, SimpleType baseType, |
| Annotation annotation) |
| { |
| super(name); |
| this.variety = variety; |
| this.facets = facets; |
| this.fundamentalFacets = fundamentalFacets; |
| this.baseType = baseType; |
| this.annotation = annotation; |
| } |
| |
| /** |
| * Indicates whether this type permits the specified value. |
| */ |
| public boolean isValid(String value, ValidationContext context) |
| { |
| try |
| { |
| checkValid(value, context); |
| return true; |
| } |
| catch (DatatypeException e) |
| { |
| return false; |
| } |
| } |
| |
| public void checkValid(String value, ValidationContext context) |
| throws DatatypeException |
| { |
| if (facets != null && !facets.isEmpty()) |
| { |
| Object parsedValue = createValue(value, context); |
| for (Iterator i = facets.iterator(); i.hasNext(); ) |
| { |
| Facet facet = (Facet) i.next(); |
| switch (facet.type) |
| { |
| case Facet.LENGTH: |
| LengthFacet lf = (LengthFacet) facet; |
| if (value.length() != lf.value) |
| throw new DatatypeException("invalid length"); |
| break; |
| case Facet.MIN_LENGTH: |
| MinLengthFacet nlf = (MinLengthFacet) facet; |
| if (value.length() < nlf.value) |
| throw new DatatypeException("invalid minimum length"); |
| break; |
| case Facet.MAX_LENGTH: |
| MaxLengthFacet xlf = (MaxLengthFacet) facet; |
| if (value.length() > xlf.value) |
| throw new DatatypeException("invalid maximum length"); |
| break; |
| case Facet.PATTERN: |
| PatternFacet pf = (PatternFacet) facet; |
| Matcher matcher = pf.value.matcher(value); |
| if (!matcher.find()) |
| throw new DatatypeException("invalid match for pattern"); |
| break; |
| case Facet.ENUMERATION: |
| // TODO |
| break; |
| case Facet.WHITESPACE: |
| // TODO |
| break; |
| case Facet.MAX_INCLUSIVE: |
| MaxInclusiveFacet xif = (MaxInclusiveFacet) facet; |
| if (!xif.matches(parsedValue)) |
| throw new DatatypeException("beyond upper bound"); |
| break; |
| case Facet.MAX_EXCLUSIVE: |
| MaxExclusiveFacet xef = (MaxExclusiveFacet) facet; |
| if (!xef.matches(parsedValue)) |
| throw new DatatypeException("beyond upper bound"); |
| break; |
| case Facet.MIN_EXCLUSIVE: |
| MinExclusiveFacet nef = (MinExclusiveFacet) facet; |
| if (!nef.matches(parsedValue)) |
| throw new DatatypeException("beyond lower bound"); |
| break; |
| case Facet.MIN_INCLUSIVE: |
| MinInclusiveFacet nif = (MinInclusiveFacet) facet; |
| if (!nif.matches(parsedValue)) |
| throw new DatatypeException("beyond lower bound"); |
| break; |
| case Facet.TOTAL_DIGITS: |
| TotalDigitsFacet tdf = (TotalDigitsFacet) facet; |
| if (countDigits(value, true) > tdf.value) |
| throw new DatatypeException("too many digits"); |
| break; |
| case Facet.FRACTION_DIGITS: |
| FractionDigitsFacet fdf = (FractionDigitsFacet) facet; |
| if (countDigits(value, false) > fdf.value) |
| throw new DatatypeException("too many fraction digits"); |
| break; |
| } |
| } |
| } |
| } |
| |
| private static int countDigits(String value, boolean any) |
| { |
| int count = 0; |
| int len = value.length(); |
| boolean seenDecimal = false; |
| for (int i = 0; i < len; i++) |
| { |
| char c = value.charAt(i); |
| if (c == 0x2e) |
| seenDecimal = true; |
| else if (c >= 0x30 && c <= 0x39 && (any || seenDecimal)) |
| count++; |
| } |
| return count; |
| } |
| |
| // TODO createStreamingValidator |
| public DatatypeStreamingValidator createStreamingValidator(ValidationContext context) |
| { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public Object createValue(String literal, ValidationContext context) { |
| return literal; |
| } |
| |
| public boolean sameValue(Object value1, Object value2) { |
| return value1.equals(value2); |
| } |
| |
| public int valueHashCode(Object value) { |
| return value.hashCode(); |
| } |
| |
| public int getIdType() |
| { |
| return ID_TYPE_NULL; |
| } |
| |
| public boolean isContextDependent() |
| { |
| return false; |
| } |
| |
| } |
| |