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 }