/** * This file is part of d:swarm graph extension. * * d:swarm graph extension 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. * * d:swarm graph extension 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 d:swarm graph extension. If not, see <http://www.gnu.org/licenses/>. */ package org.dswarm.graph.gdm.work; import java.util.HashMap; import java.util.Map; import org.dswarm.graph.DMPGraphException; import org.dswarm.graph.GraphProcessingStatics; import org.dswarm.graph.NodeType; import org.dswarm.graph.json.LiteralNode; import org.dswarm.graph.json.Predicate; import org.dswarm.graph.json.ResourceNode; import org.dswarm.graph.json.Statement; import org.dswarm.graph.model.GraphStatics; import org.dswarm.graph.read.NodeHandler; import org.dswarm.graph.read.RelationshipHandler; import org.dswarm.graph.utils.GraphUtils; import org.neo4j.graphdb.Direction; import org.neo4j.graphdb.DynamicLabel; import org.neo4j.graphdb.GraphDatabaseService; import org.neo4j.graphdb.Label; import org.neo4j.graphdb.Node; import org.neo4j.graphdb.Relationship; import org.neo4j.graphdb.ResourceIterable; import org.neo4j.graphdb.ResourceIterator; import org.neo4j.graphdb.Transaction; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author tgaengler */ public class PropertyGraphSignGDMWorker implements GDMWorker { private static final Logger LOG = LoggerFactory.getLogger(PropertyGraphSignGDMWorker.class); private final NodeHandler nodeHandler; private final NodeHandler startNodeHandler; private final RelationshipHandler relationshipHandler; private final String resourceUri; private final GraphDatabaseService database; private final Map<Long, Statement> currentResourceStatements = new HashMap<>(); public PropertyGraphSignGDMWorker(final String resourceUriArg, final GraphDatabaseService databaseArg) { resourceUri = resourceUriArg; database = databaseArg; nodeHandler = new CBDNodeHandler(); startNodeHandler = new CBDStartNodeHandler(); relationshipHandler = new CBDRelationshipHandler(); } @Override public void work() throws DMPGraphException { try (final Transaction tx = database.beginTx()) { PropertyGraphSignGDMWorker.LOG.debug("start sign GDM TX"); final Label recordClassLabel = GraphProcessingStatics.LEAF_LABEL; final ResourceIterator<Node> leafNodes = database.findNodes(recordClassLabel, GraphProcessingStatics.LEAF_IDENTIFIER, true); if (leafNodes == null) { // no leaves (?) tx.success(); PropertyGraphSignGDMWorker.LOG.debug("finished sign GDM TX successfully"); return; } while (leafNodes.hasNext()) { final Node leafNode = leafNodes.next(); startNodeHandler.handleNode(leafNode); } leafNodes.close(); tx.success(); PropertyGraphSignGDMWorker.LOG.debug("finished sign GDM TX successfully"); } catch (final Exception e) { final String message = "couldn't finished sign GDM TX successfully"; PropertyGraphSignGDMWorker.LOG.error(message, e); throw new DMPGraphException(message); } } private class CBDNodeHandler implements NodeHandler { @Override public void handleNode(final Node node) throws DMPGraphException { if (node.hasProperty(GraphStatics.URI_PROPERTY)) { final Iterable<Relationship> relationships = node.getRelationships(Direction.INCOMING); for (final Relationship relationship : relationships) { relationshipHandler.handleRelationship(relationship); } } } } private class CBDStartNodeHandler implements NodeHandler { @Override public void handleNode(final Node node) throws DMPGraphException { final Iterable<Relationship> relationships = node.getRelationships(Direction.OUTGOING); for (final Relationship relationship : relationships) { relationshipHandler.handleRelationship(relationship); } } } private class CBDRelationshipHandler implements RelationshipHandler { final Map<Long, org.dswarm.graph.json.Node> bnodes = new HashMap<Long, org.dswarm.graph.json.Node>(); final Map<String, ResourceNode> resourceNodes = new HashMap<String, ResourceNode>(); @Override public void handleRelationship(final Relationship rel) throws DMPGraphException { final long statementId = rel.getId(); // object final Node objectNode = rel.getEndNode(); final long objectId = rel.getEndNode().getId(); final NodeType objectNodeType = GraphUtils.determineNodeType(objectNode); final org.dswarm.graph.json.Node objectGDMNode; switch (objectNodeType) { case Resource: case TypeResource: final String objectURI = (String) objectNode.getProperty(GraphStatics.URI_PROPERTY, null); if (objectURI == null) { final String message = "object URI can't be null"; PropertyGraphSignGDMWorker.LOG.error(message); throw new DMPGraphException(message); } objectGDMNode = createResourceFromURI(objectId, objectURI); break; case BNode: case TypeBNode: objectGDMNode = createResourceFromBNode(objectId); break; case Literal: final Node endNode = objectNode; final String object = (String) endNode.getProperty(GraphStatics.VALUE_PROPERTY, null); if (object == null) { final String message = "object value can't be null"; PropertyGraphSignGDMWorker.LOG.error(message); throw new DMPGraphException(message); } objectGDMNode = new LiteralNode(objectId, object); break; default: final String message = "unknown node type " + objectNodeType.getName() + " for object node"; PropertyGraphSignGDMWorker.LOG.error(message); throw new DMPGraphException(message); } if (!objectNodeType.equals(NodeType.Literal)) { // continue traversal with object node nodeHandler.handleNode(rel.getEndNode()); } // predicate final String predicate = rel.getType().name(); final Predicate predicateProperty = new Predicate(predicate); // subject final Node subjectNode = rel.getStartNode(); final NodeType subjectNodeType = GraphUtils.determineNodeType(subjectNode); switch (subjectNodeType) { case Resource: case TypeResource: break; case BNode: case TypeBNode: nodeHandler.handleNode(subjectNode); break; } } private org.dswarm.graph.json.Node createResourceFromBNode(final long bnodeId) { if (!bnodes.containsKey(bnodeId)) { bnodes.put(bnodeId, new org.dswarm.graph.json.Node(bnodeId)); } return bnodes.get(bnodeId); } private ResourceNode createResourceFromURI(final long id, final String uri) { if (!resourceNodes.containsKey(uri)) { resourceNodes.put(uri, new ResourceNode(id, uri)); } return resourceNodes.get(uri); } } }