/******************************************************************************* * Copyright (c) 2004, 2007 IBM Corporation and Cambridge Semantics Incorporated. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * File: $Source: /cvsroot/slrp/glitter/com.ibm.adtech.glitter/src/com/ibm/adtech/glitter/rdf/TypedLiteral.java,v $ * Created by: Lee Feigenbaum (<a href="mailto:feigenbl@us.ibm.com">feigenbl@us.ibm.com</a>) * Created on: 10/23/06 * Revision: $Id: TypedLiteral.java 164 2007-07-31 14:11:09Z mroy $ * * Contributors: IBM Corporation - initial API and implementation * Cambridge Semantics Incorporated - Fork to Anzo *******************************************************************************/ package org.openanzo.rdf; import java.io.ObjectStreamException; import java.lang.ref.SoftReference; import java.text.MessageFormat; import javax.xml.datatype.XMLGregorianCalendar; import org.openanzo.exceptions.LogUtils; import org.openanzo.rdf.datatype.TypedValueMapper; import org.openanzo.rdf.utils.Pair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * An implementation of {@link TypedLiteral} that maintains the typed literal's lexical form, datatype, and native value (as a native Java object). * * @author lee <lee@cambridgesemantics.com> * */ public class MemTypedLiteral extends MemLiteral implements TypedLiteral { private static final long serialVersionUID = 6800687957527699783L; private static final Logger log = LoggerFactory.getLogger(MemTypedLiteral.class); private transient Object value; private final URI datatype; private final String lexical; /** Use a SoftReference to cache toString value for this literal. SoftReference will be GCed before an out of mem error */ private transient SoftReference<String> toStringValue; /** Constant for TRUE */ public static final TypedLiteral TRUE = MemTypedLiteral.create(true); /** Constant for FALSE */ public static final TypedLiteral FALSE = MemTypedLiteral.create(false); /** * Create a typed literal * * @param value * value of literal * @param datatype * datatype for literal * @return a typed literal */ public static TypedLiteral create(String value, URI datatype) { return MemValueFactory.defaultFactory.createLiteral(value, datatype); } /** * Create a typed literal for the given native object * * @param nativeObject * native object to convert * @return a typed literal for the given native object */ public static TypedLiteral create(Object nativeObject) { return MemValueFactory.defaultFactory.createTypedLiteral(nativeObject); } protected Object readResolve() throws ObjectStreamException { return create(lexical, datatype); } /** * Create a typed literal from a lexical form and datatype. * * @param value * The lexical form of the literal. * @param datatype * The typed literal's datatype. */ protected MemTypedLiteral(String value, URI datatype) { this.lexical = replace(value); this.datatype = datatype; } public Object getNativeValue() { if (this.value == null) { try { this.value = TypedValueMapper.getNativeObject(lexical, datatype); } catch (IllegalArgumentException e) { log.warn(LogUtils.GLITTER_MARKER, "Exception constructing native value for typed literal: {}", e); throw e; } } if (this.value instanceof XMLGregorianCalendar) { return ((XMLGregorianCalendar) this.value).clone(); } else if (this.value instanceof byte[]) { return ((byte[]) this.value).clone(); } else { return this.value; } } public URI getDatatypeURI() { return this.datatype; } public String getLabel() { String s = null; // SPARQL prefers that we remember the lexical form we were given originally if (this.lexical != null) s = this.lexical; else if (this.value != null) { Pair<String, URI> val = TypedValueMapper.getLexicalValue(this.value); if (val != null) { s = val.first; } } return s; } private static final String typeFormat = "\"\"\"{0}\"\"\"^^<{1}>"; // TODO - handle escaping correctly @Override public String toString() { String string = (toStringValue != null) ? toStringValue.get() : null; if (string == null) { string = MessageFormat.format(typeFormat, getLabel(), getDatatypeURI().toString()); toStringValue = new SoftReference<String>(string); } return string; } public int compareTo(TriplePatternComponent o) { return toString().compareTo(o.toString()); } @Override public boolean equals(Object other) { if (this == other) { return true; } else if (!(other instanceof TypedLiteral)) { return false; } else if (other instanceof MemTypedLiteral) { return ((this.lexical == null && ((MemTypedLiteral) other).lexical == null) || (this.lexical != null && ((MemTypedLiteral) other).lexical != null && this.lexical.equals(((MemTypedLiteral) other).lexical))) && ((this.datatype == null && ((MemTypedLiteral) other).datatype == null) || (this.datatype != null && ((MemTypedLiteral) other).datatype != null && this.datatype.equals(((MemTypedLiteral) other).datatype))); } else { return super.equals(other); } } }