001 /*
002 * Copyright (c) 2006 Henri Sivonen
003 *
004 * Permission is hereby granted, free of charge, to any person obtaining a
005 * copy of this software and associated documentation files (the "Software"),
006 * to deal in the Software without restriction, including without limitation
007 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
008 * and/or sell copies of the Software, and to permit persons to whom the
009 * Software is furnished to do so, subject to the following conditions:
010 *
011 * The above copyright notice and this permission notice shall be included in
012 * all copies or substantial portions of the Software.
013 *
014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
015 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
016 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
017 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
018 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
019 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
020 * DEALINGS IN THE SOFTWARE.
021 */
022
023 package org.whattf.datatype;
024
025 import org.relaxng.datatype.Datatype;
026 import org.relaxng.datatype.DatatypeException;
027 import org.relaxng.datatype.DatatypeStreamingValidator;
028 import org.relaxng.datatype.ValidationContext;
029
030 /**
031 * Common superclass for HTML5 datatypes. Implements all methods of the
032 * <code>Datatype</code> interface and leaves a new <code>checkValid</code> for
033 * subclasses to implement.
034 *
035 * @version $Id: AbstractDatatype.java,v 1.7 2006/11/26 14:22:54 hsivonen Exp $
036 * @author hsivonen
037 */
038 abstract class AbstractDatatype implements Datatype {
039
040 /**
041 * Mask for ASCII case folding.
042 */
043 private static final int CASE_MASK = (1 << 5);
044
045 /**
046 * Constructor
047 */
048 AbstractDatatype() {
049 super();
050 }
051
052 /**
053 * Calls <code>checkValid(CharSequence literal)</code>.
054 * @param literal the value
055 * @param context the validation context (ignored by subclasses)
056 * @return <code>true</code> if valid and <code>false</code> if not
057 * @see org.relaxng.datatype.Datatype#isValid(java.lang.String, org.relaxng.datatype.ValidationContext)
058 */
059 public final boolean isValid(String literal, ValidationContext context) {
060 try {
061 checkValid(literal);
062 } catch (DatatypeException e) {
063 return false;
064 }
065 return true;
066 }
067
068 /**
069 * Delegates to <code>checkValid(CharSequence literal)</code>.
070 * @param literal the value
071 * @param context the validation context (ignored by subclasses)
072 * @throws DatatypeException if the literal does not conform to the datatype definition
073 * @see org.relaxng.datatype.Datatype#checkValid(java.lang.String, org.relaxng.datatype.ValidationContext)
074 */
075 public final void checkValid(String literal, ValidationContext context) throws DatatypeException {
076 checkValid(literal);
077 }
078
079 public abstract void checkValid(CharSequence literal) throws DatatypeException;
080
081 /**
082 * Merely returns a <code>DatatypeStreamingValidatorImpl</code>.
083 * @param context the validation context (ignored by subclasses)
084 * @return An unoptimized <code>DatatypeStreamingValidator</code>
085 * @see org.relaxng.datatype.Datatype#createStreamingValidator(org.relaxng.datatype.ValidationContext)
086 */
087 public DatatypeStreamingValidator createStreamingValidator(
088 ValidationContext context) {
089 return new DatatypeStreamingValidatorImpl(this);
090 }
091
092 /**
093 * Implements strict string equality semantics by returning <code>literal</code>
094 * itself.
095 * @param literal the value (get returned)
096 * @param context ignored
097 * @return the <code>literal</code> that was passed in
098 * @see org.relaxng.datatype.Datatype#createValue(java.lang.String, org.relaxng.datatype.ValidationContext)
099 */
100 public final Object createValue(String literal, ValidationContext context) {
101 return literal;
102 }
103
104 /**
105 * Implements strict stirng equality semantics by performing a standard
106 * <code>equals</code> check on the arguments.
107 * @param value1 an object returned by <code>createValue</code>
108 * @param value2 another object returned by <code>createValue</code>
109 * @return <code>true</code> if the values are equal, <code>false</code> otherwise
110 * @see org.relaxng.datatype.Datatype#sameValue(java.lang.Object, java.lang.Object)
111 */
112 public final boolean sameValue(Object value1, Object value2) {
113 if (value1 == null) {
114 return (value2 == null);
115 }
116 return value1.equals(value2);
117 }
118
119 /**
120 * Implements strict stirng equality semantics by returning the
121 * <code>java.lang.Object</code>-level <code>hashCode</code> of
122 * the object.
123 * @param value an object returned by <code>createValue</code>
124 * @return the hash code
125 * @see org.relaxng.datatype.Datatype#valueHashCode(java.lang.Object)
126 */
127 public final int valueHashCode(Object value) {
128 return value.hashCode();
129 }
130
131 /**
132 * Always returns <code>Datatype.ID_TYPE_NULL</code>. (Overridden by subclasses
133 * that have a different ID-type.)
134 * @return <code>Datatype.ID_TYPE_NULL</code>
135 * @see org.relaxng.datatype.Datatype#getIdType()
136 */
137 public int getIdType() {
138 return Datatype.ID_TYPE_NULL;
139 }
140
141 /**
142 * Always returns <code>false</code>
143 * @return <code>false</code>
144 * @see org.relaxng.datatype.Datatype#isContextDependent()
145 */
146 public final boolean isContextDependent() {
147 return false;
148 }
149
150 /**
151 * Checks if a UTF-16 code unit represents a whitespace character (U+0020,
152 * U+0009, U+000D or U+000A).
153 * @param c the code unit
154 * @return <code>true</code> if whitespace, <code>false</code> otherwise
155 */
156 protected final boolean isWhitespace(char c) {
157 return c == ' ' || c == '\t' || c == '\n' || c == '\r';
158 }
159
160 /**
161 * If the argument is an upper case ASCII letter, returns the letter in
162 * lower case. Otherwise returns the argument.
163 * @param c a UTF-16 code unit
164 * @return upper case ASCII lower cased
165 */
166 protected final char toAsciiLowerCase(char c) {
167 if (c >= 'A' && c <= 'Z') {
168 return (char) (c | CASE_MASK);
169 } else {
170 return c;
171 }
172 }
173
174 protected final String toAsciiLowerCase(String str) {
175 char[] buf = str.toCharArray();
176 for (int i = 0; i < buf.length; i++) {
177 buf[i] = toAsciiLowerCase(buf[i]);
178 }
179 return new String(buf);
180 }
181 }