Package com.graphaware.tx.event.batch

Source Code of com.graphaware.tx.event.batch.TransactionSimulatingBatchInserterIntegrationTest$OtherNodeNameIncludingRelationshipPropertiesExtractor

/*
* Copyright (c) 2013 GraphAware
*
* This file is part of GraphAware.
*
* GraphAware 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.
*
* This program 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 this program.  If not, see
* <http://www.gnu.org/licenses/>.
*/

package com.graphaware.tx.event.batch;

import com.graphaware.tx.event.batch.api.TransactionSimulatingBatchInserter;
import com.graphaware.tx.event.batch.api.TransactionSimulatingBatchInserterImpl;
import com.graphaware.tx.event.batch.propertycontainer.inserter.BatchInserterNode;
import com.graphaware.tx.event.batch.propertycontainer.inserter.BatchInserterRelationship;
import com.graphaware.tx.event.improved.api.Change;
import com.graphaware.tx.event.improved.api.ImprovedTransactionData;
import com.graphaware.tx.event.improved.api.LazyTransactionData;
import com.graphaware.tx.executor.single.SimpleTransactionExecutor;
import com.graphaware.tx.executor.single.VoidReturningCallback;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.neo4j.graphdb.*;
import org.neo4j.graphdb.event.TransactionData;
import org.neo4j.graphdb.event.TransactionEventHandler;
import org.neo4j.graphdb.factory.GraphDatabaseFactory;
import org.neo4j.graphdb.traversal.Evaluators;
import org.neo4j.graphdb.traversal.TraversalDescription;
import org.neo4j.graphdb.traversal.Uniqueness;
import org.neo4j.kernel.impl.traversal.MonoDirectionalTraversalDescription;
import org.neo4j.unsafe.batchinsert.BatchInserters;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

import static com.graphaware.common.util.IterableUtils.count;
import static com.graphaware.common.util.PropertyContainerUtils.propertiesToMap;
import static com.graphaware.common.util.PropertyContainerUtils.propertyContainersToMap;
import static com.graphaware.tx.event.improved.api.Change.*;
import static org.junit.Assert.*;
import static org.neo4j.graphdb.Direction.*;
import static org.neo4j.graphdb.DynamicRelationshipType.withName;

/**
* Integration test for {@link TransactionSimulatingBatchInserter}.
*/
public class TransactionSimulatingBatchInserterIntegrationTest {

    private TransactionSimulatingBatchInserter batchInserter;
    private TemporaryFolder temporaryFolder = new TemporaryFolder();

    @Before
    public void createTemporaryFolder() throws IOException {
        temporaryFolder.create();
    }

    @After
    public void tearDown() {
        temporaryFolder.delete();
    }

    private Node getNodeById(long id) {
        return new BatchInserterNode(id, batchInserter);
    }

    private Relationship getRelationshipById(long id) {
        return new BatchInserterRelationship(batchInserter.getRelationshipById(id), batchInserter);
    }

    @Test
    public void nothingShouldEverBeDeleted() {
        createBatchInserter();
        mutateGraph(
                new BeforeCommitCallback() {
                    @Override
                    public void doBeforeCommit(ImprovedTransactionData transactionData) {
                        assertTrue(transactionData.mutationsOccurred());

                        assertFalse(transactionData.hasBeenDeleted(getNodeById(1)));
                        assertFalse(transactionData.hasBeenDeleted(getRelationshipById(1)));
                    }
                }
        );
    }

    @Test
    public void createdRelationshipsShouldBeCorrectlyIdentified() {
        createBatchInserter();
        mutateGraph(
                new BeforeCommitCallback() {
                    @Override
                    public void doBeforeCommit(ImprovedTransactionData transactionData) {
                        assertTrue(transactionData.mutationsOccurred());

                        Map<Long, Relationship> created = propertyContainersToMap(transactionData.getAllCreatedRelationships());
                        assertEquals(2, created.size());

                        long r1Id = getNodeById(5).getSingleRelationship(withName("R5"), OUTGOING).getId();
                        Relationship r1 = created.get(r1Id);
                        assertEquals(4, r1.getProperty("time"));
                        assertEquals(1, count(r1.getPropertyKeys()));

                        long r2Id = getNodeById(1).getSingleRelationship(withName("R4"), OUTGOING).getId();
                        Relationship r2 = created.get(r2Id);
                        assertEquals(0, count(r2.getPropertyKeys()));

                        try {
                            r2.getProperty("non-existing");
                            fail();
                        } catch (NotFoundException e) {
                            //ok
                        }

                        assertTrue(transactionData.hasBeenCreated(r1));
                        assertTrue(transactionData.hasBeenCreated(r2));
                        assertFalse(transactionData.hasBeenCreated(getNodeById(3).getSingleRelationship(withName("R1"), OUTGOING)));

                        //in contrast to filtered version:
                        assertTrue(r2.getEndNode().hasProperty("place"));
                        assertNotNull(r2.getEndNode().getSingleRelationship(withName("R3"), OUTGOING));

                        //directions:
                        Node startNode = r1.getStartNode();
                        Node endNode = r1.getEndNode();
                        assertEquals(startNode, r1.getOtherNode(endNode));
                        assertEquals(endNode, r1.getOtherNode(startNode));
                        assertEquals(startNode, r1.getNodes()[0]);
                        assertEquals(endNode, r1.getNodes()[1]);

                        try {
                            r1.getOtherNode(r2.getStartNode());
                            fail();
                        } catch (IllegalArgumentException e) {
                            //OK
                        }

                        //type:
                        assertTrue(r1.isType(withName("R5")));
                    }
                }
        );
    }

    @Test
    public void startingWithCreatedRelationshipCurrentGraphVersionShouldBeTraversed() {
        createBatchInserter();
        mutateGraph(
                new BeforeCommitCallback() {
                    @Override
                    public void doBeforeCommit(ImprovedTransactionData transactionData) {
                        assertTrue(transactionData.mutationsOccurred());

                        Map<Long, Relationship> created = propertyContainersToMap(transactionData.getAllCreatedRelationships());

                        long r2Id = getNodeById(1).getSingleRelationship(withName("R4"), OUTGOING).getId();
                        Relationship r2 = created.get(r2Id);

                        assertEquals("NewOne", r2.getStartNode().getProperty("name"));
                        assertFalse(r2.getStartNode().hasProperty("count"));
                        assertTrue(Arrays.equals(new String[]{"one", "three"}, (String[]) r2.getStartNode().getProperty("tags")));

                        assertNotNull(r2.getEndNode().getSingleRelationship(withName("R3"), INCOMING));
                        assertEquals(2, r2.getEndNode().getSingleRelationship(withName("R2"), INCOMING).getStartNode().getId());
                        assertEquals(5, r2.getEndNode().getSingleRelationship(withName("R5"), INCOMING).getStartNode().getId());
                    }
                }
        );
    }

    @Test
    public void changedRelationshipsShouldBeCorrectlyIdentified() {
        createBatchInserter();
        mutateGraph(
                new BeforeCommitCallback() {
                    @Override
                    public void doBeforeCommit(ImprovedTransactionData transactionData) {
                        assertTrue(transactionData.mutationsOccurred());

                        Map<Long, Change<Relationship>> changed = changesToMap(transactionData.getAllChangedRelationships());
                        assertEquals(1, changed.size());

                        Relationship previous = changed.entrySet().iterator().next().getValue().getPrevious();
                        assertEquals(2, count(previous.getPropertyKeys()));
                        assertEquals(3, previous.getProperty("time"));
                        assertEquals("cool", previous.getProperty("tag"));

                        Relationship current = changed.entrySet().iterator().next().getValue().getCurrent();
                        assertEquals(2, count(current.getPropertyKeys()));
                        assertEquals(4, current.getProperty("time"));
                        assertEquals("cool", current.getProperty("tags"));

                        assertTrue(transactionData.hasBeenChanged(previous));
                        assertTrue(transactionData.hasBeenChanged(current));
                        assertFalse(transactionData.hasBeenChanged(getNodeById(3).getSingleRelationship(withName("R1"), OUTGOING)));
                    }
                }
        );
    }

    @Test
    public void startingWithPreviousChangedRelationshipPreviousGraphVersionShouldBeTraversedUsingNativeApi() {
        createBatchInserter();
        mutateGraph(
                new BeforeCommitCallback() {
                    @Override
                    public void doBeforeCommit(ImprovedTransactionData transactionData) {
                        assertTrue(transactionData.mutationsOccurred());

                        Map<Long, Change<Relationship>> changed = changesToMap(transactionData.getAllChangedRelationships());
                        Relationship previous = changed.entrySet().iterator().next().getValue().getPrevious();

                        assertEquals("One", previous.getEndNode().getProperty("name"));
                        assertEquals(1, previous.getEndNode().getProperty("count", 2));
                        assertTrue(Arrays.equals(new String[]{"one", "two"}, (String[]) previous.getEndNode().getProperty("tags")));
                        assertEquals(4, count(previous.getEndNode().getPropertyKeys()));

                        assertEquals("Three", previous.getStartNode().getProperty("name"));
                        assertEquals("London", previous.getStartNode().getProperty("place"));
                        assertEquals("nothing", previous.getStartNode().getProperty("tags", "nothing"));

                        Node endNode = previous.getEndNode();
                        Relationship r1 = endNode.getSingleRelationship(withName("R1"), OUTGOING);
                        Node endNode1 = r1.getEndNode();
                        assertEquals("Two", endNode1.getProperty("name"));
                    }
                }
        );
    }

    @Test
    public void startingWithPreviousChangedRelationshipPreviousGraphVersionShouldBeTraversedUsingTraversalApi() {
        createBatchInserter();
        mutateGraph(
                new BeforeCommitCallback() {
                    @Override
                    public void doBeforeCommit(ImprovedTransactionData transactionData) {
                        assertTrue(transactionData.mutationsOccurred());

                        Map<Long, Change<Relationship>> changed = changesToMap(transactionData.getAllChangedRelationships());
                        Relationship previous = changed.entrySet().iterator().next().getValue().getPrevious();

                        TraversalDescription traversalDescription = new MonoDirectionalTraversalDescription()
                                .relationships(withName("R1"), OUTGOING)
                                .relationships(withName("R2"), OUTGOING)
                                .depthFirst()
                                .uniqueness(Uniqueness.NODE_GLOBAL)
                                .evaluator(Evaluators.toDepth(3));

                        assertEquals(4, count(traversalDescription.traverse(previous.getEndNode()).nodes()));
                    }
                }
        );
    }

    @Test
    public void startingWithCurrentChangedRelationshipCurrentGraphVersionShouldBeTraversedUsingNativeApi() {
        createBatchInserter();
        mutateGraph(
                new BeforeCommitCallback() {
                    @Override
                    public void doBeforeCommit(ImprovedTransactionData transactionData) {
                        assertTrue(transactionData.mutationsOccurred());

                        Map<Long, Change<Relationship>> changed = changesToMap(transactionData.getAllChangedRelationships());
                        Relationship current = changed.entrySet().iterator().next().getValue().getCurrent();

                        current = transactionData.getChanged(current).getCurrent();

                        assertEquals("NewOne", current.getEndNode().getProperty("name"));
                        assertEquals(2, current.getEndNode().getProperty("count", 2));
                        assertFalse(current.getEndNode().hasProperty("count"));
                        assertTrue(Arrays.equals(new String[]{"one", "three"}, (String[]) current.getEndNode().getProperty("tags")));
                        assertEquals(2, count(current.getEndNode().getPropertyKeys()));

                        assertEquals("Three", current.getStartNode().getProperty("name"));
                        assertEquals("London", current.getStartNode().getProperty("place"));
                        assertEquals("one", current.getStartNode().getProperty("tags"));
                    }
                }
        );
    }

    @Test
    public void startingWithCurrentChangedRelationshipCurrentGraphVersionShouldBeTraversedUsingTraversalApi() {
        createBatchInserter();
        mutateGraph(
                new BeforeCommitCallback() {
                    @Override
                    public void doBeforeCommit(ImprovedTransactionData transactionData) {
                        assertTrue(transactionData.mutationsOccurred());

                        Map<Long, Change<Relationship>> changed = changesToMap(transactionData.getAllChangedRelationships());
                        Relationship current = changed.entrySet().iterator().next().getValue().getCurrent();

                        TraversalDescription traversalDescription = new MonoDirectionalTraversalDescription()
                                .relationships(withName("R1"), OUTGOING)
                                .relationships(withName("R2"), OUTGOING)
                                .depthFirst()
                                .uniqueness(Uniqueness.NODE_GLOBAL);

                        assertEquals(4, count(traversalDescription.traverse(current.getEndNode()).nodes()));
                    }
                }
        );
    }

    @Test
    public void deletedRelationshipsShouldBeCorrectlyIdentified() {
        createBatchInserter();
        mutateGraph(
                new BeforeCommitCallback() {
                    @Override
                    public void doBeforeCommit(ImprovedTransactionData transactionData) {
                        assertTrue(transactionData.mutationsOccurred());

                        Map<Long, Relationship> deleted = propertyContainersToMap(transactionData.getAllDeletedRelationships());
                        assertEquals(0, deleted.size())//no deletes in batch
                    }
                }
        );
    }

    @Test
    public void createdRelationshipPropertiesShouldBeCorrectlyIdentified() {
        createBatchInserter();
        mutateGraph(
                new BeforeCommitCallback() {
                    @Override
                    public void doBeforeCommit(ImprovedTransactionData transactionData) {
                        assertTrue(transactionData.mutationsOccurred());

                        Change<Relationship> change = transactionData.getAllChangedRelationships().iterator().next();

                        assertTrue(transactionData.hasPropertyBeenCreated(change.getCurrent(), "tags"));
                        assertFalse(transactionData.hasPropertyBeenCreated(change.getCurrent(), "time"));
                        assertTrue(transactionData.hasPropertyBeenCreated(change.getPrevious(), "tags"));
                        assertFalse(transactionData.hasPropertyBeenCreated(change.getPrevious(), "tag"));

                        assertEquals(1, transactionData.createdProperties(change.getCurrent()).size());
                        assertEquals(1, transactionData.createdProperties(change.getPrevious()).size());
                        assertEquals("cool", transactionData.createdProperties(change.getCurrent()).get("tags"));
                        assertEquals("cool", transactionData.createdProperties(change.getPrevious()).get("tags"));

                        //created relationship should not fall into this category
                        assertFalse(transactionData.hasPropertyBeenCreated(getNodeById(5).getSingleRelationship(withName("R5"), OUTGOING), "time"));
                    }
                }
        );
    }

    @Test
    public void changedRelationshipPropertiesShouldBeCorrectlyIdentified() {
        createBatchInserter();
        mutateGraph(
                new BeforeCommitCallback() {
                    @Override
                    public void doBeforeCommit(ImprovedTransactionData transactionData) {
                        assertTrue(transactionData.mutationsOccurred());

                        Change<Relationship> change = transactionData.getAllChangedRelationships().iterator().next();

                        assertTrue(transactionData.hasPropertyBeenChanged(change.getCurrent(), "time"));
                        assertFalse(transactionData.hasPropertyBeenChanged(change.getCurrent(), "tags"));
                        assertTrue(transactionData.hasPropertyBeenChanged(change.getPrevious(), "time"));
                        assertFalse(transactionData.hasPropertyBeenChanged(change.getPrevious(), "tag"));

                        assertEquals(1, transactionData.changedProperties(change.getCurrent()).size());
                        assertEquals(1, transactionData.changedProperties(change.getPrevious()).size());
                        assertEquals(3, transactionData.changedProperties(change.getCurrent()).get("time").getPrevious());
                        assertEquals(3, transactionData.changedProperties(change.getPrevious()).get("time").getPrevious());
                        assertEquals(4, transactionData.changedProperties(change.getCurrent()).get("time").getCurrent());
                        assertEquals(4, transactionData.changedProperties(change.getPrevious()).get("time").getCurrent());
                    }
                }
        );
    }

    @Test
    public void deletedRelationshipPropertiesShouldBeCorrectlyIdentified() {
        createBatchInserter();
        mutateGraph(
                new BeforeCommitCallback() {
                    @Override
                    public void doBeforeCommit(ImprovedTransactionData transactionData) {
                        assertTrue(transactionData.mutationsOccurred());

                        Change<Relationship> change = transactionData.getAllChangedRelationships().iterator().next();

                        assertTrue(transactionData.hasPropertyBeenDeleted(change.getCurrent(), "tag"));
                        assertFalse(transactionData.hasPropertyBeenDeleted(change.getCurrent(), "time"));
                        assertTrue(transactionData.hasPropertyBeenDeleted(change.getPrevious(), "tag"));
                        assertFalse(transactionData.hasPropertyBeenDeleted(change.getPrevious(), "tags"));

                        assertEquals(1, transactionData.deletedProperties(change.getCurrent()).size());
                        assertEquals(1, transactionData.deletedProperties(change.getPrevious()).size());
                        assertEquals("cool", transactionData.deletedProperties(change.getCurrent()).get("tag"));
                        assertEquals("cool", transactionData.deletedProperties(change.getPrevious()).get("tag"));

                        assertFalse(transactionData.hasPropertyBeenDeleted(transactionData.getAllCreatedRelationships().iterator().next(), "tags"));
                    }
                }
        );
    }

    @Test
    public void createdNodesShouldBeCorrectlyIdentified() {
        createBatchInserter();
        mutateGraph(
                new BeforeCommitCallback() {
                    @Override
                    public void doBeforeCommit(ImprovedTransactionData transactionData) {
                        assertTrue(transactionData.mutationsOccurred());

                        Map<Long, Node> createdNodes = propertyContainersToMap(transactionData.getAllCreatedNodes());
                        assertEquals(1, createdNodes.size());

                        Node createdNode = createdNodes.get(5L);
                        assertEquals("Five", createdNode.getProperty("name"));
                        assertEquals(4L, createdNode.getProperty("size"));
                        assertEquals(2, count(createdNode.getPropertyKeys()));

                        try {
                            createdNode.getProperty("non-existing");
                            fail();
                        } catch (NotFoundException e) {
                            //ok
                        }

                        assertTrue(transactionData.hasBeenCreated(createdNode));
                        assertFalse(transactionData.hasBeenCreated(getNodeById(3)));
                    }
                }
        );
    }

    @Test
    public void startingWithCreatedNodeCurrentGraphVersionShouldBeTraversed() {
        createBatchInserter();
        mutateGraph(
                new BeforeCommitCallback() {
                    @Override
                    public void doBeforeCommit(ImprovedTransactionData transactionData) {
                        assertTrue(transactionData.mutationsOccurred());

                        Map<Long, Node> createdNodes = propertyContainersToMap(transactionData.getAllCreatedNodes());
                        Node createdNode = createdNodes.get(5L);

                        assertEquals("one", createdNode.getSingleRelationship(withName("R5"), OUTGOING).getEndNode().getProperty("tags"));
                    }
                }
        );
    }

    @Test
    public void changedNodesShouldBeCorrectlyIdentified() {
        createBatchInserter();
        mutateGraph(
                new BeforeCommitCallback() {
                    @Override
                    public void doBeforeCommit(ImprovedTransactionData transactionData) {
                        assertTrue(transactionData.mutationsOccurred());

                        Map<Long, Change<Node>> changed = changesToMap(transactionData.getAllChangedNodes());
                        assertEquals(2, changed.size());

                        Node previous1 = changed.get(1L).getPrevious();
                        assertEquals(4, count(previous1.getPropertyKeys()));
                        assertEquals("One", previous1.getProperty("name"));
                        assertEquals(1, previous1.getProperty("count"));
                        assertEquals("something", previous1.getProperty("something"));
                        assertTrue(Arrays.equals(new String[]{"one", "two"}, (String[]) previous1.getProperty("tags")));

                        Node current1 = changed.get(1L).getCurrent();
                        assertEquals(2, count(current1.getPropertyKeys()));
                        assertEquals("NewOne", current1.getProperty("name"));
                        assertTrue(Arrays.equals(new String[]{"one", "three"}, (String[]) current1.getProperty("tags")));

                        Node previous2 = changed.get(3L).getPrevious();
                        assertEquals(2, count(previous2.getPropertyKeys()));
                        assertEquals("Three", previous2.getProperty("name"));
                        assertEquals("London", previous2.getProperty("place"));

                        Node current2 = changed.get(3L).getCurrent();
                        assertEquals(3, count(current2.getPropertyKeys()));
                        assertEquals("Three", current2.getProperty("name"));
                        assertEquals("London", current2.getProperty("place"));
                        assertEquals("one", current2.getProperty("tags"));

                        assertTrue(transactionData.hasBeenChanged(previous1));
                        assertTrue(transactionData.hasBeenChanged(previous2));
                        assertTrue(transactionData.hasBeenChanged(current1));
                        assertTrue(transactionData.hasBeenChanged(current2));
                        assertFalse(transactionData.hasBeenChanged(getNodeById(4)));

                    }
                }
        );
    }

    @Test
    public void startingWithPreviousChangedNodePreviousGraphVersionShouldBeTraversedUsingNativeApi() {
        createBatchInserter();
        mutateGraph(
                new BeforeCommitCallback() {
                    @Override
                    public void doBeforeCommit(ImprovedTransactionData transactionData) {
                        assertTrue(transactionData.mutationsOccurred());

                        Map<Long, Change<Node>> changed = changesToMap(transactionData.getAllChangedNodes());

                        Node current = changed.get(1L).getCurrent();
                        Node previous = transactionData.getChanged(current).getPrevious();

                        assertEquals(1, previous.getSingleRelationship(withName("R1"), OUTGOING).getProperty("time"));
                        assertEquals("Two", previous.getRelationships(withName("R1"), OUTGOING).iterator().next().getEndNode().getProperty("name"));
                        assertEquals("Three", previous.getRelationships(OUTGOING, withName("R3")).iterator().next().getEndNode().getProperty("name"));
                        assertEquals(2L, previous.getRelationships(withName("R1")).iterator().next().getEndNode().getProperty("size"));

                        assertNull(previous.getSingleRelationship(withName("R1"), INCOMING));
                        assertEquals(4, count(previous.getRelationships()));
                        assertEquals(3, count(previous.getRelationships(withName("R1"), withName("R3"))));
                        assertEquals(1, count(previous.getRelationships(withName("R1"))));
                        assertEquals(3, count(previous.getRelationships(OUTGOING)));
                        assertEquals(1, count(previous.getRelationships(INCOMING)));
                        assertEquals(1, count(previous.getRelationships(OUTGOING, withName("R3"))));
                        assertEquals(2, count(previous.getRelationships(OUTGOING, withName("R1"), withName("R3"))));
                        assertEquals(1, count(previous.getRelationships(withName("R3"), OUTGOING)));

                        assertTrue(previous.hasRelationship());
                        assertTrue(previous.hasRelationship(withName("R1"), withName("R3")));
                        assertTrue(previous.hasRelationship(withName("R1")));
                        assertTrue(previous.hasRelationship(OUTGOING));
                        assertTrue(previous.hasRelationship(INCOMING));
                        assertTrue(previous.hasRelationship(OUTGOING, withName("R3")));
                        assertTrue(previous.hasRelationship(OUTGOING, withName("R1"), withName("R3")));
                        assertTrue(previous.hasRelationship(withName("R3"), OUTGOING));

                        assertFalse(previous.hasRelationship(withName("R1"), INCOMING));
                        assertFalse(previous.hasRelationship(withName("R2")));
                        assertNull(previous.getSingleRelationship(withName("R1"), INCOMING));

                        previous.createRelationshipTo(getNodeById(4), withName("R3"));
                        try {
                            previous.getSingleRelationship(withName("R3"), OUTGOING);
                            fail();
                        } catch (NotFoundException e) {
                            //ok
                        }
                    }
                }
        );
    }

    @Test
    public void startingWithPreviousChangedNodePreviousGraphVersionShouldBeTraversedUsingTraversalApi() {
        createBatchInserter();
        mutateGraph(
                new BeforeCommitCallback() {
                    @Override
                    public void doBeforeCommit(ImprovedTransactionData transactionData) {
                        assertTrue(transactionData.mutationsOccurred());

                        Map<Long, Change<Node>> changed = changesToMap(transactionData.getAllChangedNodes());

                        Node previous = changed.get(1L).getPrevious();

                        TraversalDescription traversalDescription = new MonoDirectionalTraversalDescription()
                                .relationships(withName("R1"), OUTGOING)
                                .relationships(withName("R2"), OUTGOING)
                                .depthFirst()
                                .uniqueness(Uniqueness.NODE_GLOBAL)
                                .evaluator(Evaluators.toDepth(3));

                        assertEquals(4, count(traversalDescription.traverse(previous).nodes()));
                    }
                }
        );
    }

    @Test
    public void startingWithCurrentChangedNodeCurrentGraphVersionShouldBeTraversedUsingNativeApi() {
        createBatchInserter();
        mutateGraph(
                new BeforeCommitCallback() {
                    @Override
                    public void doBeforeCommit(ImprovedTransactionData transactionData) {
                        assertTrue(transactionData.mutationsOccurred());

                        Map<Long, Change<Node>> changed = changesToMap(transactionData.getAllChangedNodes());
                        Node current = changed.get(1L).getCurrent();

                        assertEquals("Three", current.getSingleRelationship(withName("R4"), OUTGOING).getEndNode().getProperty("name"));
                        assertEquals("London", current.getRelationships(withName("R4"), OUTGOING).iterator().next().getEndNode().getProperty("place"));
                        assertEquals("one", current.getRelationships(OUTGOING, withName("R4")).iterator().next().getEndNode().getProperty("tags"));
                    }
                }
        );
    }

    @Test
    public void startingWithCurrentChangedNodeCurrentGraphVersionShouldBeTraversed() {
        createBatchInserter();
        mutateGraph(
                new BeforeCommitCallback() {
                    @Override
                    public void doBeforeCommit(ImprovedTransactionData transactionData) {
                        assertTrue(transactionData.mutationsOccurred());

                        Map<Long, Change<Node>> changed = changesToMap(transactionData.getAllChangedNodes());
                        Node current = changed.get(1L).getCurrent();

                        TraversalDescription traversalDescription = new MonoDirectionalTraversalDescription()
                                .relationships(withName("R1"), OUTGOING)
                                .relationships(withName("R2"), OUTGOING)
                                .depthFirst()
                                .uniqueness(Uniqueness.NODE_GLOBAL);

                        assertEquals(4, count(traversalDescription.traverse(current).nodes()));

                    }
                }
        );
    }

    @Test
    public void createdNodePropertiesShouldBeCorrectlyIdentified() {
        createBatchInserter();
        mutateGraph(
                new BeforeCommitCallback() {
                    @Override
                    public void doBeforeCommit(ImprovedTransactionData transactionData) {
                        assertTrue(transactionData.mutationsOccurred());

                        Change<Node> changed = changesToMap(transactionData.getAllChangedNodes()).get(3L);

                        assertTrue(transactionData.hasPropertyBeenCreated(changed.getCurrent(), "tags"));
                        assertFalse(transactionData.hasPropertyBeenCreated(changed.getCurrent(), "name"));
                        assertTrue(transactionData.hasPropertyBeenCreated(changed.getPrevious(), "tags"));
                        assertFalse(transactionData.hasPropertyBeenCreated(changed.getPrevious(), "name"));

                        assertEquals(1, transactionData.createdProperties(changed.getCurrent()).size());
                        assertEquals(1, transactionData.createdProperties(changed.getPrevious()).size());
                        assertEquals("one", transactionData.createdProperties(changed.getCurrent()).get("tags"));
                        assertEquals("one", transactionData.createdProperties(changed.getPrevious()).get("tags"));

                        assertFalse(transactionData.hasPropertyBeenCreated(changesToMap(transactionData.getAllChangedNodes()).get(1L).getCurrent(), "tags"));
                    }
                }
        );
    }

    @Test
    public void changedNodePropertiesShouldBeCorrectlyIdentified() {
        createBatchInserter();
        mutateGraph(
                new BeforeCommitCallback() {
                    @Override
                    public void doBeforeCommit(ImprovedTransactionData transactionData) {
                        assertTrue(transactionData.mutationsOccurred());

                        Change<Node> changed = changesToMap(transactionData.getAllChangedNodes()).get(1L);

                        assertTrue(transactionData.hasPropertyBeenChanged(changed.getCurrent(), "name"));
                        assertTrue(transactionData.hasPropertyBeenChanged(changed.getCurrent(), "tags"));
                        assertFalse(transactionData.hasPropertyBeenChanged(changed.getCurrent(), "count"));
                        assertTrue(transactionData.hasPropertyBeenChanged(changed.getPrevious(), "name"));
                        assertTrue(transactionData.hasPropertyBeenChanged(changed.getPrevious(), "tags"));
                        assertFalse(transactionData.hasPropertyBeenChanged(changed.getPrevious(), "count"));

                        assertEquals(2, transactionData.changedProperties(changed.getCurrent()).size());
                        assertEquals(2, transactionData.changedProperties(changed.getPrevious()).size());
                        assertEquals("One", transactionData.changedProperties(changed.getCurrent()).get("name").getPrevious());
                        assertEquals("One", transactionData.changedProperties(changed.getPrevious()).get("name").getPrevious());
                        assertEquals("NewOne", transactionData.changedProperties(changed.getCurrent()).get("name").getCurrent());
                        assertEquals("NewOne", transactionData.changedProperties(changed.getPrevious()).get("name").getCurrent());
                        assertTrue(Arrays.equals(new String[]{"one", "three"}, (String[]) transactionData.changedProperties(changed.getCurrent()).get("tags").getCurrent()));
                        assertTrue(Arrays.equals(new String[]{"one", "two"}, (String[]) transactionData.changedProperties(changed.getPrevious()).get("tags").getPrevious()));
                        assertTrue(Arrays.equals(new String[]{"one", "three"}, (String[]) transactionData.changedProperties(changed.getCurrent()).get("tags").getCurrent()));
                        assertTrue(Arrays.equals(new String[]{"one", "two"}, (String[]) transactionData.changedProperties(changed.getPrevious()).get("tags").getPrevious()));

                        assertEquals(4, count(changed.getPrevious().getPropertyKeys()));
                        assertEquals(2, count(changed.getCurrent().getPropertyKeys()));

                        changed = changesToMap(transactionData.getAllChangedNodes()).get(3L);
                        assertEquals(0, transactionData.changedProperties(changed.getCurrent()).size());
                        assertEquals(0, transactionData.changedProperties(changed.getPrevious()).size());
                        assertFalse(transactionData.hasPropertyBeenChanged(changed.getCurrent(), "name"));
                        assertFalse(transactionData.hasPropertyBeenChanged(changed.getCurrent(), "tags"));
                        assertFalse(transactionData.hasPropertyBeenChanged(changed.getCurrent(), "place"));
                        assertFalse(transactionData.hasPropertyBeenChanged(changed.getPrevious(), "name"));
                        assertFalse(transactionData.hasPropertyBeenChanged(changed.getPrevious(), "tags"));
                        assertFalse(transactionData.hasPropertyBeenChanged(changed.getPrevious(), "place"));

                        assertFalse(transactionData.hasPropertyBeenChanged(transactionData.getAllCreatedNodes().iterator().next(), "name"));

                        assertEquals(2, count(changed.getPrevious().getPropertyKeys()));
                        assertEquals(3, count(changed.getCurrent().getPropertyKeys()));

                        //one that isn't changed
                        Node unchanged = changesToMap(transactionData.getAllChangedNodes()).get(1L).getPrevious().getSingleRelationship(withName("R3"), OUTGOING).getEndNode().getSingleRelationship(withName("R1"), OUTGOING).getEndNode();
                        assertEquals(1, count(unchanged.getPropertyKeys()));
                        assertEquals("name", unchanged.getPropertyKeys().iterator().next());
                        assertEquals("Four", unchanged.getProperty("name"));
                        assertEquals("Four", unchanged.getProperty("name", "nothing"));
                        assertEquals("nothing", unchanged.getProperty("non-existing", "nothing"));

                    }
                }
        );
    }

    @Test
    public void deletedNodePropertiesShouldBeCorrectlyIdentified() {
        createBatchInserter();
        mutateGraph(
                new BeforeCommitCallback() {
                    @Override
                    public void doBeforeCommit(ImprovedTransactionData transactionData) {
                        assertTrue(transactionData.mutationsOccurred());

                        Change<Node> changed = changesToMap(transactionData.getAllChangedNodes()).get(1L);

                        assertFalse(transactionData.hasPropertyBeenDeleted(changed.getCurrent(), "name"));
                        assertFalse(transactionData.hasPropertyBeenDeleted(changed.getCurrent(), "tags"));
                        assertTrue(transactionData.hasPropertyBeenDeleted(changed.getCurrent(), "count"));
                        assertFalse(transactionData.hasPropertyBeenDeleted(changed.getPrevious(), "name"));
                        assertFalse(transactionData.hasPropertyBeenDeleted(changed.getPrevious(), "tags"));
                        assertTrue(transactionData.hasPropertyBeenDeleted(changed.getPrevious(), "count"));

                        assertEquals(2, transactionData.deletedProperties(changed.getCurrent()).size());
                        assertEquals(2, transactionData.deletedProperties(changed.getPrevious()).size());
                        assertEquals(1, transactionData.deletedProperties(changed.getCurrent()).get("count"));
                        assertEquals(1, transactionData.deletedProperties(changed.getPrevious()).get("count"));

                        changed = changesToMap(transactionData.getAllChangedNodes()).get(3L);
                        assertEquals(0, transactionData.deletedProperties(changed.getCurrent()).size());
                        assertEquals(0, transactionData.deletedProperties(changed.getPrevious()).size());
                        assertFalse(transactionData.hasPropertyBeenDeleted(changed.getCurrent(), "name"));
                        assertFalse(transactionData.hasPropertyBeenDeleted(changed.getCurrent(), "tags"));
                        assertFalse(transactionData.hasPropertyBeenDeleted(changed.getCurrent(), "place"));
                        assertFalse(transactionData.hasPropertyBeenDeleted(changed.getPrevious(), "name"));
                        assertFalse(transactionData.hasPropertyBeenDeleted(changed.getPrevious(), "tags"));
                        assertFalse(transactionData.hasPropertyBeenDeleted(changed.getPrevious(), "place"));

                        assertFalse(transactionData.hasPropertyBeenDeleted(transactionData.getAllCreatedNodes().iterator().next(), "name"));
                    }
                }
        );
    }

    //mutations

    @Test
    public void shouldBeAbleToChangeCreatedRelationshipBeforeCommit() {
        createBatchInserter();
        mutateGraph(
                new BeforeCommitCallback() {
                    @Override
                    public void doBeforeCommit(ImprovedTransactionData transactionData) {
                        Map<Long, Relationship> created = propertyContainersToMap(transactionData.getAllCreatedRelationships());

                        long r1Id = getNodeById(5).getSingleRelationship(withName("R5"), OUTGOING).getId();
                        Relationship r1 = created.get(r1Id);

                        r1.setProperty("additional", "someValue");
                        r1.removeProperty("time");
                    }
                }
        );

        batchInserter = new TransactionSimulatingBatchInserterImpl(BatchInserters.inserter(temporaryFolder.getRoot().getAbsolutePath()));

        Relationship r1 = getNodeById(5).getSingleRelationship(withName("R5"), OUTGOING);
        assertEquals(1, count(r1.getPropertyKeys()));
        assertEquals("someValue", r1.getProperty("additional"));
        assertFalse(r1.hasProperty("time"));
    }

    @Test
    public void shouldBeAbleToChangeCreatedNodeBeforeCommit() {
        createBatchInserter();
        mutateGraph(
                new BeforeCommitCallback() {
                    @Override
                    public void doBeforeCommit(ImprovedTransactionData transactionData) {
                        Map<Long, Node> createdNodes = propertyContainersToMap(transactionData.getAllCreatedNodes());
                        Node createdNode = createdNodes.get(5L);

                        createdNode.setProperty("name", "NewFive");
                        createdNode.setProperty("additional", "something");
                        createdNode.removeProperty("size");
                    }
                }
        );

        batchInserter = new TransactionSimulatingBatchInserterImpl(BatchInserters.inserter(temporaryFolder.getRoot().getAbsolutePath()));

        Node createdNode = getNodeById(5L);

        assertEquals("NewFive", createdNode.getProperty("name"));
        assertEquals("something", createdNode.getProperty("additional"));
        assertEquals(2, count(createdNode.getPropertyKeys()));
        assertFalse(createdNode.hasProperty("size"));
    }

    @Test
    public void shouldBeAbleToChangeCurrentChangedRelationshipBeforeCommit() {
        createBatchInserter();
        mutateGraph(
                new BeforeCommitCallback() {
                    @Override
                    public void doBeforeCommit(ImprovedTransactionData transactionData) {
                        Map<Long, Change<Relationship>> changed = changesToMap(transactionData.getAllChangedRelationships());

                        Relationship r = changed.entrySet().iterator().next().getValue().getCurrent();

                        r.setProperty("time", 5);
                        r.setProperty("additional", "something");
                        r.removeProperty("tags");
                    }
                }
        );

        batchInserter = new TransactionSimulatingBatchInserterImpl(BatchInserters.inserter(temporaryFolder.getRoot().getAbsolutePath()));

        Relationship r = getNodeById(3).getSingleRelationship(withName("R3"), OUTGOING);

        assertEquals(2, count(r.getPropertyKeys()));
        assertEquals(5, r.getProperty("time"));
        assertEquals("something", r.getProperty("additional"));
        assertFalse(r.hasProperty("tags"));
    }

    @Test
    public void shouldBeAbleToChangePreviousChangedRelationshipBeforeCommit() {
        createBatchInserter();
        mutateGraph(
                new BeforeCommitCallback() {
                    @Override
                    public void doBeforeCommit(ImprovedTransactionData transactionData) {
                        Map<Long, Change<Relationship>> changed = changesToMap(transactionData.getAllChangedRelationships());

                        Relationship r = changed.entrySet().iterator().next().getValue().getPrevious();

                        r.setProperty("time", 5);
                        r.setProperty("additional", "something");
                        r.removeProperty("tags");
                    }
                }
        );

        batchInserter = new TransactionSimulatingBatchInserterImpl(BatchInserters.inserter(temporaryFolder.getRoot().getAbsolutePath()));

        Relationship r = getNodeById(3).getSingleRelationship(withName("R3"), OUTGOING);

        assertEquals(2, count(r.getPropertyKeys()));
        assertEquals(5, r.getProperty("time"));
        assertEquals("something", r.getProperty("additional"));
        assertFalse(r.hasProperty("tags"));
    }

    @Test
    public void shouldBeAbleToChangeCurrentChangedNodeBeforeCommit() {
        createBatchInserter();
        mutateGraph(
                new BeforeCommitCallback() {
                    @Override
                    public void doBeforeCommit(ImprovedTransactionData transactionData) {
                        if (!transactionData.mutationsOccurred()) {
                            return;
                        }

                        Map<Long, Change<Node>> changed = changesToMap(transactionData.getAllChangedNodes());

                        Node node = changed.get(1L).getCurrent();

                        node.setProperty("name", "YetAnotherOne");
                        node.setProperty("additional", "something");
                        node.removeProperty("tags");
                    }
                }
        );

        batchInserter = new TransactionSimulatingBatchInserterImpl(BatchInserters.inserter(temporaryFolder.getRoot().getAbsolutePath()));

        Node node = getNodeById(1L);

        assertEquals(2, count(node.getPropertyKeys()));
        assertEquals("YetAnotherOne", node.getProperty("name"));
        assertEquals("something", node.getProperty("additional"));
        assertFalse(node.hasProperty("tags"));
    }

    @Test
    public void shouldBeAbleToChangePreviousChangedNodeBeforeCommit() {
        createBatchInserter();
        mutateGraph(
                new BeforeCommitCallback() {
                    @Override
                    public void doBeforeCommit(ImprovedTransactionData transactionData) {
                        Map<Long, Change<Node>> changed = changesToMap(transactionData.getAllChangedNodes());

                        Node node = changed.get(1L).getPrevious();

                        node.setProperty("name", "YetAnotherOne");
                        node.setProperty("additional", "something");
                        node.removeProperty("tags");
                    }
                }
        );

        batchInserter = new TransactionSimulatingBatchInserterImpl(BatchInserters.inserter(temporaryFolder.getRoot().getAbsolutePath()));

        Node node = getNodeById(1L);

        assertEquals(2, count(node.getPropertyKeys()));
        assertEquals("YetAnotherOne", node.getProperty("name"));
        assertEquals("something", node.getProperty("additional"));
        assertFalse(node.hasProperty("tags"));
    }

    @Test
    public void shouldBeAbleToCreateAdditionalNodesAndRelationshipsFromCurrentGraphVersion() {
        createBatchInserter();
        mutateGraph(
                new BeforeCommitCallback() {
                    @Override
                    public void doBeforeCommit(ImprovedTransactionData transactionData) {
                        Map<Long, Change<Node>> changed = changesToMap(transactionData.getAllChangedNodes());

                        Node node = changed.get(1L).getCurrent();

                        Node newNode = getNodeById(batchInserter.createNode(null));
                        newNode.setProperty("name", "Six");
                        node.createRelationshipTo(newNode, withName("R6")).setProperty("new", true);

                        //just a check we can see this right away
                        Relationship newRelationship = getNodeById(1).getSingleRelationship(withName("R6"), OUTGOING);
                        assertNotNull(newRelationship);
                        assertEquals("Six", newRelationship.getEndNode().getProperty("name"));
                        assertEquals(true, newRelationship.getProperty("new"));
                    }
                }
        );

        batchInserter = new TransactionSimulatingBatchInserterImpl(BatchInserters.inserter(temporaryFolder.getRoot().getAbsolutePath()));

        Relationship newRelationship = getNodeById(1).getSingleRelationship(withName("R6"), OUTGOING);
        assertNotNull(newRelationship);
        assertEquals("Six", newRelationship.getEndNode().getProperty("name"));
        assertEquals(true, newRelationship.getProperty("new"));
    }

    @Test
    public void shouldBeAbleToCreateAdditionalNodesAndRelationshipsFromPreviousGraphVersion() {
        createBatchInserter();
        mutateGraph(
                new BeforeCommitCallback() {
                    @Override
                    public void doBeforeCommit(ImprovedTransactionData transactionData) {
                        Map<Long, Change<Node>> changed = changesToMap(transactionData.getAllChangedNodes());

                        Node node = changed.get(1L).getPrevious();

                        Node newNode = getNodeById(batchInserter.createNode(Collections.<String, Object>emptyMap()));
                        newNode.setProperty("name", "Six");
                        node.createRelationshipTo(newNode, withName("R6")).setProperty("new", true);
                    }
                }
        );

        batchInserter = new TransactionSimulatingBatchInserterImpl(BatchInserters.inserter(temporaryFolder.getRoot().getAbsolutePath()));

        Relationship newRelationship = getNodeById(1).getSingleRelationship(withName("R6"), OUTGOING);
        assertNotNull(newRelationship);
        assertEquals("Six", newRelationship.getEndNode().getProperty("name"));
        assertEquals(true, newRelationship.getProperty("new"));
    }

    @Test
    public void shouldNotBeAbleToDeleteAnything() {
        createBatchInserter();

        try {
            getNodeById(1).delete();
            fail();
        } catch (UnsupportedOperationException e) {
            //ok
        }

        try {
            getNodeById(1).getRelationships().iterator().next().delete();
            fail();
        } catch (UnsupportedOperationException e) {
            //ok
        }
    }

    @Test
    public void propertyExtractionStrategySmokeTest() {
        createBatchInserter();
        mutateGraph(
                new BeforeCommitCallback() {
                    @Override
                    public void doBeforeCommit(ImprovedTransactionData transactionData) {
                        Relationship previous = transactionData.getAllChangedRelationships().iterator().next().getPrevious();
                        Relationship current = transactionData.getAllChangedRelationships().iterator().next().getCurrent();

                        Map<String, Object> previousProps = new OtherNodeNameIncludingRelationshipPropertiesExtractor().extractProperties(previous, previous.getStartNode());
                        assertEquals(3, previousProps.size());
                        assertEquals("One", previousProps.get("otherNodeName"));
                        assertEquals(3, previousProps.get("time"));
                        assertEquals("cool", previousProps.get("tag"));

                        Map<String, Object> currentProps = new OtherNodeNameIncludingRelationshipPropertiesExtractor().extractProperties(current, current.getStartNode());
                        assertEquals(3, currentProps.size());
                        assertEquals("NewOne", currentProps.get("otherNodeName"));
                        assertEquals(4, currentProps.get("time"));
                        assertEquals("cool", currentProps.get("tags"));
                    }
                }
        );
    }

    @Test
    public void shouldIndicateNoMutationWhenNothingHasBeenChanged() {
        createBatchInserter();

        TestingTxEventHandler handler = new TestingTxEventHandler(new BeforeCommitCallback() {
            @Override
            public void doBeforeCommit(ImprovedTransactionData transactionData) {
                assertFalse(transactionData.mutationsOccurred());
            }
        });

        batchInserter.registerTransactionEventHandler(handler);

        //change that should not be picked up as a change
        Node four = getNodeById(4);
        four.setProperty("name", "Three");
        four.setProperty("name", "Four");

        batchInserter.shutdown();
    }

    @Test
    public void verifyRelationshipRetrieving() {
        createBatchInserter();
        mutateGraph(
                new BeforeCommitCallback() {
                    @Override
                    public void doBeforeCommit(ImprovedTransactionData transactionData) {
                        assertEquals(5, count(getNodeById(1).getRelationships()));
                        assertEquals(5, count(getNodeById(1).getRelationships(BOTH)));
                        assertEquals(5, count(getNodeById(1).getRelationships(BOTH, new RelationshipType[0])));
                        assertEquals(2, count(getNodeById(1).getRelationships(withName("R3"))));
                        assertEquals(3, count(getNodeById(1).getRelationships(withName("R3"), withName("R1"))));
                        assertEquals(4, count(getNodeById(1).getRelationships(OUTGOING)));
                        assertEquals(1, count(getNodeById(1).getRelationships(OUTGOING, withName("R3"))));
                        assertEquals(1, count(getNodeById(1).getRelationships(withName("R3"), OUTGOING)));

                        assertTrue(getNodeById(1).hasRelationship());
                        assertTrue(getNodeById(1).hasRelationship(withName("R3")));
                        assertTrue(getNodeById(1).hasRelationship(withName("R3"), withName("R1")));
                        assertTrue(getNodeById(1).hasRelationship(OUTGOING));
                        assertTrue(getNodeById(1).hasRelationship(OUTGOING, withName("R3")));
                        assertTrue(getNodeById(1).hasRelationship(withName("R3"), OUTGOING));

                        assertFalse(getNodeById(1).hasRelationship(withName("R")));
                        assertFalse(getNodeById(1).hasRelationship(withName("R"), withName("R")));
                        assertFalse(getNodeById(1).hasRelationship(OUTGOING, withName("R")));
                        assertFalse(getNodeById(1).hasRelationship(withName("R"), OUTGOING));
                    }
                }
        );
    }

    @Test
    public void verifyAutoCommit() {
        batchInserter = new TransactionSimulatingBatchInserterImpl(BatchInserters.inserter(temporaryFolder.getRoot().getAbsolutePath()));

        populateDatabase();

        batchInserter.shutdown();
        batchInserter = new TransactionSimulatingBatchInserterImpl(BatchInserters.inserter(temporaryFolder.getRoot().getAbsolutePath()), 28);

        final AtomicInteger numberOfCommits = new AtomicInteger(0);

        mutateGraph(
                new BeforeCommitCallback() {
                    @Override
                    public void doBeforeCommit(ImprovedTransactionData transactionData) {
                        if (numberOfCommits.incrementAndGet() == 1) {
                            assertEquals(2, transactionData.getAllCreatedRelationships().size());
                            assertEquals(1, transactionData.getAllChangedRelationships().size());
                            assertEquals(0, transactionData.getAllDeletedRelationships().size());

                            assertEquals(1, transactionData.getAllCreatedNodes().size());
                            assertEquals(2, transactionData.getAllChangedNodes().size());
                            assertEquals(0, transactionData.getAllDeletedNodes().size());
                        } else {
                            assertFalse(transactionData.mutationsOccurred());
                        }
                    }
                }
        );

        assertEquals(2, numberOfCommits.get());
    }

    @Test
    public void shouldReturnNoNodesWhenNothingInTheDatabase() {
        batchInserter = new TransactionSimulatingBatchInserterImpl(BatchInserters.inserter(temporaryFolder.getRoot().getAbsolutePath()));

        assertFalse(batchInserter.getAllNodes().iterator().hasNext());
    }

    @Test
    public void shouldReturnAllNodesFromTheDatabase() {
        batchInserter = new TransactionSimulatingBatchInserterImpl(BatchInserters.inserter(temporaryFolder.getRoot().getAbsolutePath()));

        batchInserter.createNode(Collections.<String, Object>singletonMap("name", "One"));
        batchInserter.createNode(Collections.<String, Object>singletonMap("name", "Two"));

        Iterable<Long> allNodes = batchInserter.getAllNodes();
        assertEquals(2, count(allNodes));

        Iterator<Long> iterator = batchInserter.getAllNodes().iterator();
        assertEquals("One", batchInserter.getNodeProperties(iterator.next()).get("name"));
        assertEquals("Two", batchInserter.getNodeProperties(iterator.next()).get("name"));
    }

    @Test
    public void shouldReturnAllNodesFromTheDatabaseWithGaps() {
        GraphDatabaseService database = new GraphDatabaseFactory().newEmbeddedDatabase(temporaryFolder.getRoot().getAbsolutePath());

        new SimpleTransactionExecutor(database).executeInTransaction(new VoidReturningCallback() {
            @Override
            protected void doInTx(GraphDatabaseService database) {
                Node node1 = database.createNode();
                Node node2 = database.createNode();
                Node node3 = database.createNode();

                node1.setProperty("name", "One");
                node2.setProperty("name", "Two");
                node3.setProperty("name", "Three");

                node2.delete();
            }
        });

        database.shutdown();

        batchInserter = new TransactionSimulatingBatchInserterImpl(BatchInserters.inserter(temporaryFolder.getRoot().getAbsolutePath()));

        Iterable<Long> allNodes = batchInserter.getAllNodes();
        assertEquals(2, count(allNodes));

        Iterator<Long> iterator = batchInserter.getAllNodes().iterator();
        assertEquals("One", batchInserter.getNodeProperties(iterator.next()).get("name"));
        assertEquals("Three", batchInserter.getNodeProperties(iterator.next()).get("name"));
    }

    //test helpers

    private void mutateGraph(BeforeCommitCallback beforeCommitCallback) {
        TestingTxEventHandler handler = new TestingTxEventHandler(beforeCommitCallback);
        batchInserter.registerTransactionEventHandler(handler);

        Node one = getNodeById(1);
        one.setProperty("name", "NewOne");
        one.setProperty("count", "something");
        one.removeProperty("count");
        one.removeProperty("something");
        one.setProperty("tags", new String[]{"one"});
        one.setProperty("tags", new String[]{"one", "three"});

        Node three = getNodeById(3);
        three.setProperty("tags", "one");
        three.setProperty("place", "Rome");
        three.setProperty("place", "London");
//        three.removeProperty("place");
        three.removeProperty("place");
        three.setProperty("place", "London");

        Node five = getNodeById(batchInserter.createNode(Collections.<String, Object>emptyMap()));
        five.setProperty("name", "Five");
        five.setProperty("size", 3L);
        five.setProperty("size", 4L);
        Relationship r = five.createRelationshipTo(three, withName("R5"));
        r.setProperty("will be", "deleted");
        batchInserter.setRelationshipProperties(r.getId(), Collections.<String, Object>singletonMap("time", 4));

        //stuff commented out due to https://github.com/neo4j/neo4j/issues/2483
        r = three.getSingleRelationship(withName("R3"), OUTGOING);
        r.setProperty("time", 4);
        r.removeProperty("tag");
//        r.removeProperty("tag");
        r.setProperty("tag", "bla");
        r.removeProperty("tag");
        r.setProperty("tags", "cool");
        r.setProperty("tags", "cool");

        one.createRelationshipTo(three, withName("R4"));

        //change that should not be picked up as a change
        Node four = getNodeById(4);
        four.setProperty("name", "Three");
        four.setProperty("name", "Four");

        batchInserter.setNodeProperties(4, Collections.<String, Object>singletonMap("name", "Four"));

        assertTrue(batchInserter.nodeExists(1));
        assertTrue(batchInserter.nodeExists(2));
        assertTrue(batchInserter.nodeExists(3));
        assertTrue(batchInserter.nodeExists(4));

        batchInserter.shutdown();
    }

    private class TestingTxEventHandler implements TransactionEventHandler {

        private final BeforeCommitCallback beforeCommitCallback;

        private TestingTxEventHandler(BeforeCommitCallback beforeCommitCallback) {
            this.beforeCommitCallback = beforeCommitCallback;
        }

        @Override
        public Object beforeCommit(TransactionData data) throws Exception {
            beforeCommitCallback.doBeforeCommit(new LazyTransactionData(data));
            return null;
        }

        @Override
        public void afterCommit(TransactionData data, Object state) {
            //do nothing
        }

        @Override
        public void afterRollback(TransactionData data, Object state) {
            //do nothing
        }
    }

    private interface BeforeCommitCallback {
        void doBeforeCommit(ImprovedTransactionData transactionData);
    }

    private class OtherNodeNameIncludingRelationshipPropertiesExtractor {

        public Map<String, Object> extractProperties(Relationship relationship, Node pointOfView) {
            Map<String, Object> result = new HashMap<>();
            result.putAll(propertiesToMap(relationship));
            result.put("otherNodeName", relationship.getOtherNode(pointOfView).getProperty("name").toString());
            return result;
        }
    }

    private void createBatchInserter() {
        batchInserter = new TransactionSimulatingBatchInserterImpl(BatchInserters.inserter(temporaryFolder.getRoot().getAbsolutePath()));

        populateDatabase();

        batchInserter.shutdown();
        batchInserter = new TransactionSimulatingBatchInserterImpl(BatchInserters.inserter(temporaryFolder.getRoot().getAbsolutePath()));
    }

    private void populateDatabase() {
        Map<String, Object> props = new HashMap<>();
        props.put("name", "One");
        props.put("count", 1);
        props.put("tags", new String[]{"one", "two"});
        props.put("something", "something");
        long node1 = 1L;
        batchInserter.createNode(1, props);

        props = new HashMap<>();
        props.put("name", "Two");
        props.put("size", 2L);
        long node2 = batchInserter.createNode(null);
        batchInserter.setNodeProperties(node2, props);

        props = new HashMap<>();
        props.put("time", 1);
        batchInserter.createRelationship(node1, node2, withName("R1"), props);

        batchInserter.createRelationship(node2, node2, withName("R2"), Collections.<String, Object>emptyMap());

        props = new HashMap<>();
        props.put("name", "Three");
        props.put("place", "London");
        long node3 = batchInserter.createNode(props);

        props = new HashMap<>();
        props.put("time", 2);
        long relId = batchInserter.createRelationship(node2, node3, withName("R2"), null);
        batchInserter.setRelationshipProperties(relId, props);

        props = new HashMap<>();
        props.put("time", 3);
        props.put("tag", "cool");
        batchInserter.createRelationship(node3, node1, withName("R3"), props);

        batchInserter.createRelationship(node1, node3, withName("R3"), Collections.<String, Object>emptyMap());

        props = new HashMap<>();
        props.put("name", "Four");
        long node4 = batchInserter.createNode(props);

        props = new HashMap<>();
        props.put("time", 1);
        batchInserter.createRelationship(node3, node4, withName("R1"), props);

        batchInserter.createRelationship(node1, node4, withName("WHATEVER"), Collections.<String, Object>emptyMap());
    }
}
TOP

Related Classes of com.graphaware.tx.event.batch.TransactionSimulatingBatchInserterIntegrationTest$OtherNodeNameIncludingRelationshipPropertiesExtractor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.