package er.neo4jadaptor.ersatz.neo4j; import org.neo4j.graphdb.Direction; import org.neo4j.graphdb.Node; import org.neo4j.graphdb.Relationship; import org.neo4j.graphdb.RelationshipType; import com.webobjects.eoaccess.EOAttribute; import com.webobjects.eoaccess.EOEntity; import com.webobjects.eoaccess.EORelationship; import er.neo4jadaptor.utils.EOUtilities; /** * Ersatz stored on Neo4J node. * * @author Jedrzej Sobanski */ public class Neo4JNodeErsatz extends Neo4JErsatz { public Neo4JNodeErsatz(EOEntity entity, Node pc) { super(entity, pc); } protected Node getNode() { return (Node) getPropertyContainer(); } private boolean isPrimaryKey(EOAttribute att) { EOAttribute pk = EOUtilities.primaryKeyAttribute(entity); return att.name().equals(pk.name()); } private long getPrimaryKey() { return getNode().getId(); } @Override public Object get(EOAttribute att) { if (isPrimaryKey(att)) { long pk = getPrimaryKey(); return Neo4JTranslator.instance.toNeutralValue(pk, att); } else { return super.get(att); } } @Override public void put(EOAttribute att, Object value) { if (isPrimaryKey(att)) { long val = ((Number) value).longValue(); if (val != getPrimaryKey()) { throw new UnsupportedOperationException("Unable to change node's primary key"); } else { // do nothing } } else { super.put(att, value); } } @Override protected Number getForeignKeyValue(EORelationship rel) { RelationshipType relType = Neo4JUtils.getRelationshipType(rel); Relationship r = getNode().getSingleRelationship(relType, Direction.OUTGOING); if (r == null) { return null; } else { long id = r.getEndNode().getId(); EOAttribute dstAtt = EOUtilities.primaryKeyAttribute(rel.destinationEntity()); return EOUtilities.convertToAttributeType(dstAtt, id); } } @Override protected void setForeignKeyValue(EORelationship rel, Number referencedId) { RelationshipType relType = Neo4JUtils.getRelationshipType(rel); Relationship r = getNode().getSingleRelationship(relType, Direction.OUTGOING); if (referencedId == null) { if (r != null) { r.delete(); } } else { Node dstNode = getNode().getGraphDatabase().getNodeById(referencedId.longValue()); if (r != null && r.getEndNode().equals(dstNode)) { return; } if (r != null) { // it exists, but it's invalid r.delete(); } getNode().createRelationshipTo(dstNode, relType); } } /** * Deletes corresponding node and all of its to-one relationships. */ @Override public void delete() { // remove all relationships that this node owns (in relational database these would be simply foreign key values // therefore removing a row would remove it's owned foreign keys. We could simply traverse through all of its // surrounding outgoing relationships and delete them, but it would delete join entity relationships too. for (EORelationship rel : entity.relationships()) { if (! rel.isCompound() && ! rel.isToMany()) { RelationshipType relType = Neo4JUtils.getRelationshipType(rel); Relationship r = getNode().getSingleRelationship(relType, Direction.OUTGOING); if (r != null) { r.delete(); } } } // remove the node itself getNode().delete(); } }