package xdi2.core.impl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import xdi2.core.ContextNode; import xdi2.core.Graph; import xdi2.core.LiteralNode; import xdi2.core.Node; import xdi2.core.Relation; import xdi2.core.Statement.RelationStatement; import xdi2.core.impl.AbstractStatement.AbstractRelationStatement; import xdi2.core.syntax.XDIAddress; public abstract class AbstractRelation implements Relation { private static final long serialVersionUID = -9055773010138710261L; private static final Logger log = LoggerFactory.getLogger(AbstractRelation.class); private ContextNode contextNode; public AbstractRelation(ContextNode contextNode) { if (contextNode == null) throw new NullPointerException(); this.contextNode = contextNode; } @Override public Graph getGraph() { return this.getContextNode().getGraph(); } @Override public ContextNode getContextNode() { return this.contextNode; } @Override public synchronized void delete() { this.getContextNode().delRelation(this.getXDIAddress(), this.getTargetXDIAddress()); } @Override public Node follow() { XDIAddress targetXDIAddress = this.getTargetXDIAddress(); ContextNode targetContextNode = (ContextNode) this.getGraph().getDeepNode(targetXDIAddress.getContextNodeXDIAddress(), false); if (targetContextNode == null) { if (log.isWarnEnabled()) log.warn("Relation points to non-existent target node " + targetXDIAddress); return null; } if (targetXDIAddress.isLiteralNodeXDIAddress()) { return targetContextNode.getLiteralNode(); } else { return targetContextNode; } } @Override public ContextNode followContextNode() { Node targetNode = this.follow(); return targetNode instanceof ContextNode ? (ContextNode) targetNode : null; } @Override public LiteralNode followLiteralNode() { Node targetNode = this.follow(); return targetNode instanceof LiteralNode ? (LiteralNode) targetNode : null; } /* * Methods related to statements */ @Override public RelationStatement getStatement() { return this.statement; } /* * Object methods */ @Override public String toString() { return this.getStatement().toString(); } @Override public boolean equals(Object object) { if (object == null || ! (object instanceof Relation)) return false; if (object == this) return true; Relation other = (Relation) object; // two relations are equal if their context nodes, addresses, and target node addresses are equal return this.getContextNode().equals(other.getContextNode()) && this.getXDIAddress().equals(other.getXDIAddress()) && this.getTargetXDIAddress().equals(other.getTargetXDIAddress()); } @Override public int hashCode() { int hashCode = 1; hashCode = (hashCode * 31) + this.getContextNode().hashCode(); hashCode = (hashCode * 31) + this.getXDIAddress().hashCode(); hashCode = (hashCode * 31) + this.getTargetXDIAddress().hashCode(); return hashCode; } @Override public int compareTo(Relation other) { if (other == null || other == this) return 0; int compare; if ((compare = this.getContextNode().compareTo(other.getContextNode())) != 0) return compare; if ((compare = this.getXDIAddress().compareTo(other.getXDIAddress())) != 0) return compare; if ((compare = this.getTargetXDIAddress().compareTo(other.getTargetXDIAddress())) != 0) return compare; return 0; } /** * A statement for this relation. */ private final RelationStatement statement = new AbstractRelationStatement() { private static final long serialVersionUID = 1937380243537401799L; @Override public XDIAddress getSubject() { return AbstractRelation.this.getContextNode().getXDIAddress(); } @Override public XDIAddress getPredicate() { return AbstractRelation.this.getXDIAddress(); } @Override public XDIAddress getObject() { return AbstractRelation.this.getTargetXDIAddress(); } @Override public Graph getGraph() { return AbstractRelation.this.getGraph(); } @Override public void delete() { AbstractRelation.this.delete(); } @Override public Relation getRelation() { return AbstractRelation.this; } }; }