Java tutorial
/******************************************************************************* * Copyright (c) 2010-2015, Benedek Izso, Gabor Szarnyas, Istvan Rath and Daniel Varro * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Benedek Izso - initial API and implementation * Gabor Szarnyas - initial API and implementation *******************************************************************************/ package eu.mondo.driver.fourstore; import static eu.mondo.driver.graph.util.RDFUtil.brackets; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.HashMultimap; import com.google.common.collect.Lists; import com.google.common.collect.Multimap; import eu.mondo.driver.graph.RDFGraphDriverReadWrite; import eu.mondo.driver.graph.util.RDFUtil; import eu.mondo.utils.UnixUtils; public class FourStoreGraphDriverReadWrite extends FourStoreGraphDriverRead implements RDFGraphDriverReadWrite { // note the following limitation of arguments in Bash and set the PARTITION_SIZE accordingly. // "one argument must not be longer than MAX_ARG_STRLEN (131072)" (http://www.in-ulm.de/~mascheck/various/argmax/) private static final int PARTITION_SIZE = 500; public FourStoreGraphDriverReadWrite(final String connectionString) { super(connectionString); } // create // insert vertices @Override public void insertVertex(final String uri, final String type) throws IOException { final List<String> uris = new ArrayList<>(); uris.add(uri); insertVertices(uris, type); } @Override public void insertVertices(final List<String> uris, final String type) throws IOException { if (uris.isEmpty()) { return; } final List<List<String>> partitions = Lists.partition(uris, PARTITION_SIZE); for (final List<String> partition : partitions) { insertVerticesPartition(partition, type); } } private void insertVerticesPartition(final Collection<String> uris, final String type) throws IOException { final StringBuilder insertQueryBuilder = new StringBuilder(SPARQL_RDF_PREFIX); insertQueryBuilder.append("INSERT DATA {"); for (final String uri : uris) { insertQueryBuilder.append(String.format(". %s rdf:type %s", brackets(uri), brackets(type))); } insertQueryBuilder.append("}"); // run the update runUpdate(insertQueryBuilder.toString()); } // insert edges @Override public void insertEdge(final String sourceVertexURI, final String targetVertexURI, final String type) throws IOException { final Multimap<String, String> edges = HashMultimap.create(); edges.put(sourceVertexURI, targetVertexURI); insertEdges(edges, type); } @Override public void insertEdges(final Multimap<String, String> edges, final String type) throws IOException { if (edges.isEmpty()) { return; } final ArrayList<String> sourceVertices = new ArrayList<>(edges.keySet()); final List<List<String>> sourceVerticesPartitions = Lists.partition(sourceVertices, PARTITION_SIZE); for (final List<String> sourceVerticesPartition : sourceVerticesPartitions) { final Multimap<String, String> edgePartition = ArrayListMultimap.create(); for (final String sourceVertexURI : sourceVerticesPartition) { final Collection<String> targetVertexURIs = edges.get(sourceVertexURI); edgePartition.putAll(sourceVertexURI, targetVertexURIs); } insertEdgesPartition(edgePartition, type); } } private void insertEdgesPartition(final Multimap<String, String> edges, final String type) throws IOException { final StringBuilder insertQueryBuilder = new StringBuilder("INSERT DATA {"); edgesToTriples(edges, type, insertQueryBuilder); insertQueryBuilder.append("}"); // run the update runUpdate(insertQueryBuilder.toString()); } // insert edges with verties @Override public void insertEdgeWithVertex(final String sourceURI, final String targetURI, final String edgeType, final String targetVertexType) throws IOException { final Multimap<String, String> edges = HashMultimap.create(); edges.put(sourceURI, targetURI); insertEdgesWithVertex(edges, edgeType, targetVertexType); } @Override public void insertEdgesWithVertex(final Multimap<String, String> edges, final String edgeType, final String targetVertexType) throws IOException { if (edges.isEmpty()) { return; } final ArrayList<String> sourceVertices = new ArrayList<>(edges.keySet()); final List<List<String>> sourceVerticesPartitions = Lists.partition(sourceVertices, PARTITION_SIZE); for (final List<String> sourceVerticesPartition : sourceVerticesPartitions) { final Multimap<String, String> edgePartition = ArrayListMultimap.create(); for (final String sourceVertexURI : sourceVerticesPartition) { final Collection<String> targetVertexURIs = edges.get(sourceVertexURI); edgePartition.putAll(sourceVertexURI, targetVertexURIs); } insertEdgesWithVertexPartition(edgePartition, edgeType, targetVertexType); } } private void insertEdgesWithVertexPartition(final Multimap<String, String> edges, final String edgeType, final String targetVertexType) throws IOException { final StringBuilder insertQueryBuilder = new StringBuilder(SPARQL_RDF_PREFIX); insertQueryBuilder.append("INSERT DATA {"); edgesToTriples(edges, edgeType, insertQueryBuilder); for (final String targetVertex : edges.values()) { insertQueryBuilder .append(String.format(". %s rdf:type %s", brackets(targetVertex), brackets(targetVertexType))); } insertQueryBuilder.append("}"); // run the update runUpdate(insertQueryBuilder.toString()); } // update properties @Override public void updateProperty(final String vertex, final String type, final Object value) throws IOException { final Map<String, Object> properties = new HashMap<>(); properties.put(vertex, value); updateProperties(properties, type); } @Override public void updateProperties(final Map<String, Object> properties, final String type) throws IOException { if (properties.isEmpty()) { return; } final List<String> vertexURIs = new ArrayList<>(properties.keySet()); final List<List<String>> vertexURIpartitions = Lists.partition(vertexURIs, PARTITION_SIZE); for (final List<String> vertexURIpartition : vertexURIpartitions) { final Map<String, Object> propertyPartition = new HashMap<>(); for (final String vertexURI : vertexURIpartition) { final Object value = properties.get(vertexURI); propertyPartition.put(vertexURI, value); } updatePropertiesPartition(propertyPartition, type); } } private void updatePropertiesPartition(final Map<String, Object> properties, final String type) throws IOException { final StringBuilder updateQueryBuilder = new StringBuilder(SPARQL_RDF_PREFIX); int i = 0; // delete for (final Entry<String, Object> property : properties.entrySet()) { final String vertex = property.getKey(); i++; updateQueryBuilder.append(String.format("DELETE { %s %s ?a%d } WHERE { %s %s ?a%d }; ", brackets(vertex), brackets(type), i, brackets(vertex), brackets(type), i)); } // insert boolean first = true; updateQueryBuilder.append("INSERT DATA {"); for (final Entry<String, Object> property : properties.entrySet()) { if (first) { first = false; } else { updateQueryBuilder.append("."); } final String vertex = property.getKey(); final String value = RDFUtil.toLiteral(property.getValue()); updateQueryBuilder.append(String.format(" %s %s %s ", brackets(vertex), brackets(type), value)); } updateQueryBuilder.append("}"); // run the update runUpdate(updateQueryBuilder.toString()); } // delete vertices @Override public void deleteVertex(final String uri) throws IOException { final List<String> vertices = new ArrayList<>(); vertices.add(uri); deleteVertices(vertices); } @Override public void deleteVertices(final List<String> uris) throws IOException { if (uris.isEmpty()) { return; } final List<List<String>> partitions = Lists.partition(uris, PARTITION_SIZE); for (final List<String> partition : partitions) { deleteVertexPartition(partition); } } private void deleteVertexPartition(final List<String> uris) throws IOException { final StringBuilder deleteQueryBuilder = new StringBuilder(); // add a number to each variable number in the SPARQL query in order to make it unique long i = 0; for (final String vertex : uris) { // if we try to use DELETE DATA (as in the deleteEdge() method), 4store throws an error: // DELETE WHERE { x } not yet supported, use DELETE { x } WHERE { x } i++; // delete "incoming edges" deleteQueryBuilder.append(String.format("DELETE { ?a%d ?b%d %s } WHERE { ?a%d ?b%d %s }; ", i, i, brackets(vertex), i, i, brackets(vertex))); i++; // delete "outgoing edges" and "properties" deleteQueryBuilder.append(String.format("DELETE { %s ?a%d ?b%d } WHERE { %s ?a%d ?b%d }; ", brackets(vertex), i, i, brackets(vertex), i, i)); } runUpdate(deleteQueryBuilder.toString()); } // delete edges @Override public void deleteEdge(final String sourceVertexURI, final String targetVertexURI, final String type) throws IOException { final Multimap<String, String> edges = HashMultimap.create(); edges.put(sourceVertexURI, targetVertexURI); deleteEdges(edges, type); } @Override public void deleteEdges(final Multimap<String, String> edges, final String type) throws IOException { if (edges.isEmpty()) { return; } deleteEdgesPartition(edges, type); } private void deleteEdgesPartition(final Multimap<String, String> edges, final String type) throws IOException { final StringBuilder deleteQueryBuilder = new StringBuilder("DELETE DATA {"); edgesToTriples(edges, type, deleteQueryBuilder); deleteQueryBuilder.append("}"); runUpdate(deleteQueryBuilder.toString()); } // helper methods public void runUpdate(final String query) throws IOException { final String command = String.format("4s-update $FOURSTORE_CLUSTER_NAME '%s'", query); if (showCommands) { System.out.println(command); } UnixUtils.exec(command, environment); } protected StringBuilder initBuilder() { StringBuilder insertQueryBuilder; insertQueryBuilder = new StringBuilder(SPARQL_RDF_PREFIX); insertQueryBuilder.append("INSERT DATA {"); return insertQueryBuilder; } protected void edgesToTriples(final Multimap<String, String> edges, final String edgeLabel, final StringBuilder insertQueryBuilder) { boolean first = true; for (final Entry<String, String> edge : edges.entries()) { if (first) { first = false; } else { insertQueryBuilder.append("."); } final String sourceVertex = edge.getKey(); final String targetVertex = edge.getValue(); insertQueryBuilder.append(String.format(" %s %s %s ", brackets(sourceVertex), brackets(edgeLabel), brackets(targetVertex))); } } }