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