blob: c44d05a4ecd28670f299e233bda6bed0c46aaae4 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jena.tdb2.store;
import static org.apache.jena.sparql.expr.Expr.CMP_EQUAL;
import static org.apache.jena.tdb2.store.NodeIdType.*;
import org.apache.jena.atlas.lib.BitsLong;
import org.apache.jena.atlas.logging.FmtLog;
import org.apache.jena.dboe.sys.Sys;
import org.apache.jena.graph.Node;
import org.apache.jena.tdb2.sys.SystemTDB;
final
public class NodeId implements Comparable<NodeId>
{
public static final int SIZE = Sys.SizeOfLong;
public static final NodeId NodeIdInvalid = makeSpecial(0xA1);
public static final NodeId NodeDoesNotExist = makeSpecial(0xA3);
public static final NodeId NodeIdAny = makeSpecial(0xA4);
public static final NodeId NodeIdDefined = makeSpecial(0xA5);
public static final NodeId NodeIdUndefined = makeSpecial(0xA6);
private static NodeId makeSpecial(long v) {
// Careful of an initializer loop (create(type, v1, v2) looks at specials).
return NodeIdFactory.createValue(SPECIAL, v);
}
/*package*/ static final boolean enableInlineLiterals = SystemTDB.enableInlineLiterals;
// Internal consistency checks.
private static final boolean CHECKING = true;
// Code search:
// [64 bits]
// Encoding:
// 8 bits type, except PTR which is 0 high bit.
// 24 bits int
// 64 bit value
// The high byte of value1==type as integer value
// In-memory:
// Long:
// type PTR high bit zero, then 31+64 bits of value.
// Inlines:
// type is 8 bits
// value1 is 24 bits
// value2 is 64 bits
// type is a type and is OR'ed into value1 to store.
// Short: 64 bit:
// type PTR high bit zero, then 63 bits of value.
// Inlines:
// value1 is not used.
// value2 is 56 bits
// type is a type and is OR'ed into value2 to store.
final NodeIdType type;
final int value1;
final long value2;
private NodeId(NodeIdType type, int v1, long v2) {
if ( CHECKING ) check(type, v1, v2);
this.type = type;
value1 = v1; // Zero for 64 bit.
value2 = v2;
}
private final void check(NodeIdType type, int v1, long v2) {
if ( type == PTR )
return;
if ( type == SPECIAL )
return;
// 64 bit NodeId.
int x = ( type == XSD_DOUBLE )
? (int)BitsLong.unpack(v2, 62, 64) // High two bits
: (int)BitsLong.unpack(v2, 56, 64); // else
if ( x != 0 )
FmtLog.warn(getClass(), "Type set in long: type=%s value=%016X", type, v2);
}
public boolean isPtr() { return type == PTR; }
// public long getPtrLocation() { return value2; }
// public long getPtrLo() { return value2; }
// public int getPtrHi() { return value1 & 0x00FFFFFF; }
// 64 bit
public long getPtrLocation() { return value2; }
// Long.
// public long getPtrLo() { return value2; }
// public int getPtrHi() { return value1; }
public int getTypeValue() { return type.type(); }
public boolean isInline() {
return isInline(this);
}
public static boolean isInline(NodeId nodeId) {
return NodeIdType.isInline(nodeId.type);
}
public boolean isValue() {
return type != PTR && NodeIdType.isStorable(type);
}
// Migration
public static NodeId inline(Node node) { return NodeIdInline.inline(node); }
public static boolean hasInlineDatatype(Node node) { return NodeIdInline.hasInlineDatatype(node); }
public static Node extract(NodeId nodeId) { return NodeIdInline.extract(nodeId); }
// XXX Later.
// //Static forms only?
// public boolean isAny() { return isAny(this); }
// public boolean isDoesNotExist() { return isDoesNotExist(this); }
// public boolean isDefined() { return isDefined(this); }
// public boolean isUndefined() { return isDefined(this); }
//
public static final boolean isAny(NodeId nodeId) { return nodeId == NodeIdAny || nodeId == null; }
public static final boolean isDoesNotExist(NodeId nodeId) { return nodeId == NodeDoesNotExist; }
// public static boolean isDefined(NodeId nodeId) { return nodeId == NodeIdDefined; }
// public static boolean isUndefined(NodeId nodeId) { return nodeId == NodeIdUndefined; }
/** Create from a long-encoded value */
/*package*/ static NodeId createRaw(NodeIdType type, long value) {
return new NodeId(type, 0, value);
}
/** Create from a (int,long)-encoded value */
/*package*/ static NodeId createRaw(NodeIdType type, int value1, long value2) {
return new NodeId(type, value1, value2);
}
public NodeIdType type() { return type; }
/*package*/ int getValue1() { return value1; }
/*package*/ long getValue2() { return value2; }
@Override
public int hashCode() {
// Ensure all parts have an effect on the 32 bit hash value.
return value1 ^ ((int)value2) ^ ((int)(value2 >> 32));
}
@Override
public boolean equals(Object other) {
if ( this == other ) return true;
if ( other == null ) return false;
if ( !(other instanceof NodeId) ) return false;
NodeId nOther = ((NodeId)other);
return equals(nOther, value1, value2);
}
public boolean equals(NodeId nodeIdOther) {
if ( nodeIdOther == null ) return false;
if ( this == nodeIdOther ) return true;
return equals(nodeIdOther, value1, value2);
}
/*package*/ static boolean equals(NodeId nodeId, int v1, long v2) {
return v2 == nodeId.value2 && v1 == nodeId.value1;
}
@Override
public String toString() {
if ( this == NodeDoesNotExist ) return "[DoesNotExist]";
if ( this == NodeIdAny ) return "[Any]";
if ( this == NodeIdInvalid ) return "[Invalid]";
if ( this == NodeIdDefined ) return "[Defined]";
if ( this == NodeIdUndefined ) return "[Undefined]";
if ( this.isInline() ) {
String displayName = this.type().toString();
return String.format("[%s 0x%014X]", displayName, value2);
}
// [64 bits]
//return String.format("[%08X-%016X]", value1, value2);
return String.format("[0x%16X]", value2);
}
// ---- Encoding special - inlines.
/** Compare - provides an ordering of {@code NodeIds}. */
@Override
public int compareTo(NodeId other) {
return compare(this, other);
}
/** Compare - provides an ordering of {@code NodeIds}. */
public static int compare(NodeId n1, NodeId n2) {
int x = Integer.compare(n1.value1, n2.value1);
if ( x == 0 )
return CMP_EQUAL;
return Long.compare(n1.value2, n2.value2);
}
public final boolean isConcrete() { return isConcrete(this); }
public static final boolean isConcrete(NodeId nodeId) {
return ! NodeIdType.isSpecial(nodeId.type);
}
}