| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.apache.tinkerpop.gremlin.neo4j; |
| |
| import org.apache.commons.configuration.Configuration; |
| import org.apache.tinkerpop.gremlin.AbstractGraphProvider; |
| import org.apache.tinkerpop.gremlin.LoadGraphWith; |
| import org.apache.tinkerpop.gremlin.TestHelper; |
| import org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jEdge; |
| import org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jElement; |
| import org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jGraph; |
| import org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jGraphVariables; |
| import org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jProperty; |
| import org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jVertex; |
| import org.apache.tinkerpop.gremlin.neo4j.structure.Neo4jVertexProperty; |
| import org.apache.tinkerpop.gremlin.structure.Graph; |
| |
| import java.io.File; |
| import java.util.HashSet; |
| import java.util.Optional; |
| import java.util.Random; |
| import java.util.Set; |
| |
| /** |
| * @author Stephen Mallette (http://stephen.genoprime.com) |
| */ |
| public abstract class AbstractNeo4jGraphProvider extends AbstractGraphProvider { |
| private static final Set<Class> IMPLEMENTATIONS = new HashSet<Class>() {{ |
| add(Neo4jEdge.class); |
| add(Neo4jElement.class); |
| add(Neo4jGraph.class); |
| add(Neo4jGraphVariables.class); |
| add(Neo4jProperty.class); |
| add(Neo4jVertex.class); |
| add(Neo4jVertexProperty.class); |
| }}; |
| |
| protected Graph.Features features = null; |
| |
| @Override |
| public Graph openTestGraph(final Configuration config) { |
| final Graph graph = super.openTestGraph(config); |
| |
| // we can just use the initial set of features taken from the first graph generated from the provider because |
| // neo4j feature won't ever change. don't think there is any danger of keeping this instance about even if |
| // the original graph instance goes out of scope. |
| if (null == features) { |
| this.features = graph.features(); |
| } |
| return graph; |
| } |
| |
| @Override |
| public Optional<Graph.Features> getStaticFeatures() { |
| return Optional.ofNullable(features); |
| } |
| |
| @Override |
| public void clear(final Graph graph, final Configuration configuration) throws Exception { |
| if (null != graph) { |
| if (graph.tx().isOpen()) graph.tx().rollback(); |
| graph.close(); |
| } |
| |
| if (null != configuration && configuration.containsKey(Neo4jGraph.CONFIG_DIRECTORY)) { |
| // this is a non-in-sideEffects configuration so blow away the directory |
| final File graphDirectory = new File(configuration.getString(Neo4jGraph.CONFIG_DIRECTORY)); |
| deleteDirectory(graphDirectory); |
| } |
| } |
| |
| @Override |
| public void loadGraphData(final Graph graph, final LoadGraphWith loadGraphWith, final Class testClass, final String testName) { |
| if (loadGraphWith != null) this.createIndices((Neo4jGraph) graph, loadGraphWith.value()); |
| super.loadGraphData(graph, loadGraphWith, testClass, testName); |
| } |
| |
| public static void dropIndices(final Neo4jGraph graph, final LoadGraphWith.GraphData graphData) { |
| if (graphData.equals(LoadGraphWith.GraphData.GRATEFUL)) { |
| graph.tx().readWrite(); |
| graph.cypher("DROP INDEX ON :artist(name)").iterate(); |
| graph.cypher("DROP INDEX ON :song(name)").iterate(); |
| graph.cypher("DROP INDEX ON :song(songType)").iterate(); |
| graph.cypher("DROP INDEX ON :song(performances)").iterate(); |
| graph.tx().commit(); |
| } else if (graphData.equals(LoadGraphWith.GraphData.MODERN)) { |
| graph.tx().readWrite(); |
| graph.cypher("DROP INDEX ON :person(name)").iterate(); |
| graph.cypher("DROP INDEX ON :person(age)").iterate(); |
| graph.cypher("DROP INDEX ON :software(name)").iterate(); |
| graph.cypher("DROP INDEX ON :software(lang)").iterate(); |
| graph.tx().commit(); |
| } else if (graphData.equals(LoadGraphWith.GraphData.CLASSIC)) { |
| graph.tx().readWrite(); |
| graph.cypher("DROP INDEX ON :vertex(name)").iterate(); |
| graph.cypher("DROP INDEX ON :vertex(age)").iterate(); |
| graph.cypher("DROP INDEX ON :vertex(lang)").iterate(); |
| graph.tx().commit(); |
| } else { |
| // TODO: add CREW work here. |
| // TODO: add meta_property indices when meta_property graph is provided |
| //throw new RuntimeException("Could not load graph with " + graphData); |
| } |
| } |
| |
| private void createIndices(final Neo4jGraph graph, final LoadGraphWith.GraphData graphData) { |
| final Random random = TestHelper.RANDOM; |
| final boolean pick = random.nextBoolean(); |
| if (graphData.equals(LoadGraphWith.GraphData.GRATEFUL)) { |
| if (pick) { |
| graph.tx().readWrite(); |
| if (random.nextBoolean()) |
| graph.cypher("CREATE INDEX ON :artist(name)").iterate(); |
| if (random.nextBoolean()) |
| graph.cypher("CREATE INDEX ON :song(name)").iterate(); |
| if (random.nextBoolean()) |
| graph.cypher("CREATE INDEX ON :song(songType)").iterate(); |
| if (random.nextBoolean()) |
| graph.cypher("CREATE INDEX ON :song(performances)").iterate(); |
| graph.tx().commit(); |
| } // else no indices |
| } else if (graphData.equals(LoadGraphWith.GraphData.MODERN)) { |
| if (pick) { |
| graph.tx().readWrite(); |
| if (random.nextBoolean()) |
| graph.cypher("CREATE INDEX ON :person(name)").iterate(); |
| if (random.nextBoolean()) |
| graph.cypher("CREATE INDEX ON :person(age)").iterate(); |
| if (random.nextBoolean()) |
| graph.cypher("CREATE INDEX ON :software(name)").iterate(); |
| if (random.nextBoolean()) { |
| graph.cypher("CREATE INDEX ON :software(lang)").iterate(); |
| } |
| graph.tx().commit(); |
| } // else no indices |
| } else if (graphData.equals(LoadGraphWith.GraphData.CLASSIC)) { |
| if (pick) { |
| graph.tx().readWrite(); |
| if (random.nextBoolean()) |
| graph.cypher("CREATE INDEX ON :vertex(name)").iterate(); |
| if (random.nextBoolean()) |
| graph.cypher("CREATE INDEX ON :vertex(age)").iterate(); |
| if (random.nextBoolean()) |
| graph.cypher("CREATE INDEX ON :vertex(lang)").iterate(); |
| graph.tx().commit(); |
| } // else no indices |
| } else { |
| // TODO: add CREW work here. |
| // TODO: add meta_property indices when meta_property graph is provided |
| //throw new RuntimeException("Could not load graph with " + graphData); |
| } |
| } |
| |
| @Override |
| public Set<Class> getImplementations() { |
| return IMPLEMENTATIONS; |
| } |
| } |