/**
* Copyright (C) 2010-2017 Structr GmbH
*
* This file is part of Structr <http://structr.org>.
*
* Structr 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.
*
* Structr 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 Structr. If not, see <http://www.gnu.org/licenses/>.
*/
package org.structr.common;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.structr.api.DatabaseService;
import org.structr.api.NativeResult;
import org.structr.api.NotFoundException;
import org.structr.api.graph.Relationship;
import org.structr.common.error.FrameworkException;
import org.structr.core.GraphObject;
import org.structr.core.GraphObjectMap;
import org.structr.core.entity.SixOneManyToMany;
import org.structr.core.entity.SixOneOneToOne;
import org.structr.core.entity.TestOne;
import org.structr.core.entity.TestSix;
import org.structr.core.graph.CypherQueryCommand;
import org.structr.core.graph.GraphDatabaseCommand;
import org.structr.core.graph.Tx;
import org.structr.core.property.StringProperty;
/**
*
*/
public class CypherTest extends StructrTest {
private static final Logger logger = LoggerFactory.getLogger(CypherTest.class);
@Test
public void test01DeleteAfterLookupWithCypherInTransaction() {
try {
final TestSix testSix = this.createTestNode(TestSix.class);
final TestOne testOne = this.createTestNode(TestOne.class);
SixOneOneToOne rel = null;
assertNotNull(testSix);
assertNotNull(testOne);
try (final Tx tx = app.tx()) {
rel = app.create(testSix, testOne, SixOneOneToOne.class);
tx.success();
}
assertNotNull(rel);
DatabaseService graphDb = app.command(GraphDatabaseCommand.class).execute();
try (final Tx tx = app.tx()) {
NativeResult<Relationship> result = graphDb.execute("MATCH (n)<-[r:ONE_TO_ONE]-() RETURN r");
final Iterator<Relationship> rels = result.columnAs("r");
assertTrue(rels.hasNext());
rels.next().delete();
tx.success();
}
try (final Tx tx = app.tx()) {
rel.getUuid();
fail("Accessing a deleted relationship should thow an exception.");
tx.success();
} catch (NotFoundException iex) {
}
} catch (FrameworkException ex) {
logger.error(ex.toString());
fail("Unexpected exception");
}
}
@Test
public void test03DeleteDirectly() {
try {
final TestOne testOne = createTestNode(TestOne.class);
final TestSix testSix = createTestNode(TestSix.class);
SixOneOneToOne rel = null;
assertNotNull(testOne);
assertNotNull(testSix);
try (final Tx tx = app.tx()) {
rel = app.create(testSix, testOne, SixOneOneToOne.class);
tx.success();
}
assertNotNull(rel);
try (final Tx tx = app.tx()) {
testOne.getRelationships().iterator().next().getRelationship().delete();
tx.success();
}
try (final Tx tx = app.tx()) {
rel.getUuid();
fail("Accessing a deleted relationship should thow an exception.");
tx.success();
} catch (NotFoundException nfex) {
assertNotNull(nfex.getMessage());
}
} catch (FrameworkException ex) {
logger.error(ex.toString());
fail("Unexpected exception");
}
}
@Test
public void test04DeleteAfterIndexLookup() {
try {
final TestOne testOne = createTestNode(TestOne.class);
final TestSix testSix = createTestNode(TestSix.class);
SixOneOneToOne rel = null;
assertNotNull(testOne);
assertNotNull(testSix);
try (final Tx tx = app.tx()) {
rel = app.create(testSix, testOne, SixOneOneToOne.class);
tx.success();
}
assertNotNull(rel);
try (final Tx tx = app.tx()) {
GraphObject searchRes = app.getNodeById(testSix.getUuid());
assertNotNull(searchRes);
tx.success();
}
try (final Tx tx = app.tx()) {
testSix.getRelationships().iterator().next().getRelationship().delete();
tx.success();
}
try (final Tx tx = app.tx()) {
rel.getUuid();
fail("Accessing a deleted relationship should thow an exception.");
tx.success();
} catch (NotFoundException nfex) {
assertNotNull(nfex.getMessage());
}
} catch (FrameworkException ex) {
logger.error(ex.toString());
fail("Unexpected exception");
}
}
@Test
public void test05RollbackDelete() {
try {
final TestOne testOne = createTestNode(TestOne.class);
final TestSix testSix = createTestNode(TestSix.class);
String relId = null;
SixOneOneToOne rel = null;
assertNotNull(testOne);
assertNotNull(testSix);
try (final Tx tx = app.tx()) {
rel = app.create(testSix, testOne, SixOneOneToOne.class);
relId = rel.getUuid();
tx.success();
}
assertNotNull(rel);
try (final Tx tx = app.tx()) {
// do not commit transaction
testOne.getRelationships().iterator().next().getRelationship().delete();
}
try (final Tx tx = app.tx()) {
assertEquals("UUID of relationship should be readable after rollback", relId, rel.getUuid());
tx.success();
} catch (NotFoundException iex) {
}
} catch (FrameworkException ex) {
logger.error(ex.toString());
fail("Unexpected exception");
}
}
@Test
public void testCypherResultWrapping() {
try (final Tx tx = app.tx()) {
List<TestOne> testOnes = createTestNodes(TestOne.class, 10);
List<TestSix> testSixs = createTestNodes(TestSix.class, 10);
for (final TestOne testOne : testOnes) {
testOne.setProperty(TestOne.manyToManyTestSixs, testSixs);
}
tx.success();
} catch (FrameworkException ex) {
logger.warn("", ex);
fail("Unexpected exception");
}
try (final Tx tx = app.tx()) {
final List<GraphObject> result = app.command(CypherQueryCommand.class).execute("MATCH (n:TestOne) RETURN DISTINCT n");
assertEquals("Invalid wrapped cypher query result", 10, result.size());
for (final GraphObject obj : result) {
System.out.println(obj);
assertEquals("Invalid wrapped cypher query result", TestOne.class, obj.getClass());
}
tx.success();
} catch (FrameworkException ex) {
logger.error("", ex);
}
try (final Tx tx = app.tx()) {
final List<GraphObject> result = app.command(CypherQueryCommand.class).execute("MATCH (n:TestOne)-[r]-(m:TestSix) RETURN DISTINCT n, r, m ");
final Iterator<GraphObject> it = result.iterator();
assertEquals("Invalid wrapped cypher query result", 300, result.size());
while (it.hasNext()) {
assertEquals("Invalid wrapped cypher query result", TestOne.class, it.next().getClass()); // n
assertEquals("Invalid wrapped cypher query result", SixOneManyToMany.class, it.next().getClass()); // r
assertEquals("Invalid wrapped cypher query result", TestSix.class, it.next().getClass()); // m
}
tx.success();
} catch (FrameworkException ex) {
logger.error("", ex);
}
try (final Tx tx = app.tx()) {
final List<GraphObject> result = app.command(CypherQueryCommand.class).execute("MATCH p = (n:TestOne)-[r]-(m:TestSix) RETURN p ");
assertEquals("Invalid wrapped cypher query result", 100, result.size());
for (final GraphObject obj : result) {
assertEquals("Invalid wrapped cypher query result", GraphObjectMap.class, obj.getClass());
}
tx.success();
} catch (FrameworkException ex) {
logger.error("", ex);
}
try (final Tx tx = app.tx()) {
final List<GraphObject> result = app.command(CypherQueryCommand.class).execute("MATCH p = (n:TestOne)-[r]-(m:TestSix) RETURN { nodes: nodes(p), rels: relationships(p) } ");
assertEquals("Invalid wrapped cypher query result", 100, result.size());
for (final GraphObject obj : result) {
assertEquals("Invalid wrapped cypher query result", GraphObjectMap.class, obj.getClass());
final Object nodes = obj.getProperty(new StringProperty("nodes"));
final Object rels = obj.getProperty(new StringProperty("rels"));
assertTrue("Invalid wrapped cypher query result", nodes instanceof Collection);
assertTrue("Invalid wrapped cypher query result", rels instanceof Collection);
final Iterator it = ((Collection)nodes).iterator();
while (it.hasNext()) {
assertEquals("Invalid wrapped cypher query result", TestOne.class, it.next().getClass());
assertEquals("Invalid wrapped cypher query result", TestSix.class, it.next().getClass());
}
for (final Object node : ((Collection)rels)) {
assertEquals("Invalid wrapped cypher query result", SixOneManyToMany.class, node.getClass());
}
}
tx.success();
} catch (FrameworkException ex) {
logger.error("", ex);
}
try (final Tx tx = app.tx()) {
final List<GraphObject> result = app.command(CypherQueryCommand.class).execute("MATCH p = (n:TestOne)-[r]-(m:TestSix) RETURN DISTINCT { path: p, value: 12 } ");
assertEquals("Invalid wrapped cypher query result", 100, result.size());
final Iterator it = result.iterator();
while (it.hasNext()) {
final Object path = it.next();
final Object value = it.next();
assertEquals("Invalid wrapped cypher query result", GraphObjectMap.class, path.getClass());
assertEquals("Invalid wrapped cypher query result", GraphObjectMap.class, value.getClass());
assertEquals("Invalid wrapped cypher query result", 12L, ((GraphObjectMap)value).getProperty(new StringProperty("value")));
}
tx.success();
} catch (FrameworkException ex) {
logger.error("", ex);
}
try (final Tx tx = app.tx()) {
final List<GraphObject> result = app.command(CypherQueryCommand.class).execute("MATCH p = (n:TestOne)-[r]-(m:TestSix) RETURN { nodes: { x : { y : { z : nodes(p) } } } } ");
assertEquals("Invalid wrapped cypher query result", 100, result.size());
for (final GraphObject obj : result) {
assertEquals("Invalid wrapped cypher query result", GraphObjectMap.class, obj.getClass());
final Object nodes = obj.getProperty(new StringProperty("nodes"));
assertTrue("Invalid wrapped cypher query result", nodes instanceof GraphObjectMap);
final Object x = ((GraphObjectMap)nodes).getProperty(new StringProperty("x"));
assertTrue("Invalid wrapped cypher query result", x instanceof GraphObjectMap);
final Object y = ((GraphObjectMap)x).getProperty(new StringProperty("y"));
assertTrue("Invalid wrapped cypher query result", y instanceof GraphObjectMap);
final Object z = ((GraphObjectMap)y).getProperty(new StringProperty("z"));
assertTrue("Invalid wrapped cypher query result", z instanceof Collection);
}
tx.success();
} catch (FrameworkException ex) {
logger.error("", ex);
}
/*
try (final Tx tx = app.tx()) {
final List<GraphObject> result = app.command(CypherQueryCommand.class).execute("MATCH p = (n:TestOne)-[r]-(m:TestSix) RETURN p");
assertEquals("Invalid wrapped cypher query result", 100, result.size());
for (final GraphObject obj : result) {
assertEquals("Invalid wrapped cypher query result", GraphObjectMap.class, obj.getClass());
final Object paths = obj.getProperty(new StringProperty("p"));
assertTrue("Invalid wrapped cypher query result", paths instanceof Iterable);
final Iterator it = ((Iterable)paths).iterator();
while (it.hasNext()) {
assertEquals("Invalid wrapped cypher query result", TestOne.class, it.next().getClass()); // n
assertEquals("Invalid wrapped cypher query result", SixOneManyToMany.class, it.next().getClass()); // r
assertEquals("Invalid wrapped cypher query result", TestSix.class, it.next().getClass()); // m
}
}
tx.success();
} catch (FrameworkException ex) {
logger.error("", ex);
}
*/
}
}