KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > hp > hpl > jena > graph > impl > LiteralLabel


1 /*
2   (c) Copyright 2003, 2004, 2005 Hewlett-Packard Development Company, LP
3   [See end of file]
4   $Id: LiteralLabel.java,v 1.16 2005/04/08 13:49:50 der Exp $
5 */

6
7 package com.hp.hpl.jena.graph.impl;
8
9 import com.hp.hpl.jena.datatypes.*;
10 import com.hp.hpl.jena.datatypes.xsd.*;
11 import com.hp.hpl.jena.datatypes.xsd.impl.*;
12 import com.hp.hpl.jena.shared.impl.JenaParameters;
13
14 /**
15  * Represents the "contents" of a Node_Literal.
16  * These contents comprise a lexical form, an optional language tag,
17  * and optional datatype structure and a value.
18  *
19  * @author Jeremy Carroll and Dave Reynolds
20  */

21 final public class LiteralLabel {
22
23     //=======================================================================
24
// Variables
25

26     /**
27      * The lexical form of the literal, may be null if the literal was
28      * created programatically and has not yet been serialized
29      */

30     private String JavaDoc lexicalForm;
31
32     /**
33      * The value form of the literal. It will be null only if the value
34      * has not been parsed or if it is an illegal value.
35      * For plain literals and xsd:string literals
36      * the value is the same as the lexicalForm.
37      */

38     private Object JavaDoc value;
39
40     /**
41      * The type of the literal. A null type indicates a classic "plain" literal.
42      * The type of a literal is fixed when it is created.
43      */

44     final private RDFDatatype dtype;
45
46     /**
47      * The xml:lang tag. For xsd literals this is ignored and not part of
48      * equality. For plain literals it is not ignored. The lang of a
49      * literal is fixed when it is created.
50      */

51     final private String JavaDoc lang;
52
53     /**
54      * Indicates whether this is a legal literal. The working groups requires
55      * ill-formed literals to be treated as syntactically correct so instead
56      * of only storing well-formed literals we hack around it this way.
57      * N.B. This applies to any literal, not just XML well-formed literals.
58      */

59     private boolean wellformed = true;
60
61     //=======================================================================
62
// Constructors
63

64     /**
65      * Build a typed literal label from its lexical form. The
66      * lexical form will be parsed now and the value stored. If
67      * the form is not legal this will throw an exception.
68      *
69      * @param lex the lexical form of the literal
70      * @param lang the optional language tag, only relevant for plain literals
71      * @param dtype the type of the literal, null for old style "plain" literals
72      * @throws DatatypeFormatException if lex is not a legal form of dtype
73      */

74     public LiteralLabel(String JavaDoc lex, String JavaDoc lang, RDFDatatype dtype)
75         throws DatatypeFormatException {
76         lexicalForm = lex;
77         this.dtype = dtype;
78         this.lang = (lang == null ? "" : lang);
79         if (dtype == null) {
80             value = lex;
81         } else {
82             setValue(lex);
83         }
84     }
85
86     /**
87      * Build a plain literal label from its lexical form.
88      * @param lex the lexical form of the literal
89      * @param lang the optional language tag, only relevant for plain literals
90      */

91     public LiteralLabel(String JavaDoc lex, String JavaDoc lang) {
92         this(lex, lang, null);
93     }
94
95     /**
96      * Build a typed literal label from its value form. If the value is a string we
97      * assume this is inteded to be a lexical form after all.
98      *
99      * @param value the value of the literal
100      * @param lang the optional language tag, only relevant for plain literals
101      * @param dtype the type of the literal, null for old style "plain" literals
102      */

103     public LiteralLabel(Object JavaDoc value, String JavaDoc lang, RDFDatatype dtype) throws DatatypeFormatException {
104         this.dtype = dtype;
105         this.lang = (lang == null ? "" : lang);
106         if (value instanceof String JavaDoc) {
107             String JavaDoc lex = (String JavaDoc)value;
108             lexicalForm = lex;
109             if (dtype == null) {
110                 value = lex;
111             } else {
112                 setValue(lex);
113             }
114         } else {
115             this.value = value;
116         }
117     }
118
119     /**
120      * Build a typed literal label supplying both value and lexical form.
121      * The caller guarantees that the lexical form is legal,
122      * and the value corresponds.
123      *
124      * @param lex the lexical form of the literal
125      * @param value the value of the literal
126      * @param lang the optional language tag, only relevant for plain literals
127      * @param dtype the type of the literal, null for old style "plain" literals
128      */

129     public LiteralLabel(
130         String JavaDoc lex,
131         Object JavaDoc value,
132         String JavaDoc lang,
133         RDFDatatype dtype) {
134         this(value, lang, dtype);
135         this.lexicalForm = lex;
136     }
137
138     /**
139      * Build a typed literal label from its value form using
140      * whatever datatype is currently registered as the the default
141      * representation for this java class. No language tag is supplied.
142      * @param value the literal value to encapsulate
143      */

144     public LiteralLabel(Object JavaDoc value) {
145         this(value, "", TypeMapper.getInstance().getTypeByValue(value));
146     }
147
148     /**
149      * Old style constructor. Creates either a plain literal or an
150      * XMLLiteral.
151      * @param xml If true then s is exclusive canonical XML of type rdf:XMLLiteral, and no checking will be invoked.
152     
153      */

154     public LiteralLabel(String JavaDoc s, String JavaDoc lg, boolean xml) {
155         this.lexicalForm = s;
156         this.lang = (lg == null ? "" : lg);
157         if (xml) {
158             // XML Literal
159
this.dtype = XMLLiteralType.theXMLLiteralType;
160             value = s;
161             wellformed = true;
162         } else {
163             // Plain literal
164
this.value = s;
165             this.dtype = null;
166         }
167     }
168
169     /**
170      * Internal function to set the object value from the lexical form.
171      * Requires datatype to be set.
172      * @throws DatatypeFormatException if the value is ill-formed and
173      * eager checking is on.
174      */

175     private void setValue(String JavaDoc lex) throws DatatypeFormatException {
176         try {
177             value = dtype.parse(lex);
178             wellformed = true;
179         } catch (DatatypeFormatException e) {
180             if (JenaParameters.enableEagerLiteralValidation) {
181                 e.fillInStackTrace();
182                 throw e;
183             } else {
184                 wellformed = false;
185             }
186         }
187     }
188
189     //=======================================================================
190
// Methods
191

192     /**
193      * Return true if the literal is a well-formed XML literal (for example as
194      * created via parsetype="literal")
195      */

196     public boolean isXML() {
197         return dtype == XMLLiteralType.theXMLLiteralType && this.wellformed;
198     }
199     
200     /**
201     * Return true if the literal is a typed literal and the
202         * lexicalForm is in the lexical space.
203     */

204     public boolean isWellFormed() {
205         return dtype != null && this.wellformed;
206     }
207     
208     /**
209         Answer a human-acceptable representation of this literal value.
210         This is NOT intended for a machine-processed result.
211     */

212     public String JavaDoc toString(boolean quoting) {
213         StringBuffer JavaDoc b = new StringBuffer JavaDoc();
214         if (quoting) b.append('"');
215         b.append(getLexicalForm());
216         if (quoting) b.append('"');
217         if (lang != null && !lang.equals( "" )) b.append( "@" ).append(lang);
218         if (dtype != null) b.append( "^^" ).append(dtype.getURI());
219         return b.toString();
220     }
221
222     public String JavaDoc toString() {
223         return toString(false);
224     }
225
226     /**
227      * Returns the string component of the LiteralLabel.
228      * Note that different LiteralLabels may have the
229      * same string component.
230      * A canonical form is returned using the
231      * asNTriple() method.
232      */

233     public String JavaDoc getLexicalForm() {
234         if (lexicalForm == null)
235             lexicalForm =
236                 (dtype == null ? value.toString() : dtype.unparse(value));
237         return lexicalForm;
238     }
239
240     /** An RFC 3066 lang tag or "".
241      * These are case insensitive,
242      * mixed case is returned from this method.
243      * Where possible the case should be preserved.
244      * e.g. "en-US" is usually written in mixed case
245      * but is logically equivalent to "en-us" and "EN-US".
246      */

247     public String JavaDoc language() {
248         return lang;
249     }
250
251     /**
252      * Return the value of the literal.
253      * @throws DatatypeFormatException if the eager validation mode is
254      * switched off and this literal is ill-formed.
255      */

256     public Object JavaDoc getValue() throws DatatypeFormatException {
257         if (wellformed) {
258             return value;
259         } else {
260             throw new DatatypeFormatException(
261                 lexicalForm,
262                 dtype,
263                 " in getValue()");
264         }
265     }
266
267     /**
268      * Return the datatype of the Literal. This returns the java object
269      * (an instance of {@link RDFDatatype RDFDatatype}) that represents
270      * the datatype. It returns null for "plain" literals.
271      */

272     public RDFDatatype getDatatype() {
273         return dtype;
274     }
275
276     /**
277      * Return the uri of the datatype of the Literal.
278      * It returns null for "plain" literals.
279      */

280     public String JavaDoc getDatatypeURI() {
281         if (dtype == null)
282             return null;
283         return dtype.getURI();
284     }
285
286     /**
287      * Structural comparision operator. Takes lang, datatype and value into
288      * account. This is not the same as RDF semantic equality which is
289      * dealt with by {@link #sameValueAs}.
290      */

291     public boolean equals(Object JavaDoc other) {
292             if (other == null || !(other instanceof LiteralLabel)) {
293                 return false;
294             }
295             LiteralLabel otherLiteral = (LiteralLabel) other;
296             boolean typeEqual =
297                 (dtype == null
298                     ? otherLiteral.dtype == null
299                     : dtype.equals(otherLiteral.dtype));
300             boolean langEqual =
301                 (dtype == null ? lang.equalsIgnoreCase(otherLiteral.lang) : true);
302             return typeEqual
303                 && langEqual
304                 && getLexicalForm().equals(otherLiteral.getLexicalForm());
305 // if (wellformed) {
306
// return typeEqual && langEqual && value.equals(otherLiteral.value);
307
// } else {
308
// return typeEqual
309
// && langEqual
310
// && lexicalForm.equals(otherLiteral.lexicalForm);
311
// }
312
}
313
314     /**
315      * Test that two nodes are semantically equivalent.
316      * In some cases this may be the sames as equals, in others
317      * equals is stricter. For example, two xsd:int literals with
318      * the same value but different language tag are semantically
319      * equivalent but distinguished by the java equality function
320      * in order to support round tripping.
321      */

322     public boolean sameValueAs(LiteralLabel other) {
323         if (other == null)
324             return false;
325         if (!wellformed || !other.wellformed) {
326             if (!other.wellformed) {
327                 // Need to support this comparison in order for the WG tests on ill formed
328
// literals to be testable using isIsomorphic to
329
return lexicalForm.equals(other.lexicalForm)
330                     && lang.equalsIgnoreCase(other.lang);
331             } else {
332                 return false;
333             }
334         }
335         if (dtype == null) {
336             // Plain literal
337
if (other.dtype == null
338                 || (JenaParameters.enablePlainLiteralSameAsString
339                     && other.dtype.equals(XSDDatatype.XSDstring))) {
340                 return lexicalForm.equals(other.lexicalForm)
341                     && lang.equalsIgnoreCase(other.lang);
342             } else {
343                 return false;
344             }
345         } else {
346             // Typed literal
347
return dtype.isEqual(this, other);
348         }
349     }
350
351     /**
352      * Hash operator. Hashes only on lexical space.
353      * If two instances differ by datatype or significant lang tag then
354      * that is simply a hash collision, does not invalidate the invariants.
355      */

356     public int hashCode() {
357         return (wellformed ? value : getLexicalForm()).hashCode();
358     }
359
360 }
361
362 /*
363     (c) Copyright 2003, 2004, 2005 Hewlett-Packard Development Company, LP
364     All rights reserved.
365
366     Redistribution and use in source and binary forms, with or without
367     modification, are permitted provided that the following conditions
368     are met:
369
370     1. Redistributions of source code must retain the above copyright
371        notice, this list of conditions and the following disclaimer.
372
373     2. Redistributions in binary form must reproduce the above copyright
374        notice, this list of conditions and the following disclaimer in the
375        documentation and/or other materials provided with the distribution.
376
377     3. The name of the author may not be used to endorse or promote products
378        derived from this software without specific prior written permission.
379
380     THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
381     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
382     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
383     IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
384     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
385     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
386     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
387     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
388     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
389     THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
390 */

391
Popular Tags