![JAR search and dependency download from the Maven repository](/logo.png)
com.bigdata.rdf.spo.SPOTupleSerializer 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 Jun 23, 2008
*/
package com.bigdata.rdf.spo;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import com.bigdata.btree.DefaultTupleSerializer;
import com.bigdata.btree.IRangeQuery;
import com.bigdata.btree.ITuple;
import com.bigdata.btree.ITupleSerializer;
import com.bigdata.btree.keys.ASCIIKeyBuilderFactory;
import com.bigdata.btree.keys.IKeyBuilder;
import com.bigdata.btree.raba.codec.IRabaCoder;
import com.bigdata.io.ByteArrayBuffer;
import com.bigdata.rdf.internal.IV;
import com.bigdata.rdf.model.StatementEnum;
/**
* (De-)serializes {@link SPO}s for statement indices.
*
* Note: the encoded key for a statement is formed from the 64-bit
* long
term identifier for the subject, predicate, and object
* positions of the statement. Each statement index uses a permutation of those
* term identifiers, e.g., {s,p,o}, {o,s,p}, or {p,o,s}. The {@link SPOKeyOrder}
* identifies the specific permutation for a given index. The keys are fully
* decodable and are NOT stored redundantly in the tuple's value.
*
* The tuple value encodes the {@link StatementEnum}, indicating whether the
* statement is {explicit, inferred, or an axiom}, and optionally the unique
* statement identifier.
*
* Note: While the static methods used to decode an existing key are safe for
* concurrent readers, concurrent readers also form keys using
* {@link #statement2Key(IV, IV, IV)} and therefore require a thread-local
* {@link IKeyBuilder}.
*
* @author Bryan Thompson
* @version $Id$
*/
public class SPOTupleSerializer extends DefaultTupleSerializer {
private static final long serialVersionUID = 2893830958762265104L;
// private static final transient Logger log = Logger.getLogger(SPOTupleSerializer.class);
/**
* The natural order for the index.
*/
private SPOKeyOrder keyOrder;
/**
* If true, explicit SPOs decoded from index tuples will have a sid attached.
*/
private boolean sids;
// /**
// * Used to format the value.
// */
// private final transient ByteArrayBuffer buf = new ByteArrayBuffer(0);
public SPOKeyOrder getKeyOrder() {
return keyOrder;
}
/**
* De-serialization constructor.
*/
public SPOTupleSerializer() {
}
/**
* Create an {@link ITupleSerializer} for the indicated access path.
*
* @param keyOrder
* The access path.
*/
public SPOTupleSerializer(final SPOKeyOrder keyOrder, final boolean sids) {
this(keyOrder, sids, getDefaultLeafKeysCoder(), getDefaultValuesCoder());
}
/**
* Create an {@link ITupleSerializer} for the indicated access path.
*
* @param keyOrder
* The access path.
* @param sids
* If true, attach sids to decoded SPOs where appropriate.
* @param leafKeySer
* @param leafValSer
*/
public SPOTupleSerializer(final SPOKeyOrder keyOrder,
final boolean sids,
final IRabaCoder leafKeySer, final IRabaCoder leafValSer) {
super(new ASCIIKeyBuilderFactory(), leafKeySer, leafValSer);
// if (keyOrder == null)
// throw new IllegalArgumentException();
this.keyOrder = keyOrder;
this.sids = sids;
}
@Override
public byte[] serializeKey(final Object obj) {
if (obj == null)
throw new IllegalArgumentException();
if (obj instanceof SPO)
return serializeKey((SPO) obj);
throw new UnsupportedOperationException();
}
/**
* Forms the statement key.
*
* @param spo
* The statement.
*
* @return The key.
*/
public byte[] serializeKey(final ISPO spo) {
return keyOrder.encodeKey(getKeyBuilder(), spo);
}
/**
* Variant duplicates the behavior of {@link #serializeVal(SPO)} to provide
* support for non-{@link SPO} {@link ISPO}s.
*/
public byte[] serializeVal(final ISPO spo) {
if (spo == null)
throw new IllegalArgumentException();
return serializeVal(//buf,
spo.isOverride(), spo.getUserFlag(), spo.getStatementType());
}
/**
* Encodes the {@link StatementEnum} and the optional statement identifier.
*/
@Override
public byte[] serializeVal(final SPO spo) {
if (spo == null)
throw new IllegalArgumentException();
return serializeVal(//buf,
spo.isOverride(), spo.getUserFlag(), spo.getStatementType());
}
/**
* Return the byte[] that would be written into a statement index for this
* {@link SPO}, including the optional {@link StatementEnum#MASK_OVERRIDE}
* bit. If the statement identifier is non-null then it will be included in
* the returned byte[].
*
* @param override
* true
iff you want the
* {@link StatementEnum#MASK_OVERRIDE} bit set (this is only set
* when serializing values for a remote procedure that will write
* on the index, it is never set in the index itself).
* @param userFlag
* true
iff you want the
* {@link StatementEnum#MASK_USER_FLAG} bit set.
* @param type
* The {@link StatementEnum}.
*
* @return The value that would be written into a statement index for this
* {@link SPO}.
*/
// * @param buf
// * A buffer supplied by the caller. The buffer will be reset
// * before the value is written on the buffer.
public byte[] serializeVal(//final ByteArrayBuffer buf,
final boolean override, final boolean userFlag,
final StatementEnum type) {
// buf.reset();
// optionally set the override and user flag bits on the value.
final byte b = (byte)
(type.code()
| (override ? StatementEnum.MASK_OVERRIDE : 0x0)
| (userFlag ? StatementEnum.MASK_USER_FLAG : 0x0)
);
// buf.putByte(b);
//
// final byte[] a = buf.toByteArray();
//
// assert a.length == 1 : "Expecting one byte, but have "
// + BytesUtil.toString(a);
return RDFValueFactory.getValue(b);
}
public SPO deserialize(final ITuple tuple) {
if (tuple == null)
throw new IllegalArgumentException();
// copy of the key in a reused buffer.
final byte[] key = tuple.getKeyBuffer().array();
final SPO spo = keyOrder.decodeKey(key);
if ((tuple.flags() & IRangeQuery.VALS) == 0) {
// Note: No type or statement identifier information.
return spo;
}
// Decode the StatementEnum, bit flags, and attach a sid.
final ByteArrayBuffer vbuf = tuple.getValueBuffer();
decodeValue(spo, vbuf.array());
return spo;
}
public SPO deserializeKey(final ITuple tuple) {
// just de-serialize the whole tuple.
return deserialize(tuple);
}
/**
* Set the statement type, bit flags, and optional sid based on the tuple
* value.
*/
public ISPO decodeValue(final ISPO spo, final byte[] val) {
final byte code = val[0];
final StatementEnum type = StatementEnum.decode(code);
spo.setStatementType(type);
spo.setOverride(StatementEnum.isOverride(code));
spo.setUserFlag(StatementEnum.isUserFlag(code));
// if (sids) {
//
// // SIDs only valid for triples.
// assert keyOrder.getKeyArity() == 3;
//
// if (spo.isExplicit()) {
//
// spo.setStatementIdentifier(true);
//
// }
//
// }
return spo;
}
/**
* The initial version.
*/
private final static transient byte VERSION0 = 0;
/**
* The new version for the inline sids refactor.
*/
private final static transient byte VERSION1 = 1;
/**
* The current version.
*/
private final static transient byte VERSION = VERSION1;
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
super.readExternal(in);
final byte version = in.readByte();
switch (version) {
case VERSION0:
keyOrder = SPOKeyOrder.valueOf(in.readByte());
/*
* New version is not backwards compatible with old journals that
* used sids.
*/
sids = false;
break;
case VERSION1:
keyOrder = SPOKeyOrder.valueOf(in.readByte());
sids = in.readByte() > 0;
break;
default:
throw new UnsupportedOperationException("Unknown version: "
+ version);
}
}
public void writeExternal(ObjectOutput out) throws IOException {
super.writeExternal(out);
out.writeByte(VERSION);
out.writeByte(keyOrder.index());
out.writeByte(sids ? 1 : 0);
}
}