public void Execute(IExecution execution)
        {
            execution.Stop();

            int incomingTransitionCount = execution.CurrentNode.IncomingTransitions.Count();

            if (incomingTransitionCount > 1)
            {
                var root = execution.GetConcurrentRoot();
                var executionCollector =
                    new ExecutionCollector(e => !e.IsActive && e.CurrentNode == execution.CurrentNode);
                root.Accept(executionCollector);
                int joinedTransitionCount = executionCollector.Result.DistinctBy(e => e.IncomingTransition).Count();

                if (incomingTransitionCount > joinedTransitionCount)
                {
                    Logger.InfoFormat("Cannot join in node '{0}' yet. Joined: {1}, To join: {2}. Waiting...",
                        execution.CurrentNode.Identifier, joinedTransitionCount, incomingTransitionCount);
                    execution.Wait();
                    return;
                }

                root.Split(execution.CurrentNode);
            }
            else
            {
                execution.Split(execution.CurrentNode);
            }

        }
        public IExecution LoadExecution(string executionIdentifier, IExecutionPlan executionPlan)
        {
            var rootQuery = graphClient.Cypher
                                       .Match("(e:Execution {Identifier: {id}})")
                                       .OptionalMatch("(r:Execution)-[:PARENT_OF*]->(e)")
                                       .OptionalMatch("(r)-[:EXECUTES]->(currentNode:Node)")
                                       .Where("NOT (:Execution)-[:PARENT_OF*]->(r)")
                                       .WithParam("id", executionIdentifier)
                                       .Return((r, e, currentNode) => new
                                       {
                                           Root = r.As<ExecutionModel>(),
                                           Current = e.As<ExecutionModel>(),
                                           CurrentNode = currentNode.As<NodeModel>()
                                       });

            var executionModel = rootQuery.Results.Last();

            var root = executionModel.Root ?? executionModel.Current;


            var wfQuery = graphClient.Cypher
                                     .Match("(e:Execution {Identifier: {id}})-[*]->(n:Node)")
                                     .Match("(wf:WorkflowDefinition)-[*]->(n)")
                                     .OptionalMatch(
                                         "(e:Execution {Identifier: {id}})-[:REFERENCES]->(wf:WorkflowDefinition)")
                                     .WithParam("id", root.Identifier)
                                     .Return(wf => wf.As<WorkflowDefinitionModel>());

            var workflowDefinition = LoadWorkflowDefinition(wfQuery.Results.First().Identifier);


            Dictionary<string, object> data =
                (Dictionary<string, object>)
                    objectSerializer.Deserialize(root.Data, typeof (Dictionary<string, object>));
            var children = new List<IExecution>();

            var rootExecution = new Execution(null,
                executionModel.CurrentNode == null
                    ? null
                    : workflowDefinition.Nodes.First(n => n.Identifier == executionModel.CurrentNode.Identifier),
                root.IsActive, root.IsFinished, data, root.IncomingTransition,
                root.Identifier, root.WorkflowInstanceIdentifier,
                executionPlan, children,
                workflowDefinition);

            FillChildren(rootExecution, children, executionPlan, workflowDefinition);

            var collector = new ExecutionCollector(e => e.Identifier == executionIdentifier);
            rootExecution.Accept(collector);

            return collector.Result.First();
        }
        public IExecution TransformBack(ExecutionModel model, IWorkflowDefinition workflowDefinition,
            IExecutionPlan plan)
        {
            if (model == null)
            {
                return null;
            }

            var root = FindRoot(model);
            var transformedRoot = TransformBack(root, plan, workflowDefinition, null);

            var collector = new ExecutionCollector(e => e.Identifier == model.Identifier);
            transformedRoot.Accept(collector);
            return collector.Result.First();
        }