Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   /*
    * OfficeFloor - http://www.officefloor.net
    * Copyright (C) 2005-2011 Daniel Sagenschneider
    *
    * This program 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 net.officefloor.model.impl.desk;
  
  import java.util.Arrays;
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.List;
  import java.util.Map;
  import java.util.Set;
  
net.officefloor.model.desk.DeskChanges implementation.

Author(s):
Daniel Sagenschneider
  
  public class DeskChangesImpl implements DeskChanges {

  
  			FlowInstigationStrategyEnum instigationStrategy) {
  
  		// Ensure have instigation strategy
  		if (instigationStrategy == null) {
 			return null;
 		}
 
 		// Return instigation strategy link type
 		switch (instigationStrategy) {
 		case :
 		case :
 		case :
 		default:
 			throw new IllegalStateException("Unknown instigation strategy "
 					+ instigationStrategy);
 		}
 	}

Sorts the net.officefloor.model.desk.WorkModel instances.

This enable easier merging of configuration under SCM.

Parameters:
workModels net.officefloor.model.desk.WorkTaskModel instances.
 
 	public static void sortWorkModels(List<WorkModelworkModels) {
 		Collections.sort(workModelsnew Comparator<WorkModel>() {
 			public int compare(WorkModel aWorkModel b) {
 				return a.getWorkName().compareTo(b.getWorkName());
 			}
 		});
 	}

Sorts the net.officefloor.model.desk.WorkTaskModel instances.

This enables easier merging of configuration under SCM.

Parameters:
workTaskModels net.officefloor.model.desk.WorkTaskModel instances.
 
 	public static void sortWorkTaskModels(List<WorkTaskModelworkTaskModels) {
 		Collections.sort(workTaskModelsnew Comparator<WorkTaskModel>() {
 			public int compare(WorkTaskModel aWorkTaskModel b) {
 			}
 		});
 	}

Sorts the net.officefloor.model.desk.WorkTaskToTaskModel connections.

Parameters:
workTaskToTaskConnections net.officefloor.model.desk.WorkTaskToTaskModel instances.
 
 	public static void sortWorkTaskToTaskConnections(
 			List<WorkTaskToTaskModelworkTaskToTaskConnections) {
 		Collections.sort(workTaskToTaskConnections,
 					public int compare(WorkTaskToTaskModel a,
 						return a.getTask().getTaskName().compareTo(
 					}
 				});
 	}

Sorts the net.officefloor.model.desk.TaskModel instances.

This enable easier merging of configuration under SCM.

Parameters:
taskModels net.officefloor.model.desk.TaskModel instances.
 
 	public static void sortTaskModels(List<TaskModeltaskModels) {
 		Collections.sort(taskModelsnew Comparator<TaskModel>() {
 			public int compare(TaskModel aTaskModel b) {
 				return a.getTaskName().compareTo(b.getTaskName());
 			}
 		});
 	}

Sorts the net.officefloor.model.desk.ExternalFlowModel instances.

This enables easier merging of configuration under SCM.

Parameters:
externalFlows net.officefloor.model.desk.ExternalFlowModel instances.
 
 	public static void sortExternalFlows(List<ExternalFlowModelexternalFlows) {
 		Collections.sort(externalFlowsnew Comparator<ExternalFlowModel>() {
 			public int compare(ExternalFlowModel aExternalFlowModel b) {
 			}
 		});
 	}

Sorts the net.officefloor.model.desk.ExternalManagedObjectModel instances.

This enables easier merging of configuration under SCM.

Parameters:
externalManagedObjects net.officefloor.model.desk.ExternalManagedObjectModel instances.
 
 	public static void sortExternalManagedObjects(
 			List<ExternalManagedObjectModelexternalManagedObjects) {
 		Collections.sort(externalManagedObjects,
 					}
 				});
 	}

 
 	public static String getManagedObjectScope(ManagedObjectScope scope) {
 
 		// Ensure have scope
 		if (scope == null) {
 			return null;
 		}
 
 		// Return the text of the scope
 		switch (scope) {
 		case :
 		case :
 		case :
 		default:
 			throw new IllegalStateException("Unknown scope " + scope);
 		}
 	}

 
 	private final DeskModel desk;

Initiate.

 
 	public DeskChangesImpl(DeskModel desk) {
 		this. = desk;
 	}

 
 	protected void sortWorkModels() {
 	}

 
 	protected void sortTaskModels() {
 	}

 
 	protected void sortExternalFlows() {
 	}

 
 	protected void sortExternalManagedObjects() {
 	}

 
 	private WorkTaskModel createWorkTaskModel(TaskType<?, ?, ?> taskType) {
 
 		// Create the work task model
 		WorkTaskModel workTask = new WorkTaskModel(taskType.getTaskName());
 
 		// Add the task object models
 		for (TaskObjectType<?> taskObjectType : taskType.getObjectTypes()) {
 			Enum<?> key = taskObjectType.getKey();
 					taskObjectType.getObjectName(), (key == null ? null : key
 							.name()), taskObjectType.getObjectType().getName(),
 					false);
 			workTask.addTaskObject(taskObject);
 		}
 
 		// Return the work task model
 		return workTask;
 	}

Removes the connections to the net.officefloor.model.desk.TaskModel (except to its net.officefloor.model.desk.WorkTaskModel).

Parameters:
task net.officefloor.model.desk.TaskModel.
connectionList Listing to add removed net.officefloor.model.ConnectionModel instances.
 
 	private void removeTaskConnections(TaskModel task,
 			List<ConnectionModelconnectionList) {
 
 		// Remove input connections (copy to stop concurrent)
 			conn.remove();
 			connectionList.add(conn);
 		}
 			conn.remove();
 			connectionList.add(conn);
 		}
 			conn.remove();
 			connectionList.add(conn);
 		}
 
 		// Remove flow connections
 		for (TaskFlowModel flow : task.getTaskFlows()) {
 			this.removeTaskFlowConnections(flowconnectionList);
 		}
 
 		// Remove next connections
 		TaskToNextTaskModel connNextTask = task.getNextTask();
 		if (connNextTask != null) {
 			connNextTask.remove();
 			connectionList.add(connNextTask);
 		}
 		TaskToNextExternalFlowModel connNextExtFlow = task
 		if (connNextExtFlow != null) {
 			connNextExtFlow.remove();
 			connectionList.add(connNextExtFlow);
 		}
 
 		// Remove escalation connections
 		for (TaskEscalationModel escalation : task.getTaskEscalations()) {
 			this.removeTaskEscalationConnections(escalationconnectionList);
 		}
 	}

Removes the connections to the net.officefloor.model.desk.TaskFlowModel.

Parameters:
taskFlow net.officefloor.model.desk.TaskFlowModel.
connectionList Listing to add the removed net.officefloor.model.ConnectionModel instances.
 
 	private void removeTaskFlowConnections(TaskFlowModel taskFlow,
 			List<ConnectionModelconnectionList) {
 
 		// Remove connection to task
 		TaskFlowToTaskModel connTask = taskFlow.getTask();
 		if (connTask != null) {
 			connTask.remove();
 			connectionList.add(connTask);
 		}
 
 		// Remove connection to external flow
 		TaskFlowToExternalFlowModel connExtFlow = taskFlow.getExternalFlow();
 		if (connExtFlow != null) {
 			connExtFlow.remove();
 			connectionList.add(connExtFlow);
 		}
 	}

Removes the connections to the net.officefloor.model.desk.TaskEscalationModel.

Parameters:
taskEscalation net.officefloor.model.desk.TaskEscalationModel.
connectionList Listing to add the removed net.officefloor.model.ConnectionModel instances.
 
 			TaskEscalationModel taskEscalation,
 			List<ConnectionModelconnectionList) {
 
 		// Remove connection to task
 		TaskEscalationToTaskModel connTask = taskEscalation.getTask();
 		if (connTask != null) {
 			connTask.remove();
 			connectionList.add(connTask);
 		}
 
 		// Remove connection to external flow
 		TaskEscalationToExternalFlowModel connExtFlow = taskEscalation
 		if (connExtFlow != null) {
 			connExtFlow.remove();
 			connectionList.add(connExtFlow);
 		}
 	}

Removes the connections to the net.officefloor.model.desk.WorkTaskModel and its associated net.officefloor.model.desk.TaskModel instances.

Parameters:
workTask net.officefloor.model.desk.WorkTaskModel.
connectionList Listing to add the removed net.officefloor.model.ConnectionModel instances.
 
 	private void removeWorkTaskConnections(WorkTaskModel workTask,
 			List<ConnectionModelconnectionList) {
 
 		// Remove object connections
 		for (WorkTaskObjectModel taskObject : workTask.getTaskObjects()) {
 			this.removeWorkTaskObjectConnections(taskObjectconnectionList);
 		}
 
 		// Remove task connections (copy to stop concurrent)
 				workTask.getTasks())) {
 			TaskModel task = taskConn.getTask();
 			this.removeTaskConnections(taskconnectionList);
 		}
 	}

Removes the connections to the net.officefloor.model.desk.WorkTaskObjectModel.

Parameters:
workTaskObject net.officefloor.model.desk.WorkTaskObjectModel.
connectionList Listing to add the removed net.officefloor.model.ConnectionModel instances.
 
 			WorkTaskObjectModel workTaskObject,
 			List<ConnectionModelconnectionList) {
 
 		// Remove connection to external managed object
 		if (conn != null) {
 			conn.remove();
 			connectionList.add(conn);
 		}
 	}

Removes the net.officefloor.model.desk.TaskModel instances associated to the net.officefloor.model.desk.WorkTaskModel.

Parameters:
workTask net.officefloor.model.desk.WorkTaskModel.
taskList Listing to add the removed net.officefloor.model.desk.TaskModel instances.
 
 	private void removeWorkTask(WorkTaskModel workTaskList<TaskModeltaskList) {
 		for (WorkTaskToTaskModel conn : workTask.getTasks()) {
 			TaskModel task = conn.getTask();
 
 			// Remove task and store for revert
 			taskList.add(task);
 		}
 	}
 
 	/*
 	 * ==================== DeskOperations =================================
 	 */
 
 	public <W extends WorkChange<WorkModeladdWork(String workName,
 			String workSourceClassNamePropertyList properties,
 			WorkType<W> workTypeString... taskNames) {
 
 		// Create the work model for the work type
 		final WorkModel work = new WorkModel(workNameworkSourceClassName);
 
 		// Add the properties to source the work again
 		for (Property property : properties) {
 			work.addProperty(new PropertyModel(property.getName(), property
 					.getValue()));
 		}
 
 		// Create the set of task names to include
 		Set<StringincludeTaskNames = new HashSet<String>();
 		for (String taskName : taskNames) {
 			includeTaskNames.add(taskName);
 		}
 
 		// Add the work task models
 		for (TaskType<?, ?, ?> taskType : workType.getTaskTypes()) {
 
 			// Determine if include the task type
 			String taskName = taskType.getTaskName();
 			if ((includeTaskNames.size() > 0)
 					&& (!includeTaskNames.contains(taskName))) {
 				// Task to not be included
 				continue;
 			}
 
 			// Create and add the work task model
 			WorkTaskModel workTask = DeskChangesImpl.this
 					.createWorkTaskModel(taskType);
 			work.addWorkTask(workTask);
 		}
 
 		// Ensure work task models in sorted order
 		DeskChangesImpl.sortWorkTaskModels(work.getWorkTasks());
 
 		// Return the change to add the work
 		return new AbstractChange<WorkModel>(work"Add work " + workName) {
 			public void apply() {
 				// Add the work (ensuring in sorted order)
 			}
 
 			public void revert() {
 			}
 		};
 	}
 
 	public Change<WorkModelremoveWork(final WorkModel workModel) {
 
 		// Ensure the work is on the desk
 		boolean isOnDesk = false;
 		for (WorkModel work : this..getWorks()) {
 			if (work == workModel) {
 				isOnDesk = true;
 			}
 		}
 		if (!isOnDesk) {
 			// Not on desk so can not remove
 			return new NoChange<WorkModel>(workModel"Remove work "
 					+ workModel.getWorkName(), "Work "
 					+ workModel.getWorkName() + " not on desk");
 		}
 
 		// Return change to remove the work
 		return new AbstractChange<WorkModel>(workModel"Remove work "
 				+ workModel.getWorkName()) {

 
 			private TaskModel[] tasks;

 
 
 			public void apply() {
 
 				// Remove connections to work and its tasks
 				List<ConnectionModelconnectionList = new LinkedList<ConnectionModel>();
 				for (WorkTaskModel workTask : workModel.getWorkTasks()) {
 							connectionList);
 				}
 				this. = connectionList
 
 				// Remove the associated tasks (storing for revert)
 				List<TaskModeltaskList = new LinkedList<TaskModel>();
 				for (WorkTaskModel workTask : workModel.getWorkTasks()) {
 					DeskChangesImpl.this.removeWorkTask(workTasktaskList);
 				}
 				this. = taskList.toArray(new TaskModel[0]);
 
 				// Remove the work
 				DeskChangesImpl.this..removeWork(workModel);
 			}
 
 			public void revert() {
 				// Add the work (ensuring in sorted order)
 				DeskChangesImpl.this..addWork(workModel);
 
 				// Add the tasks (in reverse order, ensuring sorted)
 				for (int i = (this..length - 1); i >= 0; i--) {
 				}
 
 				// Reconnect connections
 				for (ConnectionModel connection : this.) {
 					connection.connect();
 				}
 			}
 		};
 	}
 
 	public Change<WorkModelrenameWork(final WorkModel workModel,
 			final String newWorkName) {
 
 		// Ensure the work is on the desk
 		boolean isOnDesk = false;
 		for (WorkModel work : this..getWorks()) {
 			if (work == workModel) {
 				isOnDesk = true;
 			}
 		}
 		if (!isOnDesk) {
 			// Not on desk so can not remove
 			return new NoChange<WorkModel>(workModel"Rename work "
 					+ workModel.getWorkName() + " to " + newWorkName"Work "
 					+ workModel.getWorkName() + " not on desk");
 		}
 
 		// Store the old name for reverting
 		final String oldWorkName = workModel.getWorkName();
 
 		// Return change to rename work
 		return new AbstractChange<WorkModel>(workModel"Rename work "
 				+ workModel.getWorkName() + " to " + newWorkName) {
 			public void apply() {
 				// Rename and ensure work in sorted order
 				workModel.setWorkName(newWorkName);
 			}
 
 			public void revert() {
 				// Revert to old name, ensuring work sorted
 				workModel.setWorkName(oldWorkName);
 			}
 		};
 	}
 
 	public <W extends WorkChange<WorkModelrefactorWork(
 			final WorkModel workModelfinal String workName,
 			final String workSourceClassNamePropertyList properties,
 			WorkType<W> workTypeMap<StringStringworkTaskNameMapping,
 			Map<StringMap<StringString>> workTaskToObjectNameMapping,
 			Map<StringMap<StringString>> taskToFlowNameMapping,
 			Map<StringMap<StringString>> taskToEscalationTypeMapping,
 			String... taskNames) {
 
 		// Create the list to contain all refactor changes
 		final List<Change<?>> refactor = new LinkedList<Change<?>>();
 
 		// ------------------- Details of WorkModel --------------------
 
 		// Add change to rename the work
 		final String existingWorkName = workModel.getWorkName();
 		refactor.add(new AbstractChange<WorkModel>(workModel"Rename work") {
 			public void apply() {
 				workModel.setWorkName(workName);
 			}
 
 			public void revert() {
 				workModel.setWorkName(existingWorkName);
 			}
 		});
 
 		// Add change for work class source name
 		final String existingWorkSourceClassName = workModel
 		refactor.add(new AbstractChange<WorkModel>(workModel,
 				"Change WorkSource class") {
 			public void apply() {
 				workModel.setWorkSourceClassName(workSourceClassName);
 			}
 
 			public void revert() {
 				workModel.setWorkSourceClassName(existingWorkSourceClassName);
 			}
 		});
 
 		// Add change to the properties
 		final List<PropertyModelexistingProperties = new ArrayList<PropertyModel>(
 				workModel.getProperties());
 		final List<PropertyModelnewProperties = new LinkedList<PropertyModel>();
 		for (Property property : properties) {
 			newProperties.add(new PropertyModel(property.getName(), property
 					.getValue()));
 		}
 		refactor.add(new AbstractChange<WorkModel>(workModel,
 				"Change work properties") {
 			public void apply() {
 				for (PropertyModel property : existingProperties) {
 					workModel.removeProperty(property);
 				}
 				for (PropertyModel property : newProperties) {
 					workModel.addProperty(property);
 				}
 			}
 
 			public void revert() {
 				for (PropertyModel property : newProperties) {
 					workModel.removeProperty(property);
 				}
 				for (PropertyModel property : existingProperties) {
 					workModel.addProperty(property);
 				}
 			}
 		});
 
 		// ---------------- WorkTaskModel / TaskModel --------------------
 
 		// Create the map of existing work tasks to their names
 		Map<StringWorkTaskModelexistingWorkTasks = new HashMap<StringWorkTaskModel>();
 		for (WorkTaskModel workTask : workModel.getWorkTasks()) {
 			existingWorkTasks.put(workTask.getWorkTaskName(), workTask);
 		}
 
 		// Create the set of tasks to include
 		Set<StringincludeTaskNames = new HashSet<String>(Arrays
 				.asList(taskNames));
 
 		// Refactor tasks
 		TaskType<?, ?, ?>[] taskTypes = workType.getTaskTypes();
 		List<WorkTaskModeltargetTaskList = new LinkedList<WorkTaskModel>();
 		for (int t = 0; t < taskTypes.lengtht++) {
 			TaskType<?, ?, ?> taskType = taskTypes[t];
 
 			// Obtain the details of the task type
 			final String workTaskName = taskType.getTaskName();
 			Class<?> returnClass = taskType.getReturnType();
 			final String returnTypeName = (returnClass == null ? null
 					: returnClass.getName());
 
 			// Determine if include the task
 			if ((includeTaskNames.size() > 0)
 					&& (!(includeTaskNames.contains(workTaskName)))) {
 				continue// task filtered from being included
 			}
 
 			// Obtain the work task for task type (may need to create)
 			WorkTaskModel findWorkTask = this.getExistingItem(workTaskName,
 					workTaskNameMappingexistingWorkTasks);
 			final WorkTaskModel workTask = ((findWorkTask == null) ? new WorkTaskModel(
 					workTaskName)
 					: findWorkTask);
 			targetTaskList.add(workTask);
 
 			// Refactor details of work task (and tasks)
 			final String existingWorkTaskName = workTask.getWorkTaskName();
 			refactor.add(new AbstractChange<WorkTaskModel>(workTask,
 					"Refactor work task") {

Existing return types for the net.officefloor.model.desk.TaskModel instances.
 
 
 				public void apply() {
 					// Specify new task name
 					workTask.setWorkTaskName(workTaskName);
 					for (WorkTaskToTaskModel conn : workTask.getTasks()) {
 						TaskModel task = conn.getTask();
 						task.setWorkTaskName(workTaskName);
 								.put(tasktask.getReturnType());
 						task.setReturnType(returnTypeName);
 					}
 				}
 
 				public void revert() {
 					// Revert to existing task name
 					workTask.setWorkTaskName(existingWorkTaskName);
 					for (WorkTaskToTaskModel conn : workTask.getTasks()) {
 						TaskModel task = conn.getTask();
 						task.setWorkTaskName(existingWorkTaskName);
 					}
 				}
 			});
 
 			// ------------------- WorkTaskObjectModel --------------------
 
 			// Work task to be refactored, so obtain object name mappings
 			Map<StringStringobjectTargetToExisting = workTaskToObjectNameMapping
 					.get(workTaskName);
 			if (objectTargetToExisting == null) {
 				// Provide default empty map
 				objectTargetToExisting = new HashMap<StringString>(0);
 			}
 
 			// Create the map of existing work task objects to their names
 			Map<StringWorkTaskObjectModelexistingWorkTaskObjects = new HashMap<StringWorkTaskObjectModel>();
 			for (WorkTaskObjectModel workTaskObject : workTask.getTaskObjects()) {
 				existingWorkTaskObjects.put(workTaskObject.getObjectName(),
 						workTaskObject);
 			}
 
 			// Obtain the objects in order as per type
 			TaskObjectType<?>[] objectTypes = taskType.getObjectTypes();
 			final WorkTaskObjectModel[] targetObjectOrder = new WorkTaskObjectModel[objectTypes.length];
 			for (int o = 0; o < objectTypes.lengtho++) {
 				TaskObjectType<?> objectType = objectTypes[o];
 
 				// Obtain the details of the object type
 				final String objectName = objectType.getObjectName();
 				Enum<?> objectKey = objectType.getKey();
 				final String objectKeyName = (objectKey == null ? null
 						: objectKey.name());
 				Class<?> objectClass = objectType.getObjectType();
 				final String objectTypeName = (objectClass == null ? null
 						: objectClass.getName());
 
 				// Obtain the object for object type (may need to create)
 				WorkTaskObjectModel findWorkTaskObject = this.getExistingItem(
 						objectNameobjectTargetToExisting,
 						existingWorkTaskObjects);
 				final WorkTaskObjectModel workTaskObject = ((findWorkTaskObject == null) ? new WorkTaskObjectModel(
 						objectNameobjectKeyNameobjectTypeNamefalse)
 						: findWorkTaskObject);
 				targetObjectOrder[o] = workTaskObject;
 
 				// Refactor details of object
 				final String existingObjectName = workTaskObject
 				final String existingKeyName = workTaskObject.getKey();
 				final String existingTypeName = workTaskObject.getObjectType();
 						workTaskObject"Refactor work task object") {
 					public void apply() {
 						workTaskObject.setObjectName(objectName);
 						workTaskObject.setKey(objectKeyName);
 						workTaskObject.setObjectType(objectTypeName);
 					}
 
 					public void revert() {
 						workTaskObject.setObjectName(existingObjectName);
 						workTaskObject.setKey(existingKeyName);
 						workTaskObject.setObjectType(existingTypeName);
 					}
 				});
 			}
 
 			// Obtain the existing object order
 			final WorkTaskObjectModel[] existingObjectOrder = workTask
 
 			// Add changes to disconnect existing objects to be removed
 					Arrays.asList(targetObjectOrder));
 			for (WorkTaskObjectModel existingObject : existingObjectOrder) {
 				if (!(targetObjects.contains(existingObject))) {
 					// Add change to disconnect object
 					final WorkTaskObjectModel taskObject = existingObject;
 							existingObject) {
 						protected void populateRemovedConnections(
 								List<ConnectionModelconnList) {
 											taskObjectconnList);
 						}
 					});
 				}
 			}
 
 			// Add change to order the refactored objects
 			refactor.add(new AbstractChange<WorkTaskModel>(workTask,
 					"Refactor objects of work task") {
 				public void apply() {
 					// Remove existing objects, add target objects
 					for (WorkTaskObjectModel object : existingObjectOrder) {
 						workTask.removeTaskObject(object);
 					}
 					for (WorkTaskObjectModel object : targetObjectOrder) {
 						workTask.addTaskObject(object);
 					}
 				}
 
 				public void revert() {
 					// Remove the target objects, add back existing
 					for (WorkTaskObjectModel object : targetObjectOrder) {
 						workTask.removeTaskObject(object);
 					}
 					for (WorkTaskObjectModel object : existingObjectOrder) {
 						workTask.addTaskObject(object);
 					}
 				}
 			});
 
 			// ---------------------- TaskModel ------------------------
 
 			// Refactor the tasks of the work task
 			for (WorkTaskToTaskModel workTaskToTask : workTask.getTasks()) {
 
 				// Ensure have task for connection
 				final TaskModel task = workTaskToTask.getTask();
 				if (task == null) {
 					continue// must have task
 				}
 
 				// Obtain details of task
 				String taskName = task.getTaskName();
 
 				// --------------- TaskFlowModel ------------------------
 
 				// Task to be refactored, so obtain flow name mappings
 				Map<StringStringflowTargetToExisting = taskToFlowNameMapping
 						.get(taskName);
 				if (flowTargetToExisting == null) {
 					// Provide default empty map
 					flowTargetToExisting = new HashMap<StringString>(0);
 				}
 
 				// Create the map of existing task flows to their names
 				Map<StringTaskFlowModelexistingTaskFlows = new HashMap<StringTaskFlowModel>();
 				for (TaskFlowModel taskFlow : task.getTaskFlows()) {
 					existingTaskFlows.put(taskFlow.getFlowName(), taskFlow);
 				}
 
 				// Obtain the flows in order of type
 				TaskFlowType<?>[] flowTypes = taskType.getFlowTypes();
 				final TaskFlowModel[] targetFlowOrder = new TaskFlowModel[flowTypes.length];
 				for (int f = 0; f < targetFlowOrder.lengthf++) {
 					TaskFlowType<?> flowType = flowTypes[f];
 
 					// Obtain the details of the flow type
 					final String flowName = flowType.getFlowName();
 					Enum<?> flowKey = flowType.getKey();
 					final String flowKeyName = (flowKey == null ? null
 							: flowKey.name());
 					Class<?> argumentType = flowType.getArgumentType();
 					final String argumentTypeName = (argumentType == null ? null
 							: argumentType.getName());
 
 					// Obtain the flow for flow type (may need to create)
 					TaskFlowModel findTaskFlow = this.getExistingItem(flowName,
 							flowTargetToExistingexistingTaskFlows);
 					final TaskFlowModel taskFlow = ((findTaskFlow == null) ? new TaskFlowModel(
 							flowNameflowKeyNameargumentTypeName)
 							: findTaskFlow);
 					targetFlowOrder[f] = taskFlow;
 
 					// Refactor details of flow
 					final String existingFlowName = taskFlow.getFlowName();
 					final String existingFlowKeyName = taskFlow.getKey();
 					final String existingArgumentTypeName = taskFlow
 					refactor.add(new AbstractChange<TaskFlowModel>(taskFlow,
 							"Refactor task flow") {
 						public void apply() {
 							taskFlow.setFlowName(flowName);
							taskFlow.setKey(flowKeyName);
							taskFlow.setArgumentType(argumentTypeName);
						public void revert() {
							taskFlow.setFlowName(existingFlowName);
							taskFlow.setKey(existingFlowKeyName);
							taskFlow.setArgumentType(existingArgumentTypeName);
					});
				// Obtain the existing flow order
				final TaskFlowModel[] existingFlowOrder = task.getTaskFlows()
				// Add changes to disconnect existing flows to be removed
				Set<TaskFlowModeltargetFlows = new HashSet<TaskFlowModel>(
						Arrays.asList(targetFlowOrder));
				for (TaskFlowModel existingTaskFlow : existingFlowOrder) {
					if (!(targetFlows.contains(existingTaskFlow))) {
						// Add change to disconnect flow
						final TaskFlowModel taskFlow = existingTaskFlow;
								taskFlow) {
									List<ConnectionModelconnList) {
										taskFlowconnList);
						});
				// Add change to order the refactored flows
				refactor.add(new AbstractChange<TaskModel>(task,
						"Refactor task flows") {
					public void apply() {
						// Remove existing flows, add target flows
						for (TaskFlowModel flow : existingFlowOrder) {
							task.removeTaskFlow(flow);
						for (TaskFlowModel flow : targetFlowOrder) {
							task.addTaskFlow(flow);
					public void revert() {
						// Remove target flows, add back existing flows
						for (TaskFlowModel flow : targetFlowOrder) {
							task.removeTaskFlow(flow);
						for (TaskFlowModel flow : existingFlowOrder) {
							task.addTaskFlow(flow);
				});
				// --------------- TaskEscalationModel ------------------
				// Task to be refactored, so obtain escalation name mappings
				Map<StringStringescalationTargetToExisting = taskToEscalationTypeMapping
						.get(taskName);
				if (escalationTargetToExisting == null) {
					// Provide default empty map
					escalationTargetToExisting = new HashMap<StringString>(0);
				// Create the map of existing task escalations to their names
				Map<StringTaskEscalationModelexistingTaskEscalations = new HashMap<StringTaskEscalationModel>();
				for (TaskEscalationModel taskEscalation : task
					existingTaskEscalations.put(taskEscalation
							.getEscalationType(), taskEscalation);
				// Obtain the escalations in order of type
				TaskEscalationType[] escalationTypes = taskType
				final TaskEscalationModel[] targetEscalationOrder = new TaskEscalationModel[escalationTypes.length];
				for (int e = 0; e < targetEscalationOrder.lengthe++) {
					TaskEscalationType escalationType = escalationTypes[e];
					// Obtain details of the escalation type
					final String escalationTypeName = escalationType
					// Obtain the escalation for escalation type (may create)
					TaskEscalationModel findTaskEscalation = this
							.getExistingItem(escalationTypeName,
									escalationTargetToExisting,
									existingTaskEscalations);
					final TaskEscalationModel taskEscalation = ((findTaskEscalation == null) ? new TaskEscalationModel(
							escalationTypeName)
findTaskEscalation);
					targetEscalationOrder[e] = taskEscalation;
					// Refactor details of escalation
					final String existingEscalationTypeName = taskEscalation
							taskEscalation"Refactor task escalation") {
						public void apply() {
							taskEscalation
									.setEscalationType(escalationTypeName);
						public void revert() {
							taskEscalation
									.setEscalationType(existingEscalationTypeName);
					});
				// Obtain the existing escalation order
				final TaskEscalationModel[] existingEscalationOrder = task
				// Add changes to disconnect existing escalations to be removed
				Set<TaskEscalationModeltargetEscalations = new HashSet<TaskEscalationModel>(
						Arrays.asList(targetEscalationOrder));
				for (TaskEscalationModel existingEscalation : existingEscalationOrder) {
					if (!(targetEscalations.contains(existingEscalation))) {
						// Add change to disconnect escalation
						final TaskEscalationModel taskEscalation = existingEscalation;
								taskEscalation) {
									List<ConnectionModelconnList) {
												taskEscalationconnList);
						});
				// Add change to order the refactored escalations
				refactor.add(new AbstractChange<TaskModel>(task,
						"Refactor task escalations") {
					public void apply() {
						// Remove existing escalations, add target escalations
						for (TaskEscalationModel escalation : existingEscalationOrder) {
							task.removeTaskEscalation(escalation);
						for (TaskEscalationModel escalation : targetEscalationOrder) {
							task.addTaskEscalation(escalation);
					public void revert() {
						// Remove target escalations, add back existing
						for (TaskEscalationModel escalation : targetEscalationOrder) {
							task.removeTaskEscalation(escalation);
						for (TaskEscalationModel escalation : existingEscalationOrder) {
							task.addTaskEscalation(escalation);
				});
		// ------------ WorkTaskModel / TaskModel (continued) ----------------
		// Obtain the target work task order
		final WorkTaskModel[] targetTaskOrder = targetTaskList
		// Obtain existing work task order
		final WorkTaskModel[] existingTaskOrder = workModel.getWorkTasks()
		// Add changes to disconnect existing tasks to be removed
		Set<WorkTaskModeltargetTasks = new HashSet<WorkTaskModel>(Arrays
				.asList(targetTaskOrder));
		for (WorkTaskModel existingTask : existingTaskOrder) {
			if (!(targetTasks.contains(existingTask))) {
				final WorkTaskModel workTask = existingTask;
				// Add change to disconnect work task (and its tasks)
				refactor.add(new DisconnectChange<WorkTaskModel>(workTask) {
							List<ConnectionModelconnList) {
								workTaskconnList);
				});
				// Add change to remove tasks of work task
				refactor.add(new AbstractChange<WorkTaskModel>(workTask,
						"Remove tasks of work task") {

					private List<TaskModeltasks;
					public void apply() {
						this. = new LinkedList<TaskModel>();
								this.);
					public void revert() {
						// Add back the task models
						for (TaskModel task : this.) {
				});
		// Add change to order the new tasks
		refactor.add(new AbstractChange<WorkModel>(workModel,
				"Refactor tasks of work") {
			public void apply() {
				// Remove existing tasks, add target tasks
				for (WorkTaskModel task : existingTaskOrder) {
					workModel.removeWorkTask(task);
				for (WorkTaskModel task : targetTaskOrder) {
					workModel.addWorkTask(task);
			public void revert() {
				// Remove the target tasks, add back existing
				for (