/** * 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.read; import java.io.OutputStream; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Optional; import java.util.Set; import com.google.common.collect.Iterators; import org.neo4j.graphdb.DynamicLabel; import org.neo4j.graphdb.GraphDatabaseService; import org.neo4j.graphdb.Label; import org.neo4j.graphdb.Node; import org.neo4j.graphdb.ResourceIterator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.dswarm.graph.DMPGraphException; import org.dswarm.graph.index.NamespaceIndex; import org.dswarm.graph.json.Resource; import org.dswarm.graph.json.Statement; import org.dswarm.graph.json.stream.ModelBuilder; import org.dswarm.graph.model.GraphStatics; import org.dswarm.graph.tx.TransactionHandler; /** * @author tgaengler */ public class PropertyGraphGDMModelReader extends PropertyGraphGDMReader implements GDMModelReader { private static final Logger LOG = LoggerFactory.getLogger(PropertyGraphGDMModelReader.class); private static final String TYPE = "GDM model"; private final String recordClassUri; private Optional<Integer> optionalAtMost; private long size = 0; private long readResources = 0; private ModelBuilder modelBuilder; public PropertyGraphGDMModelReader(final String recordClassUriArg, final String dataModelUriArg, final Optional<Integer> optionalVersionArg, final Optional<Integer> optionalAtMostArg, final GraphDatabaseService databaseArg, final TransactionHandler tx, final NamespaceIndex namespaceIndexArg) throws DMPGraphException { super(dataModelUriArg, optionalVersionArg, databaseArg, tx, namespaceIndexArg, TYPE); recordClassUri = recordClassUriArg; optionalAtMost = optionalAtMostArg; } @Override public Optional<ModelBuilder> read(final OutputStream outputStream) throws DMPGraphException { readResources = 0; tx.ensureRunningTx(); ResourceIterator<Node> recordNodesIter = null; try { final Label recordClassLabel = DynamicLabel.label(recordClassUri); PropertyGraphGDMModelReader.LOG .debug("try to read resources for class '{}' in data model '{}' with version '{}'", recordClassLabel, prefixedDataModelUri, version); recordNodesIter = database.findNodes(recordClassLabel, GraphStatics.DATA_MODEL_PROPERTY, prefixedDataModelUri); if (recordNodesIter == null) { tx.succeedTx(); PropertyGraphGDMModelReader.LOG .debug("there are no root nodes for '{}' in data model '{}' with version '{}'; finished read {} TX successfully", recordClassLabel, prefixedDataModelUri, version, type); return Optional.empty(); } if (!recordNodesIter.hasNext()) { recordNodesIter.close(); tx.succeedTx(); PropertyGraphGDMModelReader.LOG .debug("there are no root nodes for '{}' in data model '{}' with version '{}'; finished read {} TX successfully", recordClassLabel, prefixedDataModelUri, version, type); return Optional.empty(); } modelBuilder = new ModelBuilder(outputStream); size = 0; final Iterator<Node> nodeIterator; if (optionalAtMost.isPresent()) { nodeIterator = Iterators.limit(recordNodesIter, optionalAtMost.get()); } else { nodeIterator = recordNodesIter; } while (nodeIterator.hasNext()) { final Node recordNode = nodeIterator.next(); final String resourceUri = (String) recordNode.getProperty(GraphStatics.URI_PROPERTY, null); if (resourceUri == null) { LOG.debug("there is no resource URI at record node '{}'", recordNode.getId()); continue; } final String fullResourceURI = namespaceIndex.createFullURI(resourceUri); currentResource = new Resource(fullResourceURI); startNodeHandler.handleNode(recordNode); if (!currentResourceStatements.isEmpty()) { final Set<Statement> statements = new LinkedHashSet<>(); for (List<Statement> statementList : currentResourceStatements.values()) { statements.addAll(statementList); } currentResource.setStatements(statements); } final int resourceStatementSize = currentResource.size(); if (resourceStatementSize > 0) { size += resourceStatementSize; modelBuilder.addResource(currentResource); readResources++; } else { LOG.debug("couldn't find any statement for resource '{}' ('{}') in data model '{}' with version '{}'", currentResource.getUri(), resourceUri, prefixedDataModelUri, version); } currentResourceStatements.clear(); } recordNodesIter.close(); tx.succeedTx(); PropertyGraphGDMModelReader.LOG.debug("finished read {} TX successfully", type); } catch (final Exception e) { PropertyGraphGDMModelReader.LOG.error("couldn't finished read {} TX successfully", type, e); if (recordNodesIter != null) { recordNodesIter.close(); } tx.failTx(); } return Optional.of(modelBuilder); } @Override public long readResources() { return readResources; } @Override public long countStatements() { return size; } }