View Javadoc
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 (C) Intalio, Inc. All Rights Reserved.
42   *
43   * $Id$
44   */
45  package org.exolab.castor.xml.schema;
46  
47  import java.math.BigDecimal;
48  import java.util.Enumeration;
49  
50  import org.exolab.castor.xml.ValidationException;
51  
52  /**
53   * Represents the base type for XML Schema Facets
54   * @author <a href="mailto:kvisco@intalio.com">Keith Visco</a>
55   * @version $Revision$ $Date: 2005-12-13 14:58:48 -0700 (Tue, 13 Dec 2005) $
56  **/
57  public class Facet extends Annotated {
58      /** SerialVersionUID */
59      private static final long serialVersionUID = 7821829275720939922L;
60  
61      public static final String ENUMERATION      = "enumeration";
62      public static final String LENGTH           = "length";
63      public static final String PATTERN          = "pattern";
64      public static final String PRECISION        = "precision";
65      public static final String MAX_EXCLUSIVE    = "maxExclusive";
66      public static final String MAX_INCLUSIVE    = "maxInclusive";
67      public static final String MIN_EXCLUSIVE    = "minExclusive";
68      public static final String MIN_INCLUSIVE    = "minInclusive";
69      public static final String MAX_LENGTH       = "maxLength";
70      public static final String MIN_LENGTH       = "minLength";
71      public static final String WHITESPACE       = "whiteSpace";
72      public static final String TOTALDIGITS      = "totalDigits";
73      public static final String FRACTIONDIGITS   = "fractionDigits";
74  
75      public static final String WHITESPACE_PRESERVE  = "preserve";
76      public static final String WHITESPACE_REPLACE   = "replace";
77      public static final String WHITESPACE_COLLAPSE  = "collapse";
78  
79      private static final String CLASSNAME = Facet.class.getName();
80  
81      private static final String NULL_ARGUMENT =
82          "A null argument was passed to " + CLASSNAME + "#";
83  
84      private static final String ZERO_LENGTH_STRING =
85          "A zero-length String was passed to " + CLASSNAME + "#";
86  
87      /** The name of this Facet. */
88      private final String _name;
89      /** The character value of this Facet. */
90      private final String  _value;
91  
92      /**
93       * The owning {@link SimpleType} instance. 
94       */
95      private SimpleType _owningType;
96  
97      /**
98       * Creates a new Facet with the given name.
99       * @param name the name of the Facet
100      * @param value the value of the Facet
101     **/
102     public Facet(final String name, final String value) {
103         if (name == null) {
104             String err = NULL_ARGUMENT;
105             err += "Facet: 'name' and 'value' must not be null.";
106             throw new IllegalArgumentException(err);
107         }
108         if (name.length() == 0) {
109             String err = ZERO_LENGTH_STRING;
110             err += "Facet: 'name' and 'value' must not be zero-length.";
111             throw new IllegalArgumentException(err);
112         }
113         this._name  = name;
114         this._value = value;
115     }
116 
117     /**
118      * Returns the name of this Facet.
119      * @return the name of this Facet
120     **/
121     public String getName() {
122         return _name;
123     }
124 
125     /**
126      * Returns the character (String) representation of this facet.
127      * @return the value of this facet
128     **/
129     public String getValue() {
130         return this._value;
131     } //-- getValue
132 
133     /**
134      * Returns true if this Facet can occur more than once, such
135      * as the "enumeration" facet.
136      * @return true if this Facet can occur more than once.
137     **/
138     public boolean isMultivalued() {
139         return _name.equals(Facet.ENUMERATION) || _name.equals(Facet.PATTERN);
140     }
141 
142     /**
143      * Returns an int representation of the value of this facet.
144      * @return an int representation of the value of this facet
145      * @throws NumberFormatException if the value fails to parse as a int.
146     **/
147     public int toInt() throws NumberFormatException {
148         return Integer.parseInt(_value);
149     }
150 
151     /**
152      * Returns a long representation of the value of this facet.
153      * @return a long representation of the value of this facet
154      * @throws NumberFormatException if the value fails to parse as a long.
155     **/
156     public long toLong() throws NumberFormatException {
157         return Long.parseLong(_value);
158     }
159 
160     /**
161      * Returns an short representation of the value of this facet.
162      * @return an short representation of the value of this facet
163      * @throws NumberFormatException if the value fails to parse as a short.
164     **/
165     public short toShort() throws NumberFormatException {
166         return Short.parseShort(_value);
167     }
168 
169     /**
170      * Returns a double representation of the value of this facet.
171      * @return a double representation of the value of this facet
172      * @throws NumberFormatException if the value fails to parse as a float.
173      */
174     public float toFloat() throws NumberFormatException {
175         if (_value.equals("INF")) {
176             return Float.POSITIVE_INFINITY;
177         }
178         if (_value.equals("-INF")) {
179             return Float.NEGATIVE_INFINITY;
180         }
181         return Float.valueOf(_value).floatValue();
182     }
183 
184     /**
185      * Returns a double representation of the value of this facet.
186      * @return a double representation of the value of this facet
187      * @throws NumberFormatException if the value fails to parse as a double.
188     **/
189     public double toDouble() throws NumberFormatException {
190         return Double.valueOf(_value).doubleValue();
191     }
192 
193     /**
194      * Returns a byte representation of the value of this facet.
195      * @return a byte representation of the value of this facet
196      * @throws NumberFormatException if the value fails to parse as a byte.
197     **/
198     public byte toByte() throws NumberFormatException {
199         return Byte.parseByte(_value);
200     }
201 
202     /**
203      * Returns a {@link BigDecimal} representation of the value of this facet.
204      * @return a {@link BigDecimal} representation of the value of this facet
205      * @throws NumberFormatException if the value cannot be parsed as number
206      */
207     public BigDecimal toBigDecimal() throws NumberFormatException {
208         return new BigDecimal(_value);
209     }
210 
211     /**
212      * Returns the type of this Schema Structure.
213      * @return the type of this Schema Structure
214     **/
215     public short getStructureType() {
216         return Structure.FACET;
217     }
218 
219     /**
220      * Checks the validity of this Schema defintion.
221      * @exception ValidationException when this Schema definition
222      * is invalid.
223     **/
224     public void validate() throws ValidationException {
225         // TODO: shouldn't this be converted to an abstract method ? 
226          //-- do nothing for now
227     }
228 
229     /**
230      * Checks whether the current facet overrides a facet of the base data type.
231      * This does generally happen when a data type is derived by restriction
232      * and it therefore has facet(s), which are more restrictive than the ones
233      * of the base data type.
234      *
235      * <p>This method is used for merging facets of the base and derived types,
236      * in order to create an effective set of facets for the derived type.
237      *
238      * <p>It's important to note that this method does not perform any validity
239      * checks. Validation must be generally performed <b>before</b> trying
240      * to merge facets of the base and derived types.
241      *
242      * @param baseFacet a facet of the base data type
243      * @return <code>true</code>,
244      *         if the current facet overrides <code>baseFacet</code>;
245      *         <code>false</code>, otherwise.
246      * 
247      * @see #checkConstraints(Enumeration,Enumeration)
248      * @see SimpleType#getEffectiveFacets()
249      */
250     public boolean overridesBase(final Facet baseFacet) {
251         return getName().equals(baseFacet.getName());
252     }
253 
254     /**
255      * Checks the constraints on the current facet against
256      * the other local facets of the same derived data type
257      * and facets of the base data type.
258      * Validation is performed according to the rules defined in
259      * "<a href="http://www.w3.org/TR/xmlschema-2/">XML Schema Part 2:
260      * Datatypes Second Edition</a>" document.
261      *
262      * @param localFacets local facets of the data type
263      * @param baseFacets  merged facets of the base data type
264      * @throws SchemaException when the current facet does not satisfy
265      *                         schema component validation constraints
266      */
267     public void checkConstraints(
268             final Enumeration localFacets, final Enumeration baseFacets)
269             throws SchemaException {
270         // Does nothing by default
271     }
272 
273     /**
274      * Sets the owning {@link SimpleType} instance.
275      * @param owningType The owning {@link SimpleType} instance.
276      */
277     public void setOwningType(final SimpleType owningType) {
278         _owningType = owningType;
279     }
280 
281     /**
282      * Returns the owning {@link SimpleType} instance.
283      * @return The owning {@link SimpleType} instance.
284      */
285     public SimpleType getOwningType() {
286         return _owningType;
287     }
288 
289 } //-- Facet