001: /******************************************************************
002: * File: BaseDatatype.java
003: * Created by: Dave Reynolds
004: * Created on: 08-Dec-02
005: *
006: * (c) Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
007: * [See end of file]
008: * $Id: BaseDatatype.java,v 1.16 2008/01/02 12:10:24 andy_seaborne Exp $
009: *****************************************************************/package com.hp.hpl.jena.datatypes;
010:
011: import com.hp.hpl.jena.graph.impl.LiteralLabel;
012:
013: /**
014: * Base level implementation of datatype from which real implementations
015: * can inherit.
016: *
017: * @author <a href="mailto:der@hplb.hpl.hp.com">Dave Reynolds</a>
018: * @version $Revision: 1.16 $ on $Date: 2008/01/02 12:10:24 $
019: */
020: public class BaseDatatype implements RDFDatatype {
021:
022: /** The URI label for this data type */
023: protected String uri;
024:
025: /**
026: * Constructor.
027: * @param uri the URI label to use for this datatype
028: */
029: public BaseDatatype(String uri) {
030: this .uri = uri;
031: }
032:
033: /**
034: * Return the URI which is the label for this datatype
035: */
036: public String getURI() {
037: return uri;
038: }
039:
040: /**
041: * Pair object used to encode both lexical form
042: * and datatype for a typed literal with unknown
043: * datatype.
044: */
045: public static class TypedValue {
046: public final String lexicalValue;
047: public final String datatypeURI;
048:
049: public TypedValue(String lexicalValue, String datatypeURI) {
050: this .lexicalValue = lexicalValue;
051: this .datatypeURI = datatypeURI;
052: }
053:
054: public boolean equals(Object other) {
055: if (other instanceof TypedValue) {
056: return lexicalValue
057: .equals(((TypedValue) other).lexicalValue)
058: && datatypeURI
059: .equals(((TypedValue) other).datatypeURI);
060: } else {
061: return false;
062: }
063: }
064:
065: public int hashCode() {
066: return lexicalValue.hashCode() ^ datatypeURI.hashCode();
067: }
068:
069: }
070:
071: /**
072: * Convert a value of this datatype out
073: * to lexical form.
074: */
075: public String unparse(Object value) {
076: // Default implementation expects a parsed TypedValue but will
077: // accept a pure lexical form
078: if (value instanceof TypedValue) {
079: return ((TypedValue) value).lexicalValue;
080: }
081: return value.toString();
082: }
083:
084: /**
085: * Parse a lexical form of this datatype to a value
086: * @throws DatatypeFormatException if the lexical form is not legal
087: */
088: public Object parse(String lexicalForm)
089: throws DatatypeFormatException {
090: return new TypedValue(lexicalForm, getURI());
091: }
092:
093: /**
094: * Test whether the given string is a legal lexical form
095: * of this datatype.
096: */
097: public boolean isValid(String lexicalForm) {
098: try {
099: parse(lexicalForm);
100: return true;
101: } catch (DatatypeFormatException e) {
102: return false;
103: }
104: }
105:
106: /**
107: * Test whether the given LiteralLabel is a valid instance
108: * of this datatype. This takes into accound typing information
109: * as well as lexical form - for example an xsd:string is
110: * never considered valid as an xsd:integer (even if it is
111: * lexically legal like "1").
112: */
113: public boolean isValidLiteral(LiteralLabel lit) {
114: // default is that only literals with the same type are valid
115: return equals(lit.getDatatype());
116: }
117:
118: /**
119: * Test whether the given object is a legal value form
120: * of this datatype.
121: */
122: public boolean isValidValue(Object valueForm) {
123: // Default to brute force
124: return isValid(unparse(valueForm));
125: }
126:
127: /**
128: * Compares two instances of values of the given datatype.
129: * This default requires value and datatype equality.
130: */
131: public boolean isEqual(LiteralLabel value1, LiteralLabel value2) {
132: return value1.getDatatype() == value2.getDatatype()
133: && value1.getValue().equals(value2.getValue());
134: }
135:
136: /**
137: Default implementation of getHashCode() delegates to the default from
138: the literal label.
139: */
140: public int getHashCode(LiteralLabel lit) {
141: return lit.getDefaultHashcode();
142: }
143:
144: /**
145: * Helper function to compare language tag values
146: */
147: public boolean langTagCompatible(LiteralLabel value1,
148: LiteralLabel value2) {
149: if (value1.language() == null) {
150: return (value2.language() == null || value2.language()
151: .equals(""));
152: } else {
153: return value1.language()
154: .equalsIgnoreCase(value2.language());
155: }
156: }
157:
158: /**
159: * Returns the java class which is used to represent value
160: * instances of this datatype.
161: */
162: public Class getJavaClass() {
163: return null;
164: }
165:
166: /**
167: * Cannonicalise a java Object value to a normal form.
168: * Primarily used in cases such as xsd:integer to reduce
169: * the Java object representation to the narrowest of the Number
170: * subclasses to ensure that indexing of typed literals works.
171: */
172: public Object cannonicalise(Object value) {
173: return value;
174: }
175:
176: /**
177: * Returns an object giving more details on the datatype.
178: * This is type system dependent. In the case of XSD types
179: * this will be an instance of
180: * <code>org.apache.xerces.impl.xs.psvi.XSTypeDefinition</code>.
181: */
182: public Object extendedTypeDefinition() {
183: return null;
184: }
185:
186: /**
187: * Normalization. If the value is narrower than the current data type
188: * (e.g. value is xsd:date but the time is xsd:datetime) returns
189: * the narrower type for the literal.
190: * If the type is narrower than the value then it may normalize
191: * the value (e.g. set the mask of an XSDDateTime)
192: * Currently only used to narrow gener XSDDateTime objects
193: * to the minimal XSD date/time type.
194: * @param value the current object value
195: * @param dt the currently set data type
196: * @return a narrower version of the datatype based on the actual value range
197: */
198: public RDFDatatype normalizeSubType(Object value, RDFDatatype dt) {
199: return this ; // default is no narrowing
200: }
201:
202: /**
203: * Display format
204: */
205: public String toString() {
206: return "Datatype["
207: + uri
208: + (getJavaClass() == null ? "" : " -> "
209: + getJavaClass()) + "]";
210: }
211: }
212:
213: /*
214: (c) Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
215: All rights reserved.
216:
217: Redistribution and use in source and binary forms, with or without
218: modification, are permitted provided that the following conditions
219: are met:
220:
221: 1. Redistributions of source code must retain the above copyright
222: notice, this list of conditions and the following disclaimer.
223:
224: 2. Redistributions in binary form must reproduce the above copyright
225: notice, this list of conditions and the following disclaimer in the
226: documentation and/or other materials provided with the distribution.
227:
228: 3. The name of the author may not be used to endorse or promote products
229: derived from this software without specific prior written permission.
230:
231: THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
232: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
233: OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
234: IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
235: INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
236: NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
237: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
238: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
239: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
240: THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
241: */
|