package com.bigdata.rdf.internal.impl.uri; import org.openrdf.model.URI; import org.openrdf.model.impl.URIImpl; import com.bigdata.rdf.internal.ILexiconConfiguration; import com.bigdata.rdf.internal.IV; import com.bigdata.rdf.internal.VTE; import com.bigdata.rdf.internal.impl.AbstractInlineExtensionIV; import com.bigdata.rdf.internal.impl.AbstractInlineIV; import com.bigdata.rdf.internal.impl.literal.AbstractLiteralIV; import com.bigdata.rdf.lexicon.LexiconRelation; import com.bigdata.rdf.model.BigdataLiteral; import com.bigdata.rdf.model.BigdataURI; import com.bigdata.rdf.model.BigdataValueFactory; import com.bigdata.rdf.vocab.Vocabulary; /** * Class provides support for fully inline {@link URI}s for which a * {@link Vocabulary} item was registered for the {@link URI} <em>namespace</em> * . An {@link URIExtensionIV} <strong>always</strong> has the <em>inline</em> * and <em>extension</em> bits set. {@link URIExtensionIV} are fully inline * since the <code>namespace</code> can be materialized from the * {@link Vocabulary} and the <code>localName</code> is directly inline. * * @author <a href="mailto:thompsonbry@users.sourceforge.net">Bryan Thompson</a> * @param <V> */ public class URIExtensionIV<V extends BigdataURI> extends AbstractInlineExtensionIV<V, Object> implements URI { /** * */ private static final long serialVersionUID = 8267554196603121194L; /** * The namespace. */ private final AbstractInlineIV<BigdataURI, ?> namespaceIV; /** * The localName. */ private final AbstractLiteralIV<BigdataLiteral, ?> delegateIV; /** * {@inheritDoc} * <p> * Note: The extensionIV and delegateIV are NOT cloned. The rationale is * that we are only cloning to break the hard reference from the {@link IV} * to to cached value. If that needs to be done for the extensionIV and * delegateIV, then it will be done separately for those objects when they * are inserted into the termsCache. */ @Override public IV<V, Object> clone(final boolean clearCache) { final URIExtensionIV<V> tmp = new URIExtensionIV<V>(delegateIV, namespaceIV); if (!clearCache) { tmp.setValue(getValueCache()); } return tmp; } /** * * @param delegateIV * The {@link IV} which represents the localName. * @param namespaceIV * The {@link IV} which represents the namespace. This MUST be a * fully inline {@link IV} declared by the {@link Vocabulary}. */ @SuppressWarnings("unchecked") public URIExtensionIV( final AbstractLiteralIV<BigdataLiteral, ?> delegateIV, final IV<?,?> namespaceIV) { super(VTE.URI, true/* extension */, delegateIV.getDTE()); if (namespaceIV == null) throw new IllegalArgumentException(); if (!namespaceIV.isInline()) // must be fully inline. throw new IllegalArgumentException(); if (!delegateIV.isInline()) // must be fully inline. throw new IllegalArgumentException(); this.delegateIV = delegateIV; this.namespaceIV = (AbstractInlineIV<BigdataURI, ?>) namespaceIV; } /** * The namespace IV does need materialization, although it will not need * to go to the index to get the value (it just needs access to the lexicon's * vocabulary). */ @Override public boolean needsMaterialization() { return delegateIV.needsMaterialization() || namespaceIV.needsMaterialization(); } public AbstractLiteralIV<BigdataLiteral, ?> getLocalNameIV() { return delegateIV; } @Override public Object getInlineValue() { return new URIImpl(stringValue()); } /** * Extension IV is the <code>namespace</code> for the {@link URI}. */ @Override public IV<BigdataURI, ?> getExtensionIV() { return namespaceIV; } /** * */ public int hashCode() {// TODO Inspect distribution. return namespaceIV.hashCode() ^ delegateIV.hashCode(); } @Override public boolean equals(final Object o) { if (this == o) return true; if (o instanceof URIExtensionIV<?>) { return this.delegateIV.equals(((URIExtensionIV<?>) o).delegateIV) && this.namespaceIV.equals(((URIExtensionIV<?>) o).namespaceIV); } return false; } // See BLZG-1591 @Override public String toString() { if (this.namespaceIV != null && this.delegateIV != null ) return this.namespaceIV.toString() + ":" + this.delegateIV.toString(); else return getValue().stringValue(); } //////////////////////// // OpenRDF URI methods //////////////////////// @Override public String stringValue() { return toString(); // See BLZG-1591 } @Override public String getNamespace() {// See BLZG-1591 if(this.namespaceIV != null) return namespaceIV.getValue().stringValue(); return getValue().getNamespace(); } @Override public String getLocalName() {// See BLZG-1591 if(this.delegateIV!=null) return delegateIV.getInlineValue().toString(); return getValue().getLocalName(); } // // End of OpenRDF URI methods. // @Override @SuppressWarnings("rawtypes") public int _compareTo(final IV o) { int ret = namespaceIV.compareTo(((URIExtensionIV<?>) o).namespaceIV); if (ret != 0) return ret; return delegateIV._compareTo(((URIExtensionIV<?>) o).delegateIV); } /** * Return the length of the namespace IV plus the length of the localName * IV. */ @Override public int byteLength() { return 1/* flags */+ namespaceIV.byteLength() + delegateIV.byteLength(); } /** * Defer to the {@link ILexiconConfiguration} which has specific knowledge * of how to generate an RDF value from this general purpose extension IV. * <p> * {@inheritDoc} */ @Override @SuppressWarnings( "unchecked" ) public V asValue(final LexiconRelation lex) { V v = getValueCache(); if (v == null) { final BigdataValueFactory f = lex.getValueFactory(); // final ILexiconConfiguration config = lex.getLexiconConfiguration(); // // v = setValue((V) config.asValueFromVocab(this)); final URI namespace = namespaceIV.asValue(lex); final String localName = lex.getLexiconConfiguration() .getInlineURILocalNameFromDelegate(namespace, delegateIV); v = setValue((V) f.createURI(namespace.stringValue(), localName)); v.setIV(this); } return v; } }