001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2002-2006, GeoTools Project Managment Committee (PMC)
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation;
009: * version 2.1 of the License.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: */
016: package org.geotools.xs.facets;
017:
018: import java.lang.reflect.Array;
019: import java.util.Collection;
020:
021: import javax.xml.bind.ValidationException;
022:
023: import org.eclipse.xsd.XSDLengthFacet;
024: import org.eclipse.xsd.XSDSimpleTypeDefinition;
025: import org.eclipse.xsd.XSDTypeDefinition;
026:
027: /**
028: * length is the number of units of length, where units of length varies
029: * depending on the type that is being ???derived??? from.
030: * <p>
031: * The value of length ???must??? be a nonNegativeInteger.
032: * </p>
033: * Length is defined as:
034: * <ul>
035: * <li>string length is measured in units of characters
036: * <li>anyURI length is measured in units of characters
037: * <li>hexBinary and base64Binary length is measured in octets (8bits) on
038: * binary data
039: * <li>list length is measured in number of list items
040: * </ul>
041: * This is xml so length string applies to datatypes derrived from string.
042: * </p>
043: * Simon the spec says: <quote>
044: * For string and datatypes ???derived??? from string, length will not always
045: * coincide with "string length" as perceived by some users or with the number
046: * of storage units in some digital representation. Therefore, care should be
047: * taken when specifying a value for length and in attempting to infer storage
048: * requirements from a given value for length.
049: * </quote>
050: * <p>
051: * Example:
052: * <pre><code>
053: * <simpleType name='productCode'>
054: * <restriction base='string'>
055: * <length value='8' fixed='true'/>
056: * </restriction>
057: * </simpleType>
058: * </code></pre>
059: * @author Jody Garnett
060: */
061: public abstract class Length {
062: /**
063: * string and anyURI measured length is measured in units of characters
064: */
065: public static final Length CHARACTERS = new Length() {
066: public void validate(XSDTypeDefinition definition, Object value)
067: throws ValidationException {
068: String text = (String) value;
069:
070: if (text.length() > length(definition)) {
071: throw new ValidationException(text);
072: }
073: }
074: };
075:
076: /**
077: * hexBinary and base64Binary length is measured in octets (8bits) on
078: * binary data
079: */
080: public static final Length OCTETS = new Length() {
081: public void validate(XSDTypeDefinition definition, Object value)
082: throws ValidationException {
083: String text = (String) value;
084:
085: if (text.getBytes().length > length(definition)) {
086: throw new ValidationException(text);
087: }
088: }
089: };
090:
091: /**
092: * By default this one understands Collection, Array and Integer.
093: * <p>
094: * So if you are checking a custom object please pass in an Integer representing
095: * the size of your object.
096: * </p>
097: */
098: public static final Length LIST = new Length() {
099: public int length(XSDTypeDefinition definition) {
100: try {
101: XSDSimpleTypeDefinition simple = definition
102: .getSimpleType();
103: XSDLengthFacet facet = simple.getLengthFacet();
104:
105: if (facet == null) {
106: return Integer.MAX_VALUE;
107: }
108:
109: return Integer.parseInt(facet.getLexicalValue());
110: } catch (NumberFormatException ignore) {
111: return Integer.MIN_VALUE;
112: }
113: }
114:
115: public void validate(XSDTypeDefinition definition, Object value)
116: throws ValidationException {
117: int length = Integer.MIN_VALUE;
118:
119: if (value instanceof Collection) {
120: length = ((Collection) value).size();
121: }
122:
123: if (value.getClass().isArray()) {
124: length = Array.getLength(value);
125: }
126:
127: if (value instanceof Integer) {
128: length = ((Integer) value).intValue();
129: }
130:
131: String text = (String) value;
132:
133: if (text.getBytes().length > length(definition)) {
134: throw new ValidationException(text);
135: }
136: }
137: };
138:
139: private Length() {
140: }
141:
142: public int length(XSDTypeDefinition definition) {
143: try {
144: XSDSimpleTypeDefinition simple = (XSDSimpleTypeDefinition) definition;
145: XSDLengthFacet facet = simple.getLengthFacet();
146:
147: if (facet == null) {
148: return Integer.MAX_VALUE;
149: }
150:
151: return Integer.parseInt(facet.getLexicalValue());
152: } catch (NumberFormatException ignore) {
153: return Integer.MIN_VALUE;
154: }
155: }
156:
157: public abstract void validate(XSDTypeDefinition definition,
158: Object value) throws ValidationException;
159: }
|