// Path: src/main/java/toolbox/common/workflow/core/ExecutionContext.java
// public interface ExecutionContext extends Context {
//     
//     ActiveRecord getActiveRecord();
//     
//     ExecutionContext getParentContext();
//     
//     ScriptEngine getScriptEngine();
//     
//     Execution getExecution();
//     
//     void setExecution(Execution execution);
//     
//     boolean evaluateCondition(String condition);
//     
// }
// 
// Path: src/main/java/toolbox/common/workflow/entity/Execution.java
// @Data
// @EqualsAndHashCode(callSuper=true)
// @NoArgsConstructor
// @Entity
// public class Execution extends Persistable {
// 
//     private static final long serialVersionUID = -1214145175194494791L;
//     
//     @ManyToOne
//     private Phase currentPhase;
//     
//     @ManyToOne
//     private Workflow workflow;
//     
//     @ManyToOne
//     private Execution parent;
//     
//     public Execution(Long id) {
//         super(id);
//     }
//     
//     public Execution(Workflow workflow) {
//         this.workflow = workflow;
//     }
// 
// }
// 
// Path: src/main/java/toolbox/common/workflow/entity/Phase.java
// @Data
// @EqualsAndHashCode(callSuper=true)
// @NoArgsConstructor
// @Entity
// public class Phase extends Persistable {
// 
//     private static final long serialVersionUID = -1123518726422072368L;
//     
//     private String name;
//     
//     private String description;
//     
//     private boolean isStart = false;
//     
//     @ManyToOne
//     private Workflow workflow;
//     
//     public Phase(Long id) {
//         super(id);
//     }
// 
//     public TaskBinding addTask(Task task, TaskExecutionLifecycle lifecycle, boolean isAsync) {
//         TaskBinding taskBinding = new TaskBinding();
//         taskBinding.setTask(task);
//         taskBinding.setLifecycle(lifecycle);
//         taskBinding.setAsync(isAsync);
//         taskBinding.setPhase(this);
//         return taskBinding;
//     }
// 
// }
// 
// Path: src/main/java/toolbox/common/workflow/entity/Transition.java
// @Data
// @EqualsAndHashCode(callSuper=true)
// @NoArgsConstructor
// @Entity
// public class Transition extends Persistable { 
//     
//     private static final long serialVersionUID = -852009937863296827L;
//     
//     @ManyToOne
//     private Phase from;
//     
//     @ManyToOne
//     private Phase to;
//     
//     @ManyToOne
//     private Workflow workflow;
//     
//     private String conditionExpression;
//     
//     public Transition(Long id) {
//         super(id);
//     }
// 
// }
// 
// Path: src/main/java/toolbox/common/workflow/entity/Workflow.java
// @Data
// @EqualsAndHashCode(callSuper=true)
// @NoArgsConstructor
// @Entity
// public class Workflow extends Persistable {
//     
//     private static final long serialVersionUID = -4664710822540762790L;
//     
//     private String name;
//     
//     private String description;
//     
//     public Workflow(Long id) {
//         super(id);
//     }
// 
//     public Phase addPhase(String name, String description, boolean isStart) {
//         Phase phase = new Phase();
//         phase.setName(name);
//         phase.setDescription(description);
//         phase.setStart(isStart);
//         phase.setWorkflow(this);
//         return phase;
//     }
// 
//     public TaskBinding addTask(Task task, TaskExecutionLifecycle lifecycle, boolean isAsync) {
//         TaskBinding taskBinding = new TaskBinding();
//         taskBinding.setTask(task);
//         taskBinding.setLifecycle(lifecycle);
//         taskBinding.setAsync(isAsync);
//         taskBinding.setWorkflow(this);
//         return taskBinding;
//     }
// 
//     public Transition addTransition(Phase from, Phase to, TransitionType type, String condition) {
//         
//         assert this.equals(from.getWorkflow());
//         assert this.equals(to.getWorkflow());
//         Transition transition = new Transition();
//         transition.setFrom(from);
//         transition.setTo(to);
//         transition.setWorkflow(this);
//         transition.setConditionExpression(condition);
//         return transition;
//     }
// 
// }
// 
// Path: src/main/java/toolbox/common/workflow/event/TransitionStartingEvent.java
// @Data
// @EqualsAndHashCode(callSuper=false)
// public class TransitionStartingEvent extends AbstractWorkflowEvent{
//     
//     private Phase from;
//     
//     private Phase to;
//     
//     public TransitionStartingEvent(ExecutionContext context, Phase from, Phase to) {
//         super(context);
//         this.from = from;
//         this.to = to;
//     }
// }
// 
// Path: src/main/java/toolbox/common/workflow/event/WorkflowStartingEvent.java
// @Data
// @EqualsAndHashCode(callSuper=false)
// public class WorkflowStartingEvent extends AbstractWorkflowEvent {
//     
//     private Workflow workflow;
//     
//     public WorkflowStartingEvent(ExecutionContext context, Workflow starting) {
//         super(context);
//         this.workflow = starting;
//     }
// }
// 
// Path: src/main/java/toolbox/common/workflow/repository/ExecutionRepository.java
// public interface ExecutionRepository extends JpaRepository<Execution, Long>{
// 
// }


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import toolbox.common.workflow.core.ExecutionContext;
import toolbox.common.workflow.entity.Execution;
import toolbox.common.workflow.entity.Phase;
import toolbox.common.workflow.entity.Transition;
import toolbox.common.workflow.entity.Workflow;
import toolbox.common.workflow.event.TransitionStartingEvent;
import toolbox.common.workflow.event.WorkflowStartingEvent;
import toolbox.common.workflow.repository.ExecutionRepository;
package toolbox.common.workflow.service;



@Service
public class ExecutionServiceImpl implements ExecutionService{
    
    @Autowired
    private ApplicationEventPublisher eventPublisher;
    
    @Autowired
    private ExecutionRepository executionRepository;

    @Override
    public Execution startWorkflow(Workflow workflow, ExecutionContext context) {
        WorkflowStartingEvent event = new WorkflowStartingEvent(context, workflow);
        eventPublisher.publishEvent(event);
        return context.getExecution();
    }

    @Override
// Path: src/main/java/toolbox/common/workflow/core/ExecutionContext.java
// public interface ExecutionContext extends Context {
//     
//     ActiveRecord getActiveRecord();
//     
//     ExecutionContext getParentContext();
//     
//     ScriptEngine getScriptEngine();
//     
//     Execution getExecution();
//     
//     void setExecution(Execution execution);
//     
//     boolean evaluateCondition(String condition);
//     
// }
// 
// Path: src/main/java/toolbox/common/workflow/entity/Execution.java
// @Data
// @EqualsAndHashCode(callSuper=true)
// @NoArgsConstructor
// @Entity
// public class Execution extends Persistable {
// 
//     private static final long serialVersionUID = -1214145175194494791L;
//     
//     @ManyToOne
//     private Phase currentPhase;
//     
//     @ManyToOne
//     private Workflow workflow;
//     
//     @ManyToOne
//     private Execution parent;
//     
//     public Execution(Long id) {
//         super(id);
//     }
//     
//     public Execution(Workflow workflow) {
//         this.workflow = workflow;
//     }
// 
// }
// 
// Path: src/main/java/toolbox/common/workflow/entity/Phase.java
// @Data
// @EqualsAndHashCode(callSuper=true)
// @NoArgsConstructor
// @Entity
// public class Phase extends Persistable {
// 
//     private static final long serialVersionUID = -1123518726422072368L;
//     
//     private String name;
//     
//     private String description;
//     
//     private boolean isStart = false;
//     
//     @ManyToOne
//     private Workflow workflow;
//     
//     public Phase(Long id) {
//         super(id);
//     }
// 
//     public TaskBinding addTask(Task task, TaskExecutionLifecycle lifecycle, boolean isAsync) {
//         TaskBinding taskBinding = new TaskBinding();
//         taskBinding.setTask(task);
//         taskBinding.setLifecycle(lifecycle);
//         taskBinding.setAsync(isAsync);
//         taskBinding.setPhase(this);
//         return taskBinding;
//     }
// 
// }
// 
// Path: src/main/java/toolbox/common/workflow/entity/Transition.java
// @Data
// @EqualsAndHashCode(callSuper=true)
// @NoArgsConstructor
// @Entity
// public class Transition extends Persistable { 
//     
//     private static final long serialVersionUID = -852009937863296827L;
//     
//     @ManyToOne
//     private Phase from;
//     
//     @ManyToOne
//     private Phase to;
//     
//     @ManyToOne
//     private Workflow workflow;
//     
//     private String conditionExpression;
//     
//     public Transition(Long id) {
//         super(id);
//     }
// 
// }
// 
// Path: src/main/java/toolbox/common/workflow/entity/Workflow.java
// @Data
// @EqualsAndHashCode(callSuper=true)
// @NoArgsConstructor
// @Entity
// public class Workflow extends Persistable {
//     
//     private static final long serialVersionUID = -4664710822540762790L;
//     
//     private String name;
//     
//     private String description;
//     
//     public Workflow(Long id) {
//         super(id);
//     }
// 
//     public Phase addPhase(String name, String description, boolean isStart) {
//         Phase phase = new Phase();
//         phase.setName(name);
//         phase.setDescription(description);
//         phase.setStart(isStart);
//         phase.setWorkflow(this);
//         return phase;
//     }
// 
//     public TaskBinding addTask(Task task, TaskExecutionLifecycle lifecycle, boolean isAsync) {
//         TaskBinding taskBinding = new TaskBinding();
//         taskBinding.setTask(task);
//         taskBinding.setLifecycle(lifecycle);
//         taskBinding.setAsync(isAsync);
//         taskBinding.setWorkflow(this);
//         return taskBinding;
//     }
// 
//     public Transition addTransition(Phase from, Phase to, TransitionType type, String condition) {
//         
//         assert this.equals(from.getWorkflow());
//         assert this.equals(to.getWorkflow());
//         Transition transition = new Transition();
//         transition.setFrom(from);
//         transition.setTo(to);
//         transition.setWorkflow(this);
//         transition.setConditionExpression(condition);
//         return transition;
//     }
// 
// }
// 
// Path: src/main/java/toolbox/common/workflow/event/TransitionStartingEvent.java
// @Data
// @EqualsAndHashCode(callSuper=false)
// public class TransitionStartingEvent extends AbstractWorkflowEvent{
//     
//     private Phase from;
//     
//     private Phase to;
//     
//     public TransitionStartingEvent(ExecutionContext context, Phase from, Phase to) {
//         super(context);
//         this.from = from;
//         this.to = to;
//     }
// }
// 
// Path: src/main/java/toolbox/common/workflow/event/WorkflowStartingEvent.java
// @Data
// @EqualsAndHashCode(callSuper=false)
// public class WorkflowStartingEvent extends AbstractWorkflowEvent {
//     
//     private Workflow workflow;
//     
//     public WorkflowStartingEvent(ExecutionContext context, Workflow starting) {
//         super(context);
//         this.workflow = starting;
//     }
// }
// 
// Path: src/main/java/toolbox/common/workflow/repository/ExecutionRepository.java
// public interface ExecutionRepository extends JpaRepository<Execution, Long>{
// 
// }


// Path: src/main/java/toolbox/common/workflow/service/ExecutionServiceImpl.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import toolbox.common.workflow.core.ExecutionContext;
import toolbox.common.workflow.entity.Execution;
import toolbox.common.workflow.entity.Phase;
import toolbox.common.workflow.entity.Transition;
import toolbox.common.workflow.entity.Workflow;
import toolbox.common.workflow.event.TransitionStartingEvent;
import toolbox.common.workflow.event.WorkflowStartingEvent;
import toolbox.common.workflow.repository.ExecutionRepository;

package toolbox.common.workflow.service;



@Service
public class ExecutionServiceImpl implements ExecutionService{
    
    @Autowired
    private ApplicationEventPublisher eventPublisher;
    
    @Autowired
    private ExecutionRepository executionRepository;

    @Override
    public Execution startWorkflow(Workflow workflow, ExecutionContext context) {
        WorkflowStartingEvent event = new WorkflowStartingEvent(context, workflow);
        eventPublisher.publishEvent(event);
        return context.getExecution();
    }

    @Override
    public void doTransition(Execution execution, Transition transition, ExecutionContext context) {