![JAR search and dependency download from the Maven repository](/logo.png)
com.bigdata.rdf.internal.impl.AbstractIV Maven / Gradle / Ivy
/**
Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016. All rights reserved.
Contact:
SYSTAP, LLC DBA Blazegraph
2501 Calvert ST NW #106
Washington, DC 20008
[email protected]
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* Created on May 3, 2010
*/
package com.bigdata.rdf.internal.impl;
import java.io.IOException;
import java.util.UUID;
import org.openrdf.model.Literal;
import org.openrdf.model.Value;
import com.bigdata.btree.keys.IKeyBuilder;
import com.bigdata.btree.keys.KeyBuilder;
import com.bigdata.rdf.internal.DTE;
import com.bigdata.rdf.internal.DTEExtension;
import com.bigdata.rdf.internal.IExtensionIV;
import com.bigdata.rdf.internal.IInlineUnicode;
import com.bigdata.rdf.internal.IPv4Address;
import com.bigdata.rdf.internal.IV;
import com.bigdata.rdf.internal.IVUnicode;
import com.bigdata.rdf.internal.IVUtility;
import com.bigdata.rdf.internal.InlineLiteralIV;
import com.bigdata.rdf.internal.NotMaterializedException;
import com.bigdata.rdf.internal.VTE;
import com.bigdata.rdf.internal.impl.bnode.FullyInlineUnicodeBNodeIV;
import com.bigdata.rdf.internal.impl.bnode.NumericBNodeIV;
import com.bigdata.rdf.internal.impl.literal.AbstractLiteralIV;
import com.bigdata.rdf.internal.impl.literal.FullyInlineTypedLiteralIV;
import com.bigdata.rdf.internal.impl.literal.LiteralArrayIV;
import com.bigdata.rdf.internal.impl.literal.LiteralExtensionIV;
import com.bigdata.rdf.internal.impl.literal.MockedValueIV;
import com.bigdata.rdf.internal.impl.literal.XSDUnsignedByteIV;
import com.bigdata.rdf.internal.impl.literal.XSDUnsignedIntIV;
import com.bigdata.rdf.internal.impl.literal.XSDUnsignedLongIV;
import com.bigdata.rdf.internal.impl.literal.XSDUnsignedShortIV;
import com.bigdata.rdf.internal.impl.uri.FullyInlineURIIV;
import com.bigdata.rdf.internal.impl.uri.URIExtensionIV;
import com.bigdata.rdf.internal.impl.uri.VocabURIByteIV;
import com.bigdata.rdf.internal.impl.uri.VocabURIShortIV;
import com.bigdata.rdf.lexicon.ITermIndexCodes;
import com.bigdata.rdf.model.BigdataURI;
import com.bigdata.rdf.model.BigdataValue;
/**
* Abstract base class for the inline representation of an RDF Value (the
* representation which is encoded in to the keys of the statement indices).
* This class is responsible for combining the {@link VTE} and the {@link DTE}
* together into the flags byte used as a common prefix for all keys formed from
* RDF Values regardless of whether they are based on an assigned term
* identifier or the inlining of the RDF Value.
*
* Literals which are projected onto primitive data types with a natural order
* (int, float, double, long, etc.) are in total order within that segment of
* the statement index and such segments are partitioned into non-overlapping
* key ranges. Thus key range scans may be used for where the primitive data
* type allows it while filtering on the value must be used where the data type
* does not have a natural ordering. Unicode values do not have a "natural"
* ordering within the statement indices as they are modeled by a reversible
* compression rather than a collation sort key. Therefore, when a high level
* query is constrained such that a variable is known to be of a given data type
* you can use {@link IV} aware operations. Otherwise, the {@link IV}s must be
* materialized and operations performed on {@link BigdataValue}s instead.
*
*
Binary record format
*
* We currently have 14 built-in (or intrinsic) data types (see {@link DTE}).
* Each of those types has a natural order which we can encode and decode from
* the B+Tree key. In general, there is a relatively limited set of interesting
* intrinsic codings, which is important since we will dedicate just 4 bits for
* to code the natural order of the value space, which is just only 16
* distinctions. Given that we have 14 intrinsic data types, that leaves room
* for just two more. One of those bits provides for Unicode data (see
* {@link DTE#XSDString} without a collation order). The other bit provides
* extensibility in the framework itself as described below (see
* {@link DTE#Extension}).
*
* The header byte contains various bit flags which are laid out as follows:
*
*
* [valueType] : 2 bits
* [inline] : 1 bit
* [extension] : 1 bit
* [dataTypeCode] : 4 bits
*
*
*
* - valueType
* - These 2 bits distinguish between URIs, Literals, Blank Nodes, and
* statement identifiers (SIDs). These bits are up front and therefore partition
* the key space first by the RDF Value type. See {@link VTE} which governs
* these bits.
* - inline
* - This bit indicates whether the value is inline or represented by a term
* identifier in the key. This bit is set based on how a given triple store or
* quad store instance is configured. However, because the bit is present in the
* flags, we know how to decode the key without reference to this configuration
* metadata.
* - extension
* - This bit is ignored (and should be zero) unless the RDF Value is a
* Literal with a data type URI which is being inlined. For data type literals,
* this bit is set if the actual data type is not one of those which we handle
* intrinsically but is one of those which has been registered (by the
* application) as an "extended" data type projected onto one of the intrinsic
* data types. Thus, this bit partitions the key space into the intrinsic data
* types and the extended data types.
* When true
, this bit signals that information about the actual
* RDF Value data type will follow (see below). When false
, the
* datatype URI is directly recoverable (for a data type Literal) from the
* dataTypeCode
.
* - dataTypeCode
* - These 4 bits indicate the intrinsic data type for the inline value and
* are ignored (and should be zero) unless a data type Literal is being inlined.
* These bits partition the key space. However, since
extension
bit
* comes first this will not interleave inline values for intrinsic and extended
* data types having the same dataTypeCode
.
* Note: The dataTypeCode
0xf
({@link DTE#Extension)}
* is reserved for extending the set of intrinsic data types. When the code is
* 0xf
the next byte must be considered as well to determine the
* actual intrinsic data type code.
*
*
*
* ---------- byte boundary (IFF DTE == DTE.Extension) ----------
*
*
* If the DTE value was DTE.Extension
was, then the next byte(s) encode
* the DTEExtension (extended intrinsic datatype aka primitive datatype).
*
*
* ---------- byte boundary ----------
*
*
* If extension
was true, then the next byte(s) encode
* information about the source data type URI (its {@link IV}) and the key space
* will be partitioned based on the extended data type URI.
*
*
* ---------- byte boundary ----------
*
*
* The unsigned byte[] representation of the value in the value space for one of
* the intrinsic types. The length of this byte[] may be directly determined
* from the [dataTypeCode] for most data types. However, for xsd:integer and
* xsd:decimal, the length is part of the representation.
*
*
* ---------- byte boundary and end of the record ----------
*
*
* Extensibility
*
* There are three core use cases for extensibility:
*
* - projections
* - A projection takes an application specific data type and maps it onto one
* of the intrinsic data types (int, float, double, etc). Projections provide an
* extensible mechanism which allows an application to benefit from inline
* representation of RDF Values and allows the query optimizer to chose
* key-range scans for application defined data types if they can be projected
* onto intrinsic data types. For example, if you define an application specific
* data type
foo:milliseconds
representing milliseconds since the
* epoch, then the value space of that data type can be projected onto an
* xsd:long
.
* - enumerations
* - An enumeration is an application specific data type having a specific set
* of values. Those values are then projected onto an intrinsic data type such
* as
byte
(256 distinctions) or short
(64k
* distinctions). Enumerations make it possible to inline application specific
* data types while benefiting from XSD validation of those RDF Values. When an
* enumeration is registered, the order in which the members of the enumeration
* are given may optionally specify the natural order of that enumeration. The
* natural order is imposed by projecting the first member of the enumeration
* one ZERO, the second member onto ONE, etc. An enumeration with a natural
* order will be sorted based on that defined order and query optimizations may
* perform key-range scans informed by that natural order.
* Enumerations may be used in cases where you might otherwise use short
* character codes. For example, an enumeration could be defined for the two
* character abbreviations for the 50 US States. That enumeration could be
* mapped onto a single byte.
* - custom indices
* - The best example here is spatial data, which requires literals which
* represent points, rectangles, circles, arcs, clouds, etc to be inserted into
* special spatial indices. Queries must be aware of spatial data and must be
* rewritten to run against the appropriate spatial indices.
* Another use case would be carrying specialized indices for bioinformatics or
* genomics data.
*
* Note: Both projected and enumerated extensible data types MAY map many RDF
* Values onto the same internal value but each internal value MUST map onto a
* single RDF Value (materialization must be deterministic). This can be seen as
* normalization imposed by the database.
*
* @author Bryan Thompson
* @param
* The generic type for the RDF {@link Value} implementation.
* @param
* The generic type for the inline value.
*/
public abstract class AbstractIV
implements IV {
/**
*
*/
private static final long serialVersionUID = 4710700756635103123L;
/**
* Bit flags indicating the kind of RDF Value ({@link VTE}), whether the RDF
* Value is inline, whether this is an extension datatype, and the natural
* order and binary representation of the inline value ({@link See #DTE}).
*
* @see VTE
* @see DTE
*/
protected final byte flags;
/**
* The RDF Value type (URI, BNode, Literal or Statement) and the data type
* are combined and stored in a single byte together with whether the RDF
* value has been inlined (an inline bit) and whether the RDF Value
* is an extended data type (the extension> bit). The vte has 4
* distinctions and is thus TWO (2) bits wide. The dte allows for up
* to 16 distinctions and is SIX (6) bits wide. The bits allocated to these
* sets of distinctions are combined within a single byte as follows:
*
*
* [vviedddd]
*
*
* where v
is a {@link VTE} bit, i
is the
* inline bit, e
is the extension bit, and
* d
is a {@link DTE} bit.
*
* @param vte
* The RDF Value type (URI, BNode, Literal, or Statement).
* @param inline
* true
iff the RDF value will be represented inline
* in the key. When false
, the term identifier of
* the RDF Value will be represented inline instead of its actual
* value.
* @param extension
* When true
, the actual RDF data type URI differs
* from the intrinsic data type (the {@link DTE}) but has been
* projected onto the natural order of the intrinsic data type.
* @param dte
* The internal datatype for the RDF value (termId, xsd:int,
* xsd:long, xsd:float, xsd:double, etc).
*
* @see VTE
* @see DTE
*/
protected AbstractIV(final VTE vte, final boolean inline,
final boolean extension, final DTE dte) {
this(toFlags(vte, inline, extension, dte));
}
/**
* Return the flags
byte that encodes the provided metadata
* about an {@link IV internal value}.
*
* @param vte
* The value type
* @param inline
* true
iff the value is inline (no index access is
* required to materialize the value).
* @param extension
* true
iff the value is an extension data type (a
* user specific data type defined whose underlying data type is
* specified by the {@link DTE}).
* @param dte
* The basic data type.
*
* @return The flags byte that encodes that information.
*/
public static byte toFlags(final VTE vte, final boolean inline,
final boolean extension, final DTE dte) {
// vte << 6 bits (it is in the high 2 bits).
// inline << 5 bits
// extension << 4 bits
// dte is in the low 4 bits.
return (byte) ((//
(((int) vte.v()) << VTE_SHIFT)//
| ((inline ? 1 : 0) << INLINE_SHIFT)//
| ((extension ? 1 : 0) << EXTENSION_SHIFT) //
| (dte.v())//
) & 0xff);
}
/**
* Constructor used when decoding since you already have the flags.
*
* @param flags
* The flags.
*/
protected AbstractIV(final byte flags) {
this.flags = flags;
}
@Override
final public byte flags() {
return flags;
}
/**
* The #of bits (SIX) that the {@link VTE} is shifted to
* the left when encoding it into the {@link #flags}.
*/
private final static int VTE_SHIFT = 6;
/**
* The bit mask that is bit-wise ANDed with the flags in order to reveal the
* {@link VTE}. The high TWO (2) bits of the low byte in the mask are set.
*/
private final static int VTE_MASK = 0xC0;
/**
* The #of bits (FIVE) that the inline flag is shifted to the left
* when encoding it into the {@link #flags}.
*/
private final static int INLINE_SHIFT = 5;
/**
* The bit mask that is bit-wise ANDed with the flags in order to reveal
* the inline
bit.
*/
private final static int INLINE_MASK = 0x20;
/**
* The #of bits (FOUR) that the extension flag is shifted to the left
* when encoding it into the {@link #flags}.
*/
private final static int EXTENSION_SHIFT = 4;
/**
* The bit mask that is bit-wise ANDed with the flags in order to reveal
* the inline
bit.
*/
private final static int EXTENSION_MASK = 0x10;
/**
* The bit mask that is bit-wise ANDed with the flags in order to reveal the
* {@link DTE}. The low FOUR (4) bits in the mask are set.
*/
private final static int DTE_MASK = 0x0f;
/**
* Return true
if the flags byte has its inline
* bit set.
*
* @param flags
* The flags byte.
*/
static public boolean isInline(final byte flags) {
return (flags & INLINE_MASK) != 0;
}
/**
* Return true
if the flags byte has its extension
* bit set.
*
* @param flags
* The flags byte.
*/
static public boolean isExtension(final byte flags) {
return (flags & EXTENSION_MASK) != 0;
}
/**
* Return the {@link VTE} encoding in a flags byte.
*
* Note: {@link VTE#valueOf(byte)} assumes that the VTE bits are in the TWO
* (2) LSB bits of the byte. However, the VTE bits are actually stored in
* the TWO (2) MSB bits of the flags byte. This method is responsible
* for shifting the VTE bits down before invoking {@link VTE#valueOf(byte)}.
*
* @param flags
* A flags byte.
*
* @return The {@link VTE} encoded in the flags byte.
*/
static final public VTE getVTE(final byte flags) {
return VTE.valueOf((byte) (((flags & VTE_MASK) >>> VTE_SHIFT) & 0xff));
}
@Override
final public VTE getVTE() {
return getVTE(flags);
}
/**
* Return the {@link DTE} for this {@link IV}.
*/
@Override
final public DTE getDTE() {
return DTE.valueOf((byte) ((flags & DTE_MASK) & 0xff));
}
@Override
public DTEExtension getDTEX() {
return null;
}
/**
* Helper method decodes a flags byte as found in a statement index key to
* an {@link VTE}.
*
* @param flags
* The flags byte.
*
* @return The {@link VTE}
*/
static final public VTE getInternalValueTypeEnum(
final byte flags) {
return VTE
.valueOf((byte) (((flags & VTE_MASK) >>> VTE_SHIFT) & 0xff));
}
/**
* Helper method decodes a flags byte as found in a statement index key to
* an {@link DTE}.
*
* @param flags
* The flags byte.
* @return The {@link DTE}
*/
static public DTE getDTE(final byte flags) {
return DTE.valueOf((byte) ((flags & DTE_MASK) & 0xff));
}
@Override
final public boolean isLiteral() {
return (flags & VTE_MASK) >>> VTE_SHIFT == VTE.LITERAL.v();
}
@Override
final public boolean isBNode() {
return (flags & VTE_MASK) >>> VTE_SHIFT == VTE.BNODE.v();
}
@Override
final public boolean isURI() {
return (flags & VTE_MASK) >>> VTE_SHIFT == VTE.URI.v();
}
@Override
final public boolean isStatement() {
return (flags & VTE_MASK) >>> VTE_SHIFT == VTE.STATEMENT.v();
}
@Override
final public boolean isResource() {
return isURI() || isBNode();
}
/**
* {@inheritDoc}
*
* This implementation based on the inline
bit flag. This can
* be overridden in many derived classes which have compile time knowledge
* of whether the RDF value is inline or not.
*/
@Override
public boolean isInline() {
return isInline(flags);
}
/**
* {@inheritDoc}
*
* This implementation based on the extension
bit flag. Since
* the extension flag is only used for specific kinds of {@link IV}s, this
* method can be overridden in many derived classes which have compile time
* knowledge of whether the value is an RDF {@link Literal} or not.
*/
@Override
public boolean isExtension() {
return isExtension(flags);
}
/**
* {@inheritDoc}
*
* The default implementation returns false
.
*/
@Override
public boolean isVocabulary() {
return false;
}
/**
* {@inheritDoc}
*
* This implementation returns false
. It is overridden by
* {@link TermId}.
*/
@Override
public boolean isNullIV() {
return false;
}
@Override
public boolean isNumeric() {
return isInline() && getDTE().isNumeric();
}
@Override
final public boolean isSignedNumeric() {
return isInline() && getDTE().isSignedNumeric();
}
@Override
final public boolean isUnsignedNumeric() {
return isInline() && getDTE().isUnsignedNumeric();
}
@Override
final public boolean isFixedNumeric() {
return isInline() && getDTE().isFixedNumeric();
}
@Override
final public boolean isBigNumeric() {
return isInline() && getDTE().isBigNumeric();
}
@Override
final public boolean isFloatingPointNumeric() {
return isInline() && getDTE().isFloatingPointNumeric();
}
/**
* Return a hash code based on the value of the point in the value space.
*
* Note: The {@link IV} implementations typically DO NOT return hash codes
* that are consistent with {@link BigdataValue#hashCode()}. Therefore you
* MUST NOT mix {@link IV}s and {@link BigdataValue}s in the keys of a map
* or the values of a set.
*/
@Override
abstract public int hashCode();
/**
* Return true iff the two {@link IV}s are the same point in the same value
* space. Points in different value spaces (as identified by different
* datatype URIs) are NOT equal even if they have the same value in the
* corresponding primitive data type.
*
* Note: The {@link IV} implementations typically DO NOT compare equals()
* with {@link BigdataValue}s. Therefore you MUST NOT mix {@link IV}s and
* {@link BigdataValue}s in the keys of a map or the values of a set.
*/
@Override
abstract public boolean equals(Object o);
/**
* Imposes an ordering of IVs based on their natural sort ordering in the
* index as unsigned byte[]s.
*/
@Override
@SuppressWarnings("rawtypes")
final public int compareTo(final IV o) {
if (this == o)
return 0;
if (o == null) {
/*
* TODO This is ordering NULLs last. Why is this code even seeing
* null references? Also, note that SPARQL ORDER BY orders the
* nulls first.
*/
return 1;
}
/*
* First order based on the flags byte. This is the first byte of the
* key, so it always partitions the key space and hence provides the
* initial dimension of the total IV ordering.
*
* Note: This comparison will always sort out things such that URIs,
* Literals, BNodes, and SIDs will never compare as equals. It will also
* sort out extension types and datatype literals with a natural
* datatype.
*/
final AbstractIV, ?> t = (AbstractIV, ?>) o;
final int ret = (int) flags - (int) t.flags;
if (ret < 0)
return -1;
if (ret > 0)
return 1;
/*
* At this point we are comparing two IVs of the same intrinsic type.
* These can be compared by directly comparing their primitive values.
* E.g., long to long, int to int, etc. For the IVs which have inline
* Unicode, the comparison should be of the String values per the API
* for the appropriate RDF Value type (Literal, URI, Blank node). The
* String comparison will reflect the code points rather than any
* collation order, but Unicode values are inlined using a code point
* ordering preserving compression so comparing the Strings is the right
* thing to do.
*/
return _compareTo( t );
}
/**
* Compare two {@link IV}s having the same intrinsic datatype.
*/
@SuppressWarnings("rawtypes")
public abstract int _compareTo(IV o);
@Override
public IKeyBuilder encode(final IKeyBuilder keyBuilder) {
// First emit the flags byte.
keyBuilder.appendSigned(flags);
if (!isInline()) {
/*
* The IV is not 100% inline.
*/
if (isExtension()) {
/*
* The IV uses the "extension" bit. We have two different use
* cases here. One is URIs in which we have factored out the
* namespaceIV for the URI. The other is data type literals in
* which we have factored out the datatypeIV for the literal
* (this is only used when the datatype literal can not be
* projected onto one of intrinsic data types).
*
* {namespaceIV,localName} URIs
*
* {datatypeIV,label} literals.
*/
final AbstractNonInlineExtensionIVWithDelegateIV, ?> t = (AbstractNonInlineExtensionIVWithDelegateIV, ?>) this;
// Add the extension byte.
keyBuilder.appendSigned(t.getExtensionByte());
// Add the extension IV.
IVUtility.encode(keyBuilder, t.getExtensionIV());
// Add the delegate IV.
IVUtility.encode(keyBuilder, t.getDelegate());
return keyBuilder;
}
/*
* The RDF Value is represented as a term identifier (i.e., a key
* into the TERMS index).
*
* Note: This is handled by TermIV#encode() so we will never get to
* this point in the code.
*/
// keyBuilder.append(getTermId());
// return keyBuilder;
throw new AssertionError(getClass().getName() + ":" + toString());
}
if (isURI()) {
/*
* Handle a fully inline URI.
*/
if(isExtension()) {
@SuppressWarnings("unchecked")
final URIExtensionIV extension = (URIExtensionIV) this;
// The namespaceIV (a Vocabulary item).
IVUtility.encode(keyBuilder, extension.getExtensionIV());
// The inline localName (any inline literal data).
IVUtility.encode(keyBuilder, extension.getLocalNameIV());
return keyBuilder;
}
switch (getDTE()) {
case XSDByte: {
keyBuilder.append(((VocabURIByteIV>) this).byteValue());
break;
}
case XSDShort: {
keyBuilder.append(((VocabURIShortIV>) this).getInlineValue());
break;
}
case XSDString: {
final FullyInlineURIIV> iv = (FullyInlineURIIV>) this;
final String uriString = iv.getInlineValue().stringValue();
final byte[] b = IVUnicode.encode1(uriString);
keyBuilder.append(b);
iv.setByteLength(1/* flags */+ b.length);
break;
}
default:
throw new UnsupportedOperationException("dte="+getDTE());
}
return keyBuilder;
}
if (isBNode()) {
/*
* Handle inline blank nodes.
*/
switch (getDTE()) {
case XSDInt:
keyBuilder.append(((NumericBNodeIV>) this).intValue());
break;
case UUID:
keyBuilder.append((UUID) getInlineValue());
break;
case XSDString: {
final FullyInlineUnicodeBNodeIV> iv = (FullyInlineUnicodeBNodeIV>) this;
final byte[] b = IVUnicode.encode1(iv.getInlineValue());
keyBuilder.append(b);
iv.setByteLength(1/* flags */+ b.length);
break;
}
default:
throw new UnsupportedOperationException("dte="+getDTE());
}
// done.
return keyBuilder;
}
// The datatype.
final DTE dte = getDTE();
final DTEExtension dtex;
if (dte == DTE.Extension) {
/*
* @see BLZG-1507 (Implement support for DTE extension types for
* URIs)
*
* @see BLZG-1595 ( DTEExtension for compressed timestamp)
*/
dtex = getDTEX();
keyBuilder.append(dtex.v());
} else
dtex = null;
/*
* We are dealing with some kind of inlined Literal. It may either be a
* natural datatype [int, long, float, etc.] or an IExtension projected
* onto a natural datatype.
*
* Note: An optimized xsd:string handled by XSDStringExtension goes
* through this code path.
*/
assert getVTE() == VTE.LITERAL;
if (isExtension()) {
/*
* Append the extension type for a datatype literal into the key.
*
* Note: Non-inline extensions were handled above!
*/
final IExtensionIV extension = (IExtensionIV) this;
IVUtility.encode(keyBuilder, extension.getExtensionIV());
}
/*
* Append the natural value type representation.
*
* Note: We have to handle the unsigned byte, short, int and long values
* specially to get the correct total key order.
*
* Note: When we generate the key from an IV with Unicode data we cache
* the byteLength! This avoids having to compute it again since we know
* it at the time that we encode the IV.
*/
final AbstractLiteralIV, ?> t = isExtension() //
? ((LiteralExtensionIV>) this).getDelegate()//
: (AbstractLiteralIV, ?>) this;
switch (dte) {
case XSDBoolean:
keyBuilder.appendSigned((byte) (t.booleanValue() ? 1 : 0));
break;
case XSDByte:
keyBuilder.appendSigned(t.byteValue());
break;
case XSDShort:
keyBuilder.append(t.shortValue());
break;
case XSDInt:
keyBuilder.append(t.intValue());
break;
case XSDLong:
keyBuilder.append(t.longValue());
break;
case XSDFloat:
keyBuilder.append(t.floatValue());
break;
case XSDDouble:
keyBuilder.append(t.doubleValue());
break;
case XSDInteger:
keyBuilder.append(t.integerValue());
break;
case XSDDecimal:
keyBuilder.append(t.decimalValue());
break;
case UUID:
keyBuilder.append((UUID) t.getInlineValue());
break;
case XSDUnsignedByte:
keyBuilder.appendSigned(((XSDUnsignedByteIV>) t).rawValue());
break;
case XSDUnsignedShort:
keyBuilder.append(((XSDUnsignedShortIV>) t).rawValue());
break;
case XSDUnsignedInt:
keyBuilder.append(((XSDUnsignedIntIV>) t).rawValue());
break;
case XSDUnsignedLong:
keyBuilder.append(((XSDUnsignedLongIV>) t).rawValue());
break;
case XSDString: {
if (this instanceof FullyInlineTypedLiteralIV>) {
/*
* A fully inline Literal
*/
final FullyInlineTypedLiteralIV> iv = (FullyInlineTypedLiteralIV>) this;
// notice the current key length.
final int pos0 = keyBuilder.len();
// append the term code.
keyBuilder.append((byte) iv.getTermCode());
// handle language code or datatype URI.
if (iv.getLanguage() != null) {
// language code
keyBuilder.append(IVUnicode.encode1(iv.getLanguage()));
} else if (iv.getDatatype() != null) {
// datatype URI
keyBuilder.append(IVUnicode.encode1(iv.getDatatype()
.stringValue()));
}
// the literal's label
keyBuilder.append(IVUnicode.encode1(iv.getLabel()));
// figure the final length of the key.
final int len = keyBuilder.len() - pos0;
// cache the byteLength on the IV.
iv.setByteLength(1/* flags */+ len);
return keyBuilder;
}
/*
* Optimized code path for xsd:string when using in combination with
* ExternalIV.
*/
// append the term code (note: plain literal!!!)
keyBuilder.append((byte) ITermIndexCodes.TERM_CODE_LIT);
final byte[] b = IVUnicode.encode1((String) t.getInlineValue());
keyBuilder.append(b);
((IInlineUnicode) t)
.setByteLength(1/* flags */+ 1/* termCode */+ b.length);
return keyBuilder;
}
case Extension: {
switch(dtex) {
case IPV4: {
// Append the IPv4Address
keyBuilder.append(((IPv4Address) t.getInlineValue()).getBytes());
break;
}
case PACKED_LONG: {
// Third, emit the packed long's byte value
((KeyBuilder) keyBuilder).pack(((Long) t.getInlineValue()).longValue());
break;
}
case MOCKED_IV: {
final IV,?> iv = ((MockedValueIV) t).getIV();
iv.encode(keyBuilder);
break;
}
case ARRAY: {
final InlineLiteralIV[] ivs = ((LiteralArrayIV) t).getIVs();
/*
* Append the length of the array as a byte. InlineLiteralIV
* only supports arrays of length (1...256).
*/
// int(1...256) --> byte(0...255)
final byte len = (byte) (ivs.length-1);
keyBuilder.append(len);
/*
* Then append the ivs one by one.
*/
for (InlineLiteralIV,?> iv : ivs) {
iv.encode(keyBuilder);
}
break;
}
default:
throw new UnsupportedOperationException("DTExtension=" + dtex);
}
break;
}
default:
throw new AssertionError(toString());
}
return keyBuilder;
}
// public IV getExtensionIV() {
// return null;
// }
// public String bnodeId() {
//
// throw new UnsupportedOperationException();
//
// }
/*
* RDF Value cache.
*/
/**
* Value cache (transient, but overridden serialization is used to send this
* anyway for various purposes).
*
* @see https://sourceforge.net/apps/trac/bigdata/ticket/337
*/
private volatile transient V cache = null;
@Override
final public V getValue() {
final V v = cache;
if (v == null)
throw new NotMaterializedException(toString());
return v;
}
@Override
final public V setValue(final V v) {
return (this.cache = v);
}
/**
* Return the cached {@link BigdataValue} or -null
if it is not
* cached.
*/
protected final V getValueCache() {
return cache;
}
// final public void dropValue() {
//
// this.cache = null;
//
// }
@Override
final public boolean hasValue() {
return cache != null;
}
/*
* Serialization.
*/
/**
* Override default serialization to send the cached {@link BigdataValue}.
*
* @see https://sourceforge.net/apps/trac/bigdata/ticket/337
*/
private void writeObject(java.io.ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
out.writeObject(getValueCache());
}
/**
* Override default serialization to recover the cached {@link BigdataValue}
* .
*/
@SuppressWarnings("unchecked")
private void readObject(java.io.ObjectInputStream in) throws IOException,
ClassNotFoundException {
in.defaultReadObject();
final V v = (V) in.readObject();
if (v != null) {
// set the value cache.
setValue(v);
}
}
}