/** * Copyright (c) 2014 - 2017 Frank Appel * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Frank Appel - initial API and implementation */ package com.codeaffine.workflow.internal; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.UUID; import com.codeaffine.workflow.TaskHolder; import com.codeaffine.workflow.TaskList; import com.codeaffine.workflow.TaskPredicate; import com.codeaffine.workflow.Workflow; import com.codeaffine.workflow.definition.Task; import com.codeaffine.workflow.persistence.Memento; public class TaskListImpl implements TaskList { private static final TaskPredicate APPLY_ALL = new TaskPredicate() { @Override public boolean apply( Task input ) { return true; } }; private final List<TaskHolder> content; private final TaskEventNotifier notifier; public TaskListImpl( TaskEventNotifier notifier ) { this.notifier = notifier; this.content = new LinkedList<TaskHolder>(); } public void add( Task task, WorkflowImpl workflow ) { synchronized( content ) { content.add( new TaskHolder( task, workflow ) ); } notifier.notifyAboutTaskCreation( task, this ); } @Override public List<Task> snapshot() { return snapshot( APPLY_ALL ); } @Override public List<Task> snapshot( TaskPredicate filter ) { synchronized( content ) { return createSnapshot( filter ); } } @Override public Workflow getWorkflow( Task task ) { synchronized( content ) { TaskHolder taskHolder = find( task ); if( taskHolder != null ) { return taskHolder.getWorkflow(); } } return null; } @Override public UUID acquireAssignment( Task task ) { UUID result; synchronized( content ) { result = acquire( task ); } if( result != null ) { notifier.notifyAboutTaskAssignment( task, this ); } return result; } @Override public void dropAssigment( UUID assignmentToken ) { Task droppedTask; synchronized( content ) { droppedTask = drop( assignmentToken ); } if( droppedTask != null ) { notifier.notifyAboutDropOfTaskAssignment( droppedTask, this ); } } @Override public boolean isAssigned( Task task ) { boolean result = false; synchronized( content ) { TaskHolder taskHolder = find( task ); if( taskHolder != null ) { result = taskHolder.isAssigned(); } } return result; } @Override public boolean complete( UUID assignmentToken ) { TaskHolder removed = remove( assignmentToken ); boolean result = complete( removed ); if( result ) { notifier.notifyAboutTaskCompletion( removed.getTask(), this ); } return result; } @Override public int size() { synchronized( content ) { return content.size(); } } @Override public boolean isEmpty() { synchronized( content ) { return content.isEmpty(); } } public Memento save() { ArrayList<TaskHolder> copy = new ArrayList<TaskHolder>(); copy.addAll( content ); return new Memento( copy ); } public void restore( Memento memento ) { content.clear(); content.addAll( memento.getContent() ); } private TaskHolder find( Task task ) { for( TaskHolder taskHolder : content ) { if( taskHolder.getTask() == task ) { return taskHolder; } } return null; } private TaskHolder find( UUID assigmentId ) { for( TaskHolder taskHolder : content ) { if( assigmentId.equals( taskHolder.getAssignmentToken() ) ) { return taskHolder; } } return null; } private List<Task> createSnapshot( TaskPredicate filter ) { ArrayList<Task> result = new ArrayList<Task>(); Iterator<TaskHolder> iterator = content.iterator(); while( iterator.hasNext() ) { TaskHolder taskHolder = iterator.next(); if( filter.apply( taskHolder.getTask() ) ) { result.add( taskHolder.getTask() ); } } return result; } private UUID acquire( Task task ) { UUID result = null; TaskHolder taskHolder = find( task ); if( taskHolder != null && !taskHolder.isAssigned() ) { result = UUID.randomUUID(); taskHolder.setAssigmentToken( result ); } return result; } private Task drop( UUID assignmentToken ) { TaskHolder taskHolder = find( assignmentToken ); if( taskHolder != null ) { taskHolder.setAssigmentToken( null ); return taskHolder.getTask(); } return null; } private TaskHolder remove( UUID assignmentToken ) { TaskHolder taskHolder; synchronized( content ) { taskHolder = find( assignmentToken ); content.remove( taskHolder ); } return taskHolder; } private static boolean complete( TaskHolder taskHolder ) { boolean result = false; if( taskHolder != null ) { taskHolder.complete(); result = true; } return result; } }