| /******************************************************************************* |
| * Copyright (c) 2015-2017 The University of York, Aston University. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0. |
| * |
| * This Source Code may also be made available under the following Secondary |
| * Licenses when the conditions for such availability set forth in the Eclipse |
| * Public License, v. 2.0 are satisfied: GNU General Public License, version 3. |
| * |
| * SPDX-License-Identifier: EPL-2.0 OR GPL-3.0 |
| * |
| * Contributors: |
| * Antonio Garcia-Dominguez - initial API and implementation |
| ******************************************************************************/ |
| package org.hawk.backend.tests; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assert.assertNotNull; |
| import static org.junit.Assert.assertSame; |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assert.fail; |
| |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.Map; |
| import java.util.NoSuchElementException; |
| |
| import org.hawk.backend.tests.factories.IGraphDatabaseFactory; |
| import org.hawk.core.IModelIndexer; |
| import org.hawk.core.graph.IGraphIterable; |
| import org.hawk.core.graph.IGraphNode; |
| import org.hawk.core.graph.IGraphNodeIndex; |
| import org.hawk.core.graph.IGraphTransaction; |
| import org.junit.Assume; |
| import org.junit.Rule; |
| import org.junit.Test; |
| import org.junit.runners.Parameterized.Parameters; |
| |
| /** |
| * Tests for populating and querying indices. |
| */ |
| public class IndexTest extends TemporaryDatabaseTest { |
| |
| @Rule |
| public RedirectSystemErrorRule errRule = new RedirectSystemErrorRule(); |
| |
| @Rule |
| public LogbackOnlyErrorsRule logRule = new LogbackOnlyErrorsRule(); |
| |
| @Parameters(name="Parameters are {0}") |
| public static Iterable<Object[]> params() { |
| return BackendTestSuite.caseParams(); |
| } |
| |
| public IndexTest(IGraphDatabaseFactory dbFactory) { |
| super(dbFactory); |
| } |
| |
| @Test |
| public void query() throws Exception { |
| final String mmBarURI = "http://foo/bar"; |
| final String mmFileURI = "file://a/b/c.d"; |
| final Map<String, Object> mmBarNodeProps = Collections.singletonMap(IModelIndexer.IDENTIFIER_PROPERTY, mmBarURI); |
| final Map<String, Object> mmFileNodeProps = Collections.singletonMap(IModelIndexer.IDENTIFIER_PROPERTY, mmFileURI); |
| |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| IGraphNode mmNode = db.createNode(mmBarNodeProps, "metamodel"); |
| db.getMetamodelIndex().add(mmNode, Collections.singletonMap("id", mmBarURI)); |
| |
| IGraphNode mmFileNode = db.createNode(mmFileNodeProps, "metamodel"); |
| db.getMetamodelIndex().add(mmFileNode, Collections.singletonMap("id", mmFileURI)); |
| |
| tx.success(); |
| } |
| |
| // Query with partial wildcard |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| final IGraphIterable<? extends IGraphNode> iter = db.getMetamodelIndex().query("id", "http://*"); |
| assertSame(db, iter.getSingle().getGraph()); |
| assertEquals(1, iter.size()); |
| assertTrue(iter.getSingle().getProperty(IModelIndexer.IDENTIFIER_PROPERTY).toString().startsWith("http://")); |
| tx.success(); |
| } |
| |
| // Query with full value |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| final IGraphIterable<? extends IGraphNode> iter3 = db.getMetamodelIndex().query("id", mmBarURI); |
| assertEquals(1, iter3.size()); |
| |
| final IGraphNode node = iter3.getSingle(); |
| assertSame(db, node.getGraph()); |
| assertEquals(mmBarURI, node.getProperty(IModelIndexer.IDENTIFIER_PROPERTY)); |
| tx.success(); |
| } |
| |
| // Query with wildcard on one field |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| final IGraphIterable<? extends IGraphNode> iter4 = db.getMetamodelIndex().query("id", "*"); |
| assertSame(db, iter4.getSingle().getGraph()); |
| assertEquals(2, iter4.size()); |
| tx.success(); |
| } |
| |
| // Retrieve with full value |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| final IGraphIterable<? extends IGraphNode> iter2 = db.getMetamodelIndex().get("id", mmFileURI); |
| assertEquals(1, iter2.size()); |
| assertEquals(mmFileURI, iter2.getSingle().getProperty(IModelIndexer.IDENTIFIER_PROPERTY)); |
| tx.success(); |
| } |
| |
| // Use */* (all fields, all values) |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| assertEquals(new HashSet<>(Arrays.asList(mmBarURI, mmFileURI)), db.getKnownMMUris()); |
| tx.success(); |
| } |
| } |
| |
| @Test |
| public void queryWithPipes() throws Exception { |
| // Pipe characters should be treated as such, not as "OR" (as in regexps) |
| final String sN1 = "/a||/foo/bar", sN2 = "/b||/test"; |
| |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| IGraphNode n1 = db.createNode(null, "metamodel"); |
| db.getMetamodelIndex().add(n1, "id", sN1); |
| |
| IGraphNode n2 = db.createNode(null, "metamodel"); |
| db.getMetamodelIndex().add(n2, "id", sN2); |
| |
| tx.success(); |
| } |
| |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| assertEquals(1, db.getMetamodelIndex().query("id", "/*||/foo/*").size()); |
| tx.success(); |
| } |
| } |
| |
| @Test |
| public void removeByNode() throws Exception { |
| final String mmBarURI = populateForRemove(); |
| |
| // NOTE: changes in Lucene indexes are not complete until we commit the |
| // transaction |
| final IGraphIterable<? extends IGraphNode> iter = checkBeforeRemove(mmBarURI); |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| db.getMetamodelIndex().remove(iter.getSingle()); |
| tx.success(); |
| } |
| checkAfterRemove(mmBarURI); |
| } |
| |
| @Test |
| public void removeByNodeMultipleIndicesRemoveOne() throws Exception { |
| IGraphNode n; |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| n = db.createNode(null, "x"); |
| db.getMetamodelIndex().add(n, "a", 1); |
| db.getFileIndex().add(n, "f", "/x/y"); |
| tx.success(); |
| } |
| |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| assertEquals(1, db.getMetamodelIndex().query("*", "*").size()); |
| assertEquals(1, db.getFileIndex().query("*", "*").size()); |
| db.getMetamodelIndex().remove(n); |
| assertEquals(0, db.getMetamodelIndex().query("*", "*").size()); |
| assertEquals(1, db.getFileIndex().query("*", "*").size()); |
| |
| tx.success(); |
| } |
| } |
| |
| @Test |
| public void removeByNodeMultipleIndicesRemoveAll() throws Exception { |
| IGraphNode n; |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| n = db.createNode(null, "x"); |
| db.getMetamodelIndex().add(n, "a", 1); |
| db.getFileIndex().add(n, "f", "/x/y"); |
| tx.success(); |
| } |
| |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| assertEquals(1, db.getMetamodelIndex().query("*", "*").size()); |
| assertEquals(1, db.getFileIndex().query("*", "*").size()); |
| |
| for (String idxName : db.getNodeIndexNames()) { |
| db.getOrCreateNodeIndex(idxName).remove(n); |
| } |
| for (String idxName : db.getNodeIndexNames()) { |
| assertEquals(0, db.getOrCreateNodeIndex(idxName).query("*", "*").size()); |
| } |
| tx.success(); |
| } |
| |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| for (String idxName : db.getNodeIndexNames()) { |
| assertEquals(0, db.getOrCreateNodeIndex(idxName).query("*", "*").size()); |
| } |
| tx.success(); |
| } |
| } |
| |
| @Test |
| public void removeByFullKey() throws Exception { |
| final String mmBarURI = populateForRemove(); |
| |
| final IGraphIterable<? extends IGraphNode> iter = checkBeforeRemove(mmBarURI); |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| db.getMetamodelIndex().remove(iter.getSingle(), "id", mmBarURI); |
| tx.success(); |
| } |
| checkAfterRemove(mmBarURI); |
| } |
| |
| @Test |
| public void removeByFullKeyInt() throws Exception { |
| IGraphNode n1, n2; |
| final String key = "int"; |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| n1 = db.createNode(null, "v"); |
| n2 = db.createNode(null, "v"); |
| db.getMetamodelIndex().add(n1, key, 1); |
| db.getMetamodelIndex().add(n2, key, 2); |
| |
| tx.success(); |
| } |
| |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| final IGraphNodeIndex mmIdx = db.getMetamodelIndex(); |
| assertEquals(2, mmIdx.query(key, 1, 2, true, true).size()); |
| mmIdx.remove(n1, key, 1); |
| tx.success(); |
| } |
| |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| assertEquals(0, db.getMetamodelIndex().get(key, 1).size()); |
| assertEquals(1, db.getMetamodelIndex().get(key, 2).size()); |
| assertEquals(1, db.getMetamodelIndex().query(key, 1, 2, true, true).size()); |
| assertEquals(1, db.getMetamodelIndex().query(key, "*").size()); |
| tx.success(); |
| } |
| } |
| |
| @Test |
| public void removeByFullKeyDouble() throws Exception { |
| final String key = "double"; |
| |
| IGraphNode n1, n2; |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| n1 = db.createNode(null, "v"); |
| n2 = db.createNode(null, "v"); |
| db.getMetamodelIndex().add(n1, key, 1.1); |
| db.getMetamodelIndex().add(n2, key, 2.3); |
| |
| tx.success(); |
| } |
| |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| final IGraphNodeIndex mmIdx = db.getMetamodelIndex(); |
| mmIdx.remove(n1, key, 1.1); |
| tx.success(); |
| } |
| |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| assertEquals(0, db.getMetamodelIndex().get(key, 1.1).size()); |
| assertEquals(1, db.getMetamodelIndex().get(key, 2.3).size()); |
| assertEquals(1, db.getMetamodelIndex().query(key, 1.0, 3.0, false, false).size()); |
| assertEquals(1, db.getMetamodelIndex().query(key, "*").size()); |
| tx.success(); |
| } |
| } |
| |
| @Test |
| public void removeByValueNode() throws Exception { |
| final String mmBarURI = populateForRemove(); |
| final IGraphIterable<? extends IGraphNode> iter = checkBeforeRemove(mmBarURI); |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| db.getMetamodelIndex().remove(iter.getSingle(), null, mmBarURI); |
| tx.success(); |
| } catch (UnsupportedOperationException ex) { |
| Assume.assumeTrue("Removing a node by value with no key is not supported on this backend", false); |
| } |
| checkAfterRemove(mmBarURI); |
| } |
| |
| @Test |
| public void removeByFieldNode() throws Exception { |
| final String mmBarURI = populateForRemove(); |
| |
| final IGraphIterable<? extends IGraphNode> iter = checkBeforeRemove(mmBarURI); |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| db.getMetamodelIndex().remove(iter.getSingle(), "id", null); |
| tx.success(); |
| } |
| checkAfterRemove(mmBarURI); |
| } |
| |
| @Test |
| public void removeByNode3Arg() throws Exception { |
| final String mmBarURI = populateForRemove(); |
| |
| // NOTE: changes in Lucene indexes are not complete until we commit the transaction |
| final IGraphIterable<? extends IGraphNode> iter = checkBeforeRemove(mmBarURI); |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| db.getMetamodelIndex().remove(iter.getSingle(), null, null); |
| tx.success(); |
| } |
| checkAfterRemove(mmBarURI); |
| } |
| |
| @Test |
| public void integerExact() throws Exception { |
| final String mmBarURI = "http://foo/bar"; |
| final Map<String, Object> mmBarNodeProps = Collections.singletonMap(IModelIndexer.IDENTIFIER_PROPERTY, mmBarURI); |
| |
| final IGraphNodeIndex idx = db.getMetamodelIndex(); |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| IGraphNode mmNode = db.createNode(mmBarNodeProps, "metamodel"); |
| idx.add(mmNode, Collections.singletonMap("value", 5)); |
| |
| IGraphNode mmNode2 = db.createNode(mmBarNodeProps, "metamodel"); |
| idx.add(mmNode2, Collections.singletonMap("value", 8)); |
| |
| IGraphNode mmNode3 = db.createNode(mmBarNodeProps, "metamodel"); |
| idx.add(mmNode3, Collections.singletonMap("value", 8)); |
| |
| tx.success(); |
| } |
| |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| assertEquals(0, idx.get("value", 1).size()); |
| assertEquals(0, idx.query("value", 1).size()); |
| |
| assertEquals(1, idx.get("value", 5).size()); |
| assertEquals(1, idx.query("value", 5).size()); |
| |
| assertEquals(2, idx.get("value", 8).size()); |
| assertEquals(2, idx.query("value", 8).size()); |
| |
| assertEquals(3, idx.query("value", "*").size()); |
| assertEquals(3, idx.query("*", "*").size()); |
| |
| tx.success(); |
| } |
| } |
| |
| @Test |
| public void doubleExact() throws Exception { |
| final String mmBarURI = "http://foo/bar"; |
| final Map<String, Object> mmBarNodeProps = Collections.singletonMap(IModelIndexer.IDENTIFIER_PROPERTY, mmBarURI); |
| |
| final IGraphNodeIndex idx = db.getMetamodelIndex(); |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| IGraphNode mmNode = db.createNode(mmBarNodeProps, "metamodel"); |
| idx.add(mmNode, Collections.singletonMap("value", 5.3)); |
| |
| IGraphNode mmNode2 = db.createNode(mmBarNodeProps, "metamodel"); |
| idx.add(mmNode2, Collections.singletonMap("value", 8.1)); |
| |
| IGraphNode mmNode3 = db.createNode(mmBarNodeProps, "metamodel"); |
| idx.add(mmNode3, Collections.singletonMap("value", 8.1)); |
| |
| tx.success(); |
| } |
| |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| assertEquals(0, idx.get("value", 5.2).size()); |
| assertEquals(0, idx.query("value", 5.2).size()); |
| assertEquals(0, idx.get("value", 8.4).size()); |
| assertEquals(0, idx.query("value", 8.4).size()); |
| |
| assertEquals(1, idx.get("value", 5.3).size()); |
| assertEquals(1, idx.query("value", 5.3).size()); |
| assertEquals(2, idx.get("value", 8.1).size()); |
| assertEquals(2, idx.query("value", 8.1).size()); |
| |
| assertEquals(3, idx.query("value", "*").size()); |
| assertEquals(3, idx.query("*", "*").size()); |
| |
| tx.success(); |
| } |
| } |
| |
| @Test |
| public void integerRanges() throws Exception { |
| final String mmBarURI = "http://foo/bar"; |
| final Map<String, Object> mmBarNodeProps = Collections.singletonMap(IModelIndexer.IDENTIFIER_PROPERTY, mmBarURI); |
| |
| final IGraphNodeIndex idx = db.getMetamodelIndex(); |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| IGraphNode mmNode = db.createNode(mmBarNodeProps, "metamodel"); |
| idx.add(mmNode, Collections.singletonMap("value", 5)); |
| |
| IGraphNode mmNode2 = db.createNode(mmBarNodeProps, "metamodel"); |
| idx.add(mmNode2, Collections.singletonMap("value", 8)); |
| |
| IGraphNode mmNode3 = db.createNode(mmBarNodeProps, "metamodel"); |
| idx.add(mmNode3, Collections.singletonMap("value", 1)); |
| tx.success(); |
| } |
| |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| assertEquals(3, idx.query("value", 0, 10, false, false).size()); |
| assertEquals(1, idx.query("value", 1, 8, false, false).size()); |
| assertEquals(2, idx.query("value", 1, 8, true, false).size()); |
| assertEquals(2, idx.query("value", 1, 8, false, true).size()); |
| assertEquals(3, idx.query("value", 1, 8, true, true).size()); |
| assertEquals(2, idx.query("value", 2, 8, true, true).size()); |
| assertEquals(2, idx.query("value", 1, 7, true, true).size()); |
| assertEquals(1, idx.query("value", 4, 6, false, false).size()); |
| assertEquals(1, idx.query("value", 5, 5, true, true).size()); |
| assertEquals(0, idx.query("value", 5, 5, false, false).size()); |
| assertEquals(0, idx.query("value", 5, 4, false, false).size()); |
| tx.success(); |
| } |
| } |
| |
| @Test |
| public void floatingRanges() throws Exception { |
| final String mmBarURI = "http://foo/bar"; |
| final Map<String, Object> mmBarNodeProps = Collections.singletonMap(IModelIndexer.IDENTIFIER_PROPERTY, mmBarURI); |
| |
| final IGraphNodeIndex idx = db.getMetamodelIndex(); |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| IGraphNode mmNode = db.createNode(mmBarNodeProps, "metamodel"); |
| idx.add(mmNode, Collections.singletonMap("value", 5.3)); |
| |
| IGraphNode mmNode2 = db.createNode(mmBarNodeProps, "metamodel"); |
| idx.add(mmNode2, Collections.singletonMap("value", 8.1d)); |
| |
| IGraphNode mmNode3 = db.createNode(mmBarNodeProps, "metamodel"); |
| idx.add(mmNode3, Collections.singletonMap("value", 1.34)); |
| tx.success(); |
| } |
| |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| assertEquals(3, idx.query("value", 0.0, 10.0, false, false).size()); |
| assertEquals(3, idx.query("value", 1.3, 8.2, false, false).size()); |
| assertEquals(2, idx.query("value", 1.4, 8.2, false, false).size()); |
| assertEquals(2, idx.query("value", 1.3, 8.0, false, false).size()); |
| assertEquals(1, idx.query("value", 1.4, 8.0, false, false).size()); |
| assertEquals(1, idx.query("value", 5.2, 5.4, false, false).size()); |
| assertEquals(0, idx.query("value", 5.2, 5.2, false, false).size()); |
| assertEquals(0, idx.query("value", 5.2, 5.1, false, false).size()); |
| tx.success(); |
| } |
| } |
| |
| @Test |
| public void invalidIndexNames() throws Exception { |
| // OIndexManagerShared#createIndex checks for these |
| final char[] invalidChars = ":,; %=/\\".toCharArray(); |
| |
| IGraphNode n; |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| n = db.createNode(null, "eobject"); |
| tx.success(); |
| } |
| for (char invalidChar : invalidChars) { |
| final String name = "my" + invalidChar + "index"; |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| assertFalse(db.nodeIndexExists(name)); |
| IGraphNodeIndex idx = db.getOrCreateNodeIndex(name); |
| idx.add(n, "id", 1); |
| tx.success(); |
| } |
| |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| assertTrue("Index " + name + " should be listed", db.getNodeIndexNames().contains(name)); |
| assertTrue(db.nodeIndexExists(name)); |
| IGraphNodeIndex idx = db.getOrCreateNodeIndex(name); |
| |
| IGraphIterable<? extends IGraphNode> results = idx.query("id", 1); |
| assertEquals("Exact query for index " + name + " should produce one result", 1, results.size()); |
| results = idx.query("id", 0, 1, true, true); |
| assertEquals("Range query for index " + name + " should produce one result", 1, results.size()); |
| |
| final IGraphIterable<? extends IGraphNode> allID = idx.query("id", "*"); |
| assertEquals("Should find exactly one match in " + name, 1, allID.size()); |
| |
| tx.success(); |
| } |
| } |
| } |
| |
| @Test |
| public void getMultipleMatches() throws Exception { |
| final String objLabel = "object"; |
| final String fileIdxKey = "file"; |
| final String fileNodeLabel = fileIdxKey; |
| final String fileEdgeLabel = "inFile"; |
| |
| IGraphNodeIndex idxRoots; |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| idxRoots = db.getOrCreateNodeIndex("roots"); |
| |
| IGraphNode n1 = db.createNode(null, objLabel); |
| IGraphNode n2 = db.createNode(null, objLabel); |
| IGraphNode n3 = db.createNode(null, objLabel); |
| IGraphNode f1 = db.createNode(null, fileNodeLabel); |
| IGraphNode f2 = db.createNode(null, fileNodeLabel); |
| |
| db.createRelationship(n1, f1, fileEdgeLabel); |
| db.createRelationship(n2, f1, fileEdgeLabel); |
| db.createRelationship(n3, f2, fileEdgeLabel); |
| idxRoots.add(n1, fileIdxKey, "a.xmi"); |
| idxRoots.add(n2, fileIdxKey, "a.xmi"); |
| idxRoots.add(n3, fileIdxKey, "b.xmi"); |
| |
| tx.success(); |
| } |
| |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| final IGraphIterable<? extends IGraphNode> aRoots = idxRoots.get(fileIdxKey, "a.xmi"); |
| assertEquals(2, aRoots.size()); |
| assertEquals(2, iteratorSize(aRoots.iterator())); |
| assertNotNull(aRoots.getSingle()); |
| tx.success(); |
| } |
| |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| final IGraphIterable<? extends IGraphNode> bRoots = idxRoots.get(fileIdxKey, "b.xmi"); |
| assertEquals(1, bRoots.size()); |
| assertEquals(1, iteratorSize(bRoots.iterator())); |
| assertNotNull(bRoots.getSingle()); |
| tx.success(); |
| } |
| |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| final IGraphIterable<? extends IGraphNode> cRoots = idxRoots.get(fileIdxKey, "c.xmi"); |
| assertEquals(0, cRoots.size()); |
| assertEquals(0, iteratorSize(cRoots.iterator())); |
| try { |
| cRoots.getSingle(); |
| fail("NoSuchElementException should have been thrown"); |
| } catch (NoSuchElementException ex) { |
| // good! |
| } |
| tx.success(); |
| } |
| } |
| |
| @Test |
| public void addNullValue() throws Exception { |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| IGraphNodeIndex idxRoots = db.getOrCreateNodeIndex("roots"); |
| IGraphNode n1 = db.createNode(null, "eobject"); |
| idxRoots.add(n1, "file", null); |
| tx.success(); |
| } |
| } |
| |
| @Test |
| public void addNullMap() throws Exception { |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| IGraphNodeIndex idxRoots = db.getOrCreateNodeIndex("roots"); |
| IGraphNode n1 = db.createNode(null, "eobject"); |
| idxRoots.add(n1, null); |
| tx.success(); |
| } |
| } |
| |
| @Test |
| public void addPreservesPriorValue() throws Exception { |
| /* |
| * IMPORTANT - Don't pull an Antonio and think that a single (node, key) pair |
| * should only be associated with one value. Derived attribute acces indices |
| * need to track all the attributes (values) that a (node = source node, key = |
| * accessed node) accessed! |
| */ |
| |
| IGraphNodeIndex idxRoots; |
| IGraphNode x; |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| idxRoots = db.getOrCreateNodeIndex("roots"); |
| x = db.createNode(null, "eobject"); |
| idxRoots.add(x, "a", "1"); |
| idxRoots.add(x, "a", "2"); |
| tx.success(); |
| } |
| |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| assertEquals(1, idxRoots.query("a", "1").size()); |
| assertEquals(1, idxRoots.query("a", "2").size()); |
| tx.success(); |
| } |
| } |
| |
| /* |
| * TODO test adding multiple values and removing one value. |
| */ |
| |
| @Test |
| public void deleteRecreate() throws Exception { |
| IGraphNodeIndex idxRoots; |
| IGraphNode x; |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| idxRoots = db.getOrCreateNodeIndex("roots"); |
| x = db.createNode(null, "eobject"); |
| idxRoots.add(x, "a", "1"); |
| tx.success(); |
| } |
| |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| assertEquals(1, idxRoots.query("a", "1").size()); |
| idxRoots.delete(); |
| tx.success(); |
| } |
| |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| idxRoots = db.getOrCreateNodeIndex("roots"); |
| idxRoots.flush(); |
| assertEquals(0, idxRoots.query("a", "*").size()); |
| idxRoots.add(x, "a", "2"); |
| tx.success(); |
| } |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| assertEquals(0, idxRoots.query("a", "1").size()); |
| assertEquals(1, idxRoots.query("a", "2").size()); |
| } |
| } |
| |
| @Test |
| public void nodeDelete() throws Exception { |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| IGraphNode n = db.createNode(null, "x"); |
| db.getMetamodelIndex().add(n, "a", 1); |
| tx.success(); |
| } |
| |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| final IGraphIterable<? extends IGraphNode> results = db.getMetamodelIndex().get("a", 1); |
| assertEquals(1, results.size()); |
| results.getSingle().delete(); |
| tx.success(); |
| } |
| |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| final IGraphIterable<? extends IGraphNode> results = db.getMetamodelIndex().get("a", 1); |
| assertEquals(0, results.size()); |
| tx.success(); |
| } |
| } |
| |
| @Test |
| public void indexKeyAdditionRollback() throws Exception { |
| IGraphNode n; |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| n = db.createNode(null, "x"); |
| db.getMetamodelIndex().add(n, "b", 1); |
| tx.success(); |
| } |
| |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| db.getMetamodelIndex().add(n, "a", 1); |
| tx.failure(); |
| } |
| |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| assertEquals(0, db.getMetamodelIndex().query("a", "*").size()); |
| assertEquals(1, db.getMetamodelIndex().query("b", "*").size()); |
| tx.success(); |
| } |
| } |
| |
| @Test |
| public void indexKeyRemovalRollback() throws Exception { |
| IGraphNode n; |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| n = db.createNode(null, "x"); |
| db.getMetamodelIndex().add(n, "b", 1); |
| db.getMetamodelIndex().add(n, "c", "x"); |
| tx.success(); |
| } |
| |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| assertEquals(1, db.getMetamodelIndex().query("b", 1).size()); |
| assertEquals(1, db.getMetamodelIndex().query("c", "x").size()); |
| tx.success(); |
| } |
| |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| db.getMetamodelIndex().remove(n, "b", 1); |
| db.getMetamodelIndex().remove(n, "c", "x"); |
| // NOTE: GreyCat and Orient expose changes immediately, but Neo4j 2.0.5 does not |
| // assertEquals(0, db.getMetamodelIndex().query("b", 1).size()); |
| // assertEquals(0, db.getMetamodelIndex().query("c", "x").size()); |
| tx.failure(); |
| } |
| |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| assertEquals(1, db.getMetamodelIndex().query("b", 1).size()); |
| assertEquals(1, db.getMetamodelIndex().query("c", "x").size()); |
| tx.success(); |
| } |
| } |
| |
| @Test |
| public void indexDeletionRollback() throws Exception { |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| IGraphNode n1 = db.createNode(null, "x"), n2 = db.createNode(null, "y"); |
| db.getMetamodelIndex().add(n1, "b", 1); |
| db.getMetamodelIndex().add(n2, "b", 3); |
| tx.success(); |
| } |
| |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| assertEquals(2, db.getMetamodelIndex().query("b", "*").size()); |
| db.getMetamodelIndex().delete(); |
| db.getMetamodelIndex().flush(); |
| assertEquals(0, db.getMetamodelIndex().query("b", "*").size()); |
| tx.failure(); |
| } |
| |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| assertEquals(2, db.getMetamodelIndex().query("b", "*").size()); |
| tx.success(); |
| } |
| } |
| |
| @Test |
| public void indexNodeDeletionRollback() throws Exception { |
| IGraphNode n1, n2; |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| n1 = db.createNode(null, "x"); |
| n2 = db.createNode(null, "y"); |
| db.getMetamodelIndex().add(n1, "b", 1); |
| db.getMetamodelIndex().add(n2, "b", 3); |
| tx.success(); |
| } |
| |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| assertEquals(2, db.getMetamodelIndex().query("b", "*").size()); |
| db.getMetamodelIndex().remove(n2); |
| assertEquals(1, db.getMetamodelIndex().query("b", "*").size()); |
| tx.failure(); |
| } |
| |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| assertEquals(2, db.getMetamodelIndex().query("b", "*").size()); |
| tx.success(); |
| } |
| } |
| |
| private String populateForRemove() throws Exception { |
| final String mmBarURI = "http://foo/bar"; |
| final Map<String, Object> mmBarNodeProps = Collections.singletonMap(IModelIndexer.IDENTIFIER_PROPERTY, mmBarURI); |
| |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| IGraphNode mmNode = db.createNode(mmBarNodeProps, "metamodel"); |
| final IGraphNodeIndex mmIdx = db.getMetamodelIndex(); |
| mmIdx.add(mmNode, Collections.singletonMap("id", mmBarURI)); |
| |
| IGraphNode mmNode2 = db.createNode(mmBarNodeProps, "metamodel"); |
| mmIdx.add(mmNode2, Collections.singletonMap("id", "file://foo")); |
| |
| tx.success(); |
| } |
| return mmBarURI; |
| } |
| |
| private void checkAfterRemove(final String mmBarURI) throws Exception { |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| final IGraphNodeIndex mmIdx = db.getMetamodelIndex(); |
| |
| assertEquals(0, mmIdx.query("id", mmBarURI).size()); |
| assertEquals(0, mmIdx.query("id", "http://*").size()); |
| assertEquals(1, mmIdx.query("id", "file://*").size()); |
| assertEquals(1, mmIdx.query("id", "fil*://*").size()); |
| assertEquals(1, mmIdx.query("id", "*file://*").size()); |
| } |
| } |
| |
| private IGraphIterable<? extends IGraphNode> checkBeforeRemove(final String mmBarURI) throws Exception { |
| try (IGraphTransaction tx = db.beginTransaction()) { |
| final IGraphIterable<? extends IGraphNode> iter = db.getMetamodelIndex().query("id", mmBarURI); |
| assertEquals(1, iter.size()); |
| tx.success(); |
| return iter; |
| } |
| } |
| |
| private int iteratorSize(Iterator<?> it) { |
| int count = 0; |
| while (it.hasNext()) { |
| it.next(); |
| count++; |
| } |
| return count; |
| } |
| } |