package com.ontology2.bakemono.jena;
import com.hp.hpl.jena.datatypes.TypeMapper;
import com.hp.hpl.jena.graph.Node;
import org.apache.hadoop.io.WritableComparable;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import static com.google.common.base.Charsets.UTF_8;
import static com.google.common.collect.ComparisonChain.start;
//
// Some apologies here. The WritableNode does not support Blank nodes or Anonymous
// Nodes since these are things unlikely to show up in a triple file.
//
public class WritableNode implements WritableComparable {
Node innerNode;
final static int URI=0;
final static int STRING=1;
final static int GENERAL_LITERAL=2;
private TypeMapper typeLookup=TypeMapper.getInstance();
// try to write this when this is null and you're in trouble, this is only
// intended for use if you wish to read
public WritableNode() {
innerNode=null;
}
public WritableNode(Node n) {
innerNode=n;
}
@Override
public void write(DataOutput out) throws IOException {
if(innerNode.isURI()) {
out.writeByte(URI);
writeBigUTF8(out,innerNode.getURI());
return;
}
String dt=innerNode.getLiteralDatatypeURI();
if(dt!=null) {
out.writeByte(GENERAL_LITERAL);
writeBigUTF8(out,innerNode.getLiteralLexicalForm());
writeBigUTF8(out,dt);
return;
}
out.writeByte(STRING);
writeBigUTF8(out,innerNode.getLiteralLexicalForm());
writeBigUTF8(out,innerNode.getLiteralLanguage());
return;
}
int nodeType() {
return innerNode.isURI() ? URI
: innerNode.getLiteralDatatypeURI()!=null ? GENERAL_LITERAL
: STRING;
}
@Override
public void readFields(DataInput in) throws IOException {
int type=in.readByte();
if(type==URI) {
String uri=readBigUTF8(in);
innerNode=Node.createURI(uri);
} else if (type==GENERAL_LITERAL) {
String lexicalForm=readBigUTF8(in);
String dt=readBigUTF8(in);
innerNode=Node.createLiteral(lexicalForm,typeLookup.getSafeTypeByName(dt));
} else if (type==STRING) {
String lexicalForm=readBigUTF8(in);
String language=readBigUTF8(in);
innerNode=Node.createLiteral(lexicalForm,language,false);
}
}
public Node getNode() {
return innerNode;
}
@Override
public boolean equals(Object obj) {
return (obj instanceof WritableNode)
? ((WritableNode) obj).getNode().equals(getNode())
: false;
}
@Override
public int hashCode() {
return getNode().hashCode();
}
//
// this comparsion function may not conform with any particular standard
//
@Override
public int compareTo(Object o) {
if(o==null && !(o instanceof WritableNode))
return -1;
WritableNode that=(WritableNode) o;
if (that.nodeType()>this.nodeType()) return -1;
if (that.nodeType()<this.nodeType()) return 1;
switch(this.nodeType()) {
case URI: return innerNode.getURI().compareTo(that.innerNode.getURI());
case GENERAL_LITERAL: return start()
.compare(this.getNode().getLiteralLexicalForm(), that.getNode().getLiteralLexicalForm())
.compare(this.getNode().getLiteralDatatypeURI(), that.getNode().getLiteralDatatypeURI())
.result();
default: return start()
.compare(this.getNode().getLiteralLexicalForm(), that.getNode().getLiteralLexicalForm())
.compare(this.getNode().getLiteralLanguage(), that.getNode().getLiteralLanguage())
.result();
}
}
public static void writeBigUTF8(DataOutput out,String that) throws IOException {
byte[] utf8=that.getBytes(UTF_8);
out.writeInt(utf8.length);
out.write(utf8);
}
public static String readBigUTF8(DataInput in) throws IOException {
byte[] utf8=new byte[in.readInt()];
in.readFully(utf8);
return new String(utf8,UTF_8);
}
}