/** * 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.utils; import java.util.Map; import java.util.Optional; import org.mapdb.Atomic; import org.mapdb.DB; import org.neo4j.graphdb.GraphDatabaseService; import org.neo4j.graphdb.Node; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.dswarm.common.types.Tuple; import org.dswarm.common.web.URI; import org.dswarm.graph.DMPGraphException; import org.dswarm.graph.GraphProcessingStatics; import org.dswarm.graph.model.GraphStatics; import org.dswarm.graph.tx.TransactionHandler; /** * @author tgaengler */ public class NamespaceUtils { private static final Logger LOG = LoggerFactory.getLogger(NamespaceUtils.class); public static final String NAMESPACE_PREFIX_BASE = "ns"; public static final char PREFIX_DELIMITER = ':'; public static final String PREFIX_DELIMTER_STRING = String.valueOf(PREFIX_DELIMITER); public static String createPrefixedURI(final String fullURI, final Map<String, String> uriPrefixedURIMap, final Map<String, String> tempNamespacePrefixes, final Map<String, String> inMemoryNamespacePrefixes, final Tuple<Atomic.Long, DB> prefixCounterTuple, final GraphDatabaseService database, final TransactionHandler tx) throws DMPGraphException { if (fullURI == null) { throw new DMPGraphException("full URI shouldn't be null"); } if (uriPrefixedURIMap != null) { if (!uriPrefixedURIMap.containsKey(fullURI)) { final String prefixedURI = determinePrefixedURI(fullURI, tempNamespacePrefixes, inMemoryNamespacePrefixes, prefixCounterTuple, database, tx); uriPrefixedURIMap.put(fullURI, prefixedURI); } return uriPrefixedURIMap.get(fullURI); } else { return determinePrefixedURI(fullURI, tempNamespacePrefixes, inMemoryNamespacePrefixes, prefixCounterTuple, database, tx); } } public static String createFullURI(final String prefixedURI, final Map<String, String> prefixedURIURIMap, final GraphDatabaseService database, final TransactionHandler tx) throws DMPGraphException { if (prefixedURI == null) { throw new DMPGraphException("prefixed URI shouldn't be null"); } if (prefixedURIURIMap != null) { if (!prefixedURIURIMap.containsKey(prefixedURI)) { final String fullURI = determineFullURI(prefixedURI, database, tx); prefixedURIURIMap.put(prefixedURI, fullURI); } return prefixedURIURIMap.get(prefixedURI); } else { return determineFullURI(prefixedURI, database, tx); } } public static String getPrefix(final String namespace, final Map<String, String> tempNamespacesPrefixesMap, final Map<String, String> inMemoryNamespacesPrefixesMap, final Tuple<Atomic.Long, DB> prefixCounterTuple, final GraphDatabaseService database, final TransactionHandler tx) throws DMPGraphException { if (namespace == null || namespace.trim().isEmpty()) { throw new DMPGraphException("namespace shouldn't be null or empty"); } if (tempNamespacesPrefixesMap != null && tempNamespacesPrefixesMap.containsKey(namespace)) { return tempNamespacesPrefixesMap.get(namespace); } if (inMemoryNamespacesPrefixesMap != null && inMemoryNamespacesPrefixesMap.containsKey(namespace)) { return inMemoryNamespacesPrefixesMap.get(namespace); } try { tx.ensureRunningTx(); final Optional<Node> optionalNode = getPrefix(namespace, database); if (optionalNode.isPresent()) { final String prefix = (String) optionalNode.get().getProperty(GraphProcessingStatics.PREFIX_PROPERTY); if (inMemoryNamespacesPrefixesMap != null) { // cache in-memory inMemoryNamespacesPrefixesMap.put(namespace, prefix); } return prefix; } final long currentPrefixCount = getNewPrefixCount(prefixCounterTuple); final String prefix = NAMESPACE_PREFIX_BASE + currentPrefixCount; if (tempNamespacesPrefixesMap != null) { tempNamespacesPrefixesMap.put(namespace, prefix); } LOG.debug("minted new prefix '{}' for namespace '{}'", prefix, namespace); return prefix; } catch (final Exception e) { tx.failTx(); final String message = String.format("couldn't retrieve prefix for namespace '%s' successfully", namespace); LOG.error(message); throw new DMPGraphException(message, e); } } public static Optional<Node> getPrefix(final String namespace, final GraphDatabaseService database) { return Optional .ofNullable(database.findNode(GraphProcessingStatics.PREFIX_LABEL, GraphStatics.URI_PROPERTY, namespace)); } public static String getNamespace(final String prefix, final GraphDatabaseService database, final TransactionHandler tx) throws DMPGraphException { if (prefix == null || prefix.trim().isEmpty()) { throw new DMPGraphException("prefix shouldn't be null or empty"); } try { tx.ensureRunningTx(); final Optional<Node> optionalNode = Optional.ofNullable( database.findNode(GraphProcessingStatics.PREFIX_LABEL, GraphProcessingStatics.PREFIX_PROPERTY, prefix)); if (!optionalNode.isPresent()) { throw new DMPGraphException(String.format("couldn't find a namespace for prefix '%s'", prefix)); } final Node node = optionalNode.get(); return (String) node.getProperty(GraphStatics.URI_PROPERTY); } catch (final Exception e) { tx.failTx(); final String message = String.format("couldn't retrieve namespace for prefix '%s' successfully", prefix); LOG.error(message); throw new DMPGraphException(message, e); } } public static String determinePrefixedURI(final String fullURI, final Map<String, String> tempNamespacePrefixes, final Map<String, String> inMemoryNamespacePrefixes, final Tuple<Atomic.Long, DB> prefixCounterTuple, final GraphDatabaseService database, final TransactionHandler tx) throws DMPGraphException { final Tuple<String, String> uriParts = URI.determineParts(fullURI); final String namespaceURI = uriParts.v1(); final String localName = uriParts.v2(); final String prefix = NamespaceUtils .getPrefix(namespaceURI, tempNamespacePrefixes, inMemoryNamespacePrefixes, prefixCounterTuple, database, tx); return prefix + NamespaceUtils.PREFIX_DELIMITER + localName; } public static String determineFullURI(final String prefixedURI, final GraphDatabaseService database, final TransactionHandler tx) throws DMPGraphException { final String[] splittedPrefixedURI = prefixedURI.split(PREFIX_DELIMTER_STRING); if (splittedPrefixedURI.length != 2) { throw new DMPGraphException(String.format("couldn't split prefixed URI '%s' into two parts", prefixedURI)); } final String prefix = splittedPrefixedURI[0]; final String localName = splittedPrefixedURI[1]; final String namespace = getNamespace(prefix, database, tx); return namespace + localName; } private static long getNewPrefixCount(final Tuple<Atomic.Long, DB> prefixCounterTuple) { final Atomic.Long prefixCounter = prefixCounterTuple.v1(); final DB prefixCounterDB = prefixCounterTuple.v2(); final long prefixCount = prefixCounter.getAndIncrement(); prefixCounterDB.commit(); return prefixCount; } }