001: /*
002: * The Apache Software License, Version 1.1
003: *
004: *
005: * Copyright (c) 1999, 2000 The Apache Software Foundation. All rights
006: * reserved.
007: *
008: * Redistribution and use in source and binary forms, with or without
009: * modification, are permitted provided that the following conditions
010: * are met:
011: *
012: * 1. Redistributions of source code must retain the above copyright
013: * notice, this list of conditions and the following disclaimer.
014: *
015: * 2. Redistributions in binary form must reproduce the above copyright
016: * notice, this list of conditions and the following disclaimer in
017: * the documentation and/or other materials provided with the
018: * distribution.
019: *
020: * 3. The end-user documentation included with the redistribution,
021: * if any, must include the following acknowledgment:
022: * "This product includes software developed by the
023: * Apache Software Foundation (http://www.apache.org/)."
024: * Alternately, this acknowledgment may appear in the software itself,
025: * if and wherever such third-party acknowledgments normally appear.
026: *
027: * 4. The names "Xerces" and "Apache Software Foundation" must
028: * not be used to endorse or promote products derived from this
029: * software without prior written permission. For written
030: * permission, please contact apache@apache.org.
031: *
032: * 5. Products derived from this software may not be called "Apache",
033: * nor may "Apache" appear in their name, without prior written
034: * permission of the Apache Software Foundation.
035: *
036: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
037: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
038: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
039: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
040: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
041: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
042: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
043: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
044: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
045: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
046: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
047: * SUCH DAMAGE.
048: * ====================================================================
049: *
050: * This software consists of voluntary contributions made by many
051: * individuals on behalf of the Apache Software Foundation and was
052: * originally based on software copyright (c) 1999, International
053: * Business Machines, Inc., http://www.apache.org. For more
054: * information on the Apache Software Foundation, please see
055: * <http://www.apache.org/>.
056: */
057:
058: package org.apache.xerces.validators.datatype;
059:
060: import java.util.Enumeration;
061: import java.util.Hashtable;
062: import java.util.Vector;
063: import org.apache.xerces.validators.schema.SchemaSymbols;
064: import org.apache.xerces.utils.regex.RegularExpression;
065: import java.util.StringTokenizer;
066: import java.util.NoSuchElementException;
067:
068: /**
069: *
070: * @author Elena Litani
071: * @author Ted Leung
072: * @author Jeffrey Rodriguez
073: * @author Mark Swinkles - List Validation refactoring
074: * @version $Id: FloatDatatypeValidator.java,v 1.21 2001/04/25 20:42:03 elena Exp $
075: */
076:
077: public class FloatDatatypeValidator extends AbstractNumericValidator {
078:
079: public FloatDatatypeValidator()
080: throws InvalidDatatypeFacetException {
081: this (null, null, false); // Native, No Facets defined, Restriction
082: }
083:
084: public FloatDatatypeValidator(DatatypeValidator base,
085: Hashtable facets, boolean derivedByList)
086: throws InvalidDatatypeFacetException {
087: // Set base type
088: super (base, facets, derivedByList);
089: }
090:
091: public int compare(String value1, String value2) {
092: try {
093: float f1 = fValueOf(value1).floatValue();
094: float f2 = fValueOf(value2).floatValue();
095: return compareFloats(f1, f2);
096: } catch (NumberFormatException e) {
097: //REVISIT: should we throw exception??
098: return -1;
099: }
100: }
101:
102: protected void assignAdditionalFacets(String key, Hashtable facets)
103: throws InvalidDatatypeFacetException {
104: throw new InvalidDatatypeFacetException(getErrorString(
105: DatatypeMessageProvider.ILLEGAL_FLOAT_FACET,
106: DatatypeMessageProvider.MSG_NONE, new Object[] { key }));
107: }
108:
109: protected int compareValues(Object value1, Object value2) {
110:
111: float f1 = ((Float) value1).floatValue();
112: float f2 = ((Float) value2).floatValue();
113: return compareFloats(f1, f2);
114: }
115:
116: protected void setMaxInclusive(String value) {
117: fMaxInclusive = fValueOf(value);
118: }
119:
120: protected void setMinInclusive(String value) {
121: fMinInclusive = fValueOf(value);
122:
123: }
124:
125: protected void setMaxExclusive(String value) {
126: fMaxExclusive = fValueOf(value);
127:
128: }
129:
130: protected void setMinExclusive(String value) {
131: fMinExclusive = fValueOf(value);
132:
133: }
134:
135: protected void setEnumeration(Vector enumeration)
136: throws InvalidDatatypeValueException {
137: if (enumeration != null) {
138: fEnumeration = new Float[enumeration.size()];
139: Object[] baseEnum = null;
140: for (int i = 0; i < enumeration.size(); i++) {
141: fEnumeration[i] = fValueOf((String) enumeration
142: .elementAt(i));
143: ((FloatDatatypeValidator) fBaseValidator).validate(
144: (String) enumeration.elementAt(i), null);
145: }
146: }
147: }
148:
149: protected String getMaxInclusive(boolean isBase) {
150: return (isBase) ? (((FloatDatatypeValidator) fBaseValidator).fMaxInclusive
151: .toString())
152: : ((Float) fMaxInclusive).toString();
153: }
154:
155: protected String getMinInclusive(boolean isBase) {
156: return (isBase) ? (((FloatDatatypeValidator) fBaseValidator).fMinInclusive
157: .toString())
158: : ((Float) fMinInclusive).toString();
159: }
160:
161: protected String getMaxExclusive(boolean isBase) {
162: return (isBase) ? (((FloatDatatypeValidator) fBaseValidator).fMaxExclusive
163: .toString())
164: : ((Float) fMaxExclusive).toString();
165: }
166:
167: protected String getMinExclusive(boolean isBase) {
168: return (isBase) ? (((FloatDatatypeValidator) fBaseValidator).fMinExclusive
169: .toString())
170: : ((Float) fMinExclusive).toString();
171: }
172:
173: /**
174: * validate if the content is valid against base datatype and facets (if any)
175: * this function might be called directly from UnionDatatype or ListDatatype
176: *
177: * @param content A string containing the content to be validated
178: * @param enumeration A vector with enumeration strings
179: * @exception throws InvalidDatatypeException if the content is
180: * is not a W3C float type;
181: * @exception throws InvalidDatatypeFacetException if enumeration is not float
182: */
183:
184: protected void checkContent(String content, Object state,
185: Vector enumeration, boolean asBase)
186: throws InvalidDatatypeValueException {
187: // validate against parent type if any
188: if (this .fBaseValidator != null) {
189: // validate content as a base type
190: ((FloatDatatypeValidator) fBaseValidator).checkContent(
191: content, state, enumeration, true);
192: }
193:
194: // we check pattern first
195: if ((fFacetsDefined & DatatypeValidator.FACET_PATTERN) != 0) {
196: if (fRegex == null || fRegex.matches(content) == false)
197: throw new InvalidDatatypeValueException("Value'"
198: + content
199: + "does not match regular expression facet"
200: + fPattern);
201: }
202:
203: // if this is a base validator, we only need to check pattern facet
204: // all other facet were inherited by the derived type
205: if (asBase)
206: return;
207:
208: Float f = null;
209: try {
210: f = fValueOf(content);
211: } catch (NumberFormatException nfe) {
212: throw new InvalidDatatypeValueException(getErrorString(
213: DatatypeMessageProvider.NOT_FLOAT,
214: DatatypeMessageProvider.MSG_NONE,
215: new Object[] { content }));
216: }
217:
218: //enumeration is passed from List or Union datatypes
219: if (enumeration != null) {
220: int size = enumeration.size();
221: Float[] enumFloats = new Float[size];
222: int i = 0;
223: try {
224: for (; i < size; i++)
225: enumFloats[i] = fValueOf((String) enumeration
226: .elementAt(i));
227:
228: } catch (NumberFormatException nfe) {
229: throw new InvalidDatatypeValueException(getErrorString(
230: DatatypeMessageProvider.INVALID_ENUM_VALUE,
231: DatatypeMessageProvider.MSG_NONE,
232: new Object[] { enumeration.elementAt(i) }));
233: }
234: enumCheck(f.floatValue(), enumFloats);
235: }
236:
237: boundsCheck(f);
238:
239: if (((fFacetsDefined & DatatypeValidator.FACET_ENUMERATION) != 0 && (fEnumeration != null))) {
240: enumCheck(f.floatValue(), (Float[]) fEnumeration);
241: }
242: }
243:
244: protected int getInvalidFacetMsg() {
245: return DatatypeMessageProvider.ILLEGAL_FLOAT_FACET;
246: }
247:
248: private void enumCheck(float v, Float[] enumFloats)
249: throws InvalidDatatypeValueException {
250: for (int i = 0; i < enumFloats.length; i++) {
251: if (v == ((Float) enumFloats[i]).floatValue())
252: return;
253: }
254: throw new InvalidDatatypeValueException(getErrorString(
255: DatatypeMessageProvider.NOT_ENUM_VALUE,
256: DatatypeMessageProvider.MSG_NONE,
257: new Object[] { new Float(v) }));
258: }
259:
260: private static Float fValueOf(String s)
261: throws NumberFormatException {
262: Float f = null;
263: try {
264: f = Float.valueOf(s);
265: } catch (NumberFormatException nfe) {
266: if (s.equals("INF")) {
267: f = new Float(Float.POSITIVE_INFINITY);
268: } else if (s.equals("-INF")) {
269: f = new Float(Float.NEGATIVE_INFINITY);
270: } else if (s.equals("NaN")) {
271: f = new Float(Float.NaN);
272: } else {
273: throw nfe;
274: }
275: }
276: return f;
277: }
278:
279: private int compareFloats(float f1, float f2) {
280: int f1V = Float.floatToIntBits(f1);
281: int f2V = Float.floatToIntBits(f2);
282: if (f1 > f2) {
283: return 1;
284: }
285: if (f1 < f2) {
286: return -1;
287: }
288: if (f1V == f2V) {
289: return 0;
290: }
291: //REVISIT: NaN values comparison..
292: return (f1V < f2V) ? -1 : 1;
293: }
294: }
|