/** * Copyright (C) 2010-2017 Structr GmbH * * This file is part of Structr <http://structr.org>. * * Structr 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, either version 3 of the * License, or (at your option) any later version. * * Structr 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 Structr. If not, see <http://www.gnu.org/licenses/>. */ package org.structr.neo4j.wrapper; import java.util.HashMap; import java.util.Map; import java.util.Set; import org.neo4j.gis.spatial.rtree.RTreeRelationshipTypes; import org.structr.api.graph.Direction; import org.structr.api.util.Iterables; import org.structr.api.graph.Label; import org.structr.api.graph.Node; import org.structr.api.NotInTransactionException; import org.structr.api.graph.Relationship; import org.structr.api.graph.RelationshipType; import org.structr.neo4j.Neo4jDatabaseService; import org.structr.neo4j.mapper.LabelMapper; import org.structr.neo4j.mapper.RelationshipMapper; /** * */ public class NodeWrapper extends EntityWrapper<org.neo4j.graphdb.Node> implements Node { private final Map<String, Set<Relationship>> relationshipCache = new HashMap<>(); private NodeWrapper(final Neo4jDatabaseService graphDb, final org.neo4j.graphdb.Node node) { super(graphDb, node); } @Override public int hashCode() { return entity.hashCode(); } @Override public boolean equals(final Object other) { if (other instanceof Node) { return other.hashCode() == hashCode(); } return false; } @Override public Relationship createRelationshipTo(final Node endNode, final RelationshipType relationshipType) { try { TransactionWrapper.getCurrentTransaction().registerModified(this); // clear caches of start and end node ((NodeWrapper)endNode).relationshipCache.clear(); relationshipCache.clear(); return RelationshipWrapper.getWrapper(graphDb, entity.createRelationshipTo(unwrap(endNode), unwrap(relationshipType))); } catch (org.neo4j.graphdb.NotInTransactionException t) { throw new NotInTransactionException(t); } } @Override public void addLabel(final Label label) { try { TransactionWrapper.getCurrentTransaction().registerModified(this); entity.addLabel(unwrap(label)); } catch (org.neo4j.graphdb.NotInTransactionException t) { throw new NotInTransactionException(t); } } @Override public void removeLabel(final Label label) { try { TransactionWrapper.getCurrentTransaction().registerModified(this); entity.removeLabel(unwrap(label)); } catch (org.neo4j.graphdb.NotInTransactionException t) { throw new NotInTransactionException(t); } } @Override public Iterable<Label> getLabels() { try { return Iterables.map(new LabelMapper(), entity.getLabels()); } catch (org.neo4j.graphdb.NotInTransactionException t) { throw new NotInTransactionException(t); } } @Override public Iterable<Relationship> getRelationships() { Set<Relationship> allRelationships = relationshipCache.get("*"); if (allRelationships == null) { try { allRelationships = Iterables.toSet(Iterables.map(new RelationshipMapper(graphDb), entity.getRelationships())); relationshipCache.put("*", allRelationships); } catch (org.neo4j.graphdb.NotInTransactionException t) { throw new NotInTransactionException(t); } } return allRelationships; } @Override public Iterable<Relationship> getRelationships(Direction direction) { Set<Relationship> relationships = relationshipCache.get(direction.name()); if (relationships == null) { try { relationships = Iterables.toSet(Iterables.map(new RelationshipMapper(graphDb), entity.getRelationships(unwrap(direction)))); relationshipCache.put(direction.name(), relationships); } catch (org.neo4j.graphdb.NotInTransactionException t) { throw new NotInTransactionException(t); } } return relationships; } @Override public Iterable<Relationship> getRelationships(Direction direction, RelationshipType relationshipType) { Set<Relationship> relationships = relationshipCache.get(direction.name() + relationshipType.name()); if (relationships == null) { try { relationships = Iterables.toSet(Iterables.map(new RelationshipMapper(graphDb), entity.getRelationships(unwrap(direction), unwrap(relationshipType)))); relationshipCache.put(direction.name() + relationshipType.name(), relationships); } catch (org.neo4j.graphdb.NotInTransactionException t) { throw new NotInTransactionException(t); } } return relationships; } @Override public long getId() { return entity.getId(); } @Override public void delete() throws NotInTransactionException { try { TransactionWrapper.getCurrentTransaction().registerModified(this); entity.delete(); deleted = true; graphDb.removeNodeFromCache(getId()); } catch (org.neo4j.graphdb.NotInTransactionException t) { throw new NotInTransactionException(t); } } @Override public boolean isSpatialEntity() { return entity.hasRelationship(RTreeRelationshipTypes.values()); } // ----- helper methods ----- public org.neo4j.graphdb.Node unwrap() { return entity; } @Override public void clearCaches() { super.clearCaches(); relationshipCache.clear(); } // ----- public static methods ----- public static NodeWrapper getWrapper(final Neo4jDatabaseService graphDb, final org.neo4j.graphdb.Node node) { NodeWrapper wrapper = graphDb.getNodeFromCache(node.getId()); if (wrapper == null) { wrapper = new NodeWrapper(graphDb, node); graphDb.storeNodeInCache(wrapper); } return wrapper; } }