[TRUNK][FEATURE]

- adds association class for tasks dependencies
- adds export capability for task dependencies

git-svn-id: https://svn.libreccm.org/ccm/trunk@5165 8810af33-2d31-482b-a856-94f89814c4df
master
tosmers 2017-12-12 17:43:36 +00:00
parent 6d81102967
commit a0b89a168d
8 changed files with 276 additions and 72 deletions

View File

@ -32,6 +32,7 @@ import com.arsdigita.portation.modules.core.workflow.AssignableTask;
import com.arsdigita.portation.modules.core.workflow.Task; import com.arsdigita.portation.modules.core.workflow.Task;
import com.arsdigita.portation.modules.core.workflow.TaskAssignment; import com.arsdigita.portation.modules.core.workflow.TaskAssignment;
import com.arsdigita.portation.modules.core.workflow.TaskComment; import com.arsdigita.portation.modules.core.workflow.TaskComment;
import com.arsdigita.portation.modules.core.workflow.TaskDependency;
import com.arsdigita.portation.modules.core.workflow.Workflow; import com.arsdigita.portation.modules.core.workflow.Workflow;
import java.util.ArrayList; import java.util.ArrayList;
@ -62,6 +63,7 @@ public class NgCoreCollection {
public static Map<Long, TaskComment> taskComments = new HashMap<>(); public static Map<Long, TaskComment> taskComments = new HashMap<>();
public static Map<Long, Task> tasks = new HashMap<>(); public static Map<Long, Task> tasks = new HashMap<>();
public static Map<Long, AssignableTask> assignableTasks = new HashMap<>(); public static Map<Long, AssignableTask> assignableTasks = new HashMap<>();
public static Map<Long, TaskDependency> taskDependencies = new HashMap<>();
public static Map<Long, TaskAssignment> taskAssignments = new HashMap<>(); public static Map<Long, TaskAssignment> taskAssignments = new HashMap<>();
public static Map<Long, Permission> permissions = new HashMap<>(); public static Map<Long, Permission> permissions = new HashMap<>();

View File

@ -100,7 +100,8 @@ public class GroupConversion {
if (group != null && member != null) { if (group != null && member != null) {
// create groupMemeberships // create groupMemeberships
GroupMembership groupMembership = new GroupMembership(group, member); GroupMembership groupMembership = new GroupMembership(group,
member);
// set opposed associations // set opposed associations
group.addMembership(groupMembership); group.addMembership(groupMembership);

View File

@ -28,9 +28,9 @@ import com.arsdigita.portation.modules.core.workflow.AssignableTask;
import com.arsdigita.portation.modules.core.workflow.Task; import com.arsdigita.portation.modules.core.workflow.Task;
import com.arsdigita.portation.modules.core.workflow.TaskAssignment; import com.arsdigita.portation.modules.core.workflow.TaskAssignment;
import com.arsdigita.portation.modules.core.workflow.TaskComment; import com.arsdigita.portation.modules.core.workflow.TaskComment;
import com.arsdigita.portation.modules.core.workflow.TaskDependency;
import com.arsdigita.portation.modules.core.workflow.Workflow; import com.arsdigita.portation.modules.core.workflow.Workflow;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
@ -59,9 +59,9 @@ public class AssignableTaskConversion {
.arsdigita.workflow.simple.UserTask.getAllObjectUserTasks(); .arsdigita.workflow.simple.UserTask.getAllObjectUserTasks();
System.err.println("done."); System.err.println("done.");
System.err.printf("\tConverting assignable tasks and task assignments...\n"); System.err.printf("\tConverting assignable tasks, task dependencies " +
"and task assignments...\n");
createAssignableTasksAndSetAssociations(trunkUserTasks); createAssignableTasksAndSetAssociations(trunkUserTasks);
setTaskRingDependencies(trunkUserTasks);
System.err.printf("\tSorting task assignments...\n"); System.err.printf("\tSorting task assignments...\n");
sortAssignableTaskMap(); sortAssignableTaskMap();
@ -79,11 +79,13 @@ public class AssignableTaskConversion {
*/ */
private static void createAssignableTasksAndSetAssociations(List<com.arsdigita private static void createAssignableTasksAndSetAssociations(List<com.arsdigita
.workflow.simple.UserTask> trunkUserTasks) { .workflow.simple.UserTask> trunkUserTasks) {
int pTasks = 0, pAssignments = 0; int pTasks = 0, pAssignments = 0, pDependencies = 0;
for (com.arsdigita.workflow.simple.UserTask trunkUserTask : for (com.arsdigita.workflow.simple.UserTask trunkUserTask :
trunkUserTasks) { trunkUserTasks) {
// TASK STUFF
// create assignableTask // create assignableTask
AssignableTask assignableTask = new AssignableTask(trunkUserTask); AssignableTask assignableTask = new AssignableTask(trunkUserTask);
@ -101,6 +103,10 @@ public class AssignableTaskConversion {
} }
} catch (Exception ignored) {} } catch (Exception ignored) {}
// taskDependencies
pDependencies += createTaskDependencies(assignableTask,
trunkUserTask.getDependencies());
// set taskComments // set taskComments
Iterator commentsIt = trunkUserTask.getComments(); Iterator commentsIt = trunkUserTask.getComments();
while (commentsIt.hasNext()) { while (commentsIt.hasNext()) {
@ -116,6 +122,8 @@ public class AssignableTaskConversion {
} }
// ASSIGNABLETASK STUFF
// set lockingUser and notificationSender // set lockingUser and notificationSender
if (trunkUserTask.getLockedUser() != null) { if (trunkUserTask.getLockedUser() != null) {
User lockingUser = NgCoreCollection.users.get(trunkUserTask User lockingUser = NgCoreCollection.users.get(trunkUserTask
@ -138,11 +146,57 @@ public class AssignableTaskConversion {
groupCollection); groupCollection);
pTasks++; pTasks++;
/*System.err.printf("\t\tTasks: %d, " +
"Dependencies: %d, " +
"Assignments: %d\n",
pTasks, pDependencies, pAssignments);*/
} }
System.err.printf("\t\tCreated %d assignable tasks and\n" + System.err.printf("\t\tCreated %d assignable tasks and\n" +
"\t\tCreated %d task dependencies and\n" +
"\t\tcreated %d task assignments.\n", "\t\tcreated %d task assignments.\n",
pTasks, pAssignments); pTasks, pDependencies, pAssignments);
}
/**
* Method for recreating the
* ng-{@link com.arsdigita.portation.modules.core.workflow.Task}s ring-like
* dependencies between dependentTask and dependsOn. Because all
* ng-{@link com.arsdigita.portation.modules.core.workflow.Task}s have
* already been created, it is possible e.g. to find the dependsOn-{@code
* Tasks} and bind them for association.
*
* @param assignableTask The {@link AssignableTask}
* @param dependencyIt An iterator representing all dependencies of the
* given assignableTask
*/
private static long createTaskDependencies(AssignableTask assignableTask,
Iterator dependencyIt) {
int processed = 0;
while (dependencyIt.hasNext()) {
AssignableTask dependency = NgCoreCollection
.assignableTasks
.get(((com.arsdigita.workflow.simple
.Task) dependencyIt.next())
.getID()
.longValue());
if (assignableTask != null && dependency != null) {
TaskDependency taskDependency =
new TaskDependency(assignableTask, dependency);
// set opposed associations
assignableTask.addBlockingTask(taskDependency);
dependency.addBlockedTask(taskDependency);
processed++;
}
}
return processed;
} }
/** /**
@ -184,43 +238,6 @@ public class AssignableTaskConversion {
return processed; return processed;
} }
/**
* Method for recreating the
* ng-{@link com.arsdigita.portation.modules.core.workflow.Task}s ring-like
* dependencies between dependentTask and dependsOn. Because all
* ng-{@link com.arsdigita.portation.modules.core.workflow.Task}s have
* already been created, it is possible e.g. to find the dependsOn-{@code
* Tasks} and bind them for association.
*
* @param trunkUserTasks List of all
* {@link com.arsdigita.workflow.simple.UserTask}s
* from this old trunk-system.
*/
private static void setTaskRingDependencies(List<com.arsdigita.workflow
.simple.UserTask> trunkUserTasks) {
for (com.arsdigita.workflow.simple.UserTask trunkUserTask :
trunkUserTasks) {
AssignableTask assignableTask = NgCoreCollection
.assignableTasks
.get(trunkUserTask.getID().longValue());
Iterator it = trunkUserTask.getDependencies();
while (it.hasNext()) {
AssignableTask dependency = NgCoreCollection
.assignableTasks
.get(((com.arsdigita.workflow.simple
.Task) it.next()).getID().longValue());
if (assignableTask != null && dependency != null) {
// set dependencies and opposed
assignableTask.addDependsOn(dependency);
dependency.addDependentTask(assignableTask);
}
}
}
}
/** /**
* Sorts values of assignable-task-map to ensure that the dependencies will * Sorts values of assignable-task-map to ensure that the dependencies will
* be listed before their dependant tasks in the export file. * be listed before their dependant tasks in the export file.
@ -258,16 +275,17 @@ public class AssignableTaskConversion {
*/ */
private static void addDependencies(ArrayList<AssignableTask> sortedList, private static void addDependencies(ArrayList<AssignableTask> sortedList,
AssignableTask assignableTask) { AssignableTask assignableTask) {
List<Task> dependencies = assignableTask.getDependsOn(); List<TaskDependency> dependencies = assignableTask.getBlockingTasks();
if (!dependencies.isEmpty()) { if (!dependencies.isEmpty()) {
for (Task dependsOnTask : dependencies) { for (TaskDependency dependency : dependencies) {
AssignableTask dependency = (AssignableTask) dependsOnTask; AssignableTask blockingTask = (AssignableTask) dependency
if (dependency != null) { .getBlockingTask();
addDependencies(sortedList, dependency); if (blockingTask != null) {
addDependencies(sortedList, blockingTask);
if (!sortedList.contains(dependency)) if (!sortedList.contains(blockingTask))
sortedList.add(dependency); sortedList.add(blockingTask);
} }
} }
} }

View File

@ -51,6 +51,7 @@ public class CoreExporter extends AbstractExporter {
exportWorkflows(); exportWorkflows();
exportTaskComments(); exportTaskComments();
exportAssignableTasks(); exportAssignableTasks();
exportTaskDependencies();
exportTaskAssignments(); exportTaskAssignments();
} }
@ -171,6 +172,17 @@ public class CoreExporter extends AbstractExporter {
System.out.printf("\tdone.\n"); System.out.printf("\tdone.\n");
} }
private static void exportTaskDependencies() {
System.out.printf("\tExporting task dependencies...");
TaskDependencyMarshaller taskDependencyMarshaller = new
TaskDependencyMarshaller();
taskDependencyMarshaller.prepare(
Format.XML, pathName, "taskDependencies", indentation);
taskDependencyMarshaller.exportList(
new ArrayList<>(NgCoreCollection.taskDependencies.values()));
System.out.printf("\tdone.\n");
}
private static void exportTaskAssignments() { private static void exportTaskAssignments() {
System.out.printf("\tExporting task assignments..."); System.out.printf("\tExporting task assignments...");
TaskAssignmentMarshaller taskAssignmentMarshaller = new TaskAssignmentMarshaller taskAssignmentMarshaller = new

View File

@ -49,9 +49,9 @@ public class Task {
@JsonIdentityReference(alwaysAsId = true) @JsonIdentityReference(alwaysAsId = true)
private Workflow workflow; private Workflow workflow;
@JsonIgnore @JsonIgnore
private List<Task> dependentTasks; private List<TaskDependency> blockedTasks;
@JsonIdentityReference(alwaysAsId = true) @JsonIgnore
private List<Task> dependsOn; private List<TaskDependency> blockingTasks;
@JsonIdentityReference(alwaysAsId = true) @JsonIdentityReference(alwaysAsId = true)
private List<TaskComment> comments; private List<TaskComment> comments;
@ -70,8 +70,8 @@ public class Task {
//this.workflow //this.workflow
this.dependentTasks = new ArrayList<>(); this.blockedTasks = new ArrayList<>();
this.dependsOn = new ArrayList<>(); this.blockingTasks = new ArrayList<>();
this.comments = new ArrayList<>(); this.comments = new ArrayList<>();
NgCoreCollection.tasks.put(this.getTaskId(), this); NgCoreCollection.tasks.put(this.getTaskId(), this);
@ -133,37 +133,36 @@ public class Task {
this.workflow = workflow; this.workflow = workflow;
} }
public List<Task> getDependentTasks() { public List<TaskDependency> getBlockedTasks() {
return dependentTasks; return blockedTasks;
} }
public void setDependentTasks(final List<Task> dependentTasks) { public void setBlockedTasks(final List<TaskDependency> blockedTasks) {
this.dependentTasks = dependentTasks; this.blockedTasks = blockedTasks;
} }
public void addDependentTask(final Task task) { public void addBlockedTask(final TaskDependency blockedTask) {
dependentTasks.add(task); this.blockedTasks.add(blockedTask);
} }
public void removeDependentTask(final Task task) { public void removeBlockedTask(final TaskDependency blockedTask) {
dependentTasks.remove(task); this.blockedTasks.remove(blockedTask);
} }
public List<Task> getDependsOn() { public List<TaskDependency> getBlockingTasks() {
return dependsOn; return blockingTasks;
} }
public void setDependsOn(final List<Task> dependsOn) { public void setBlockingTasks(final List<TaskDependency> blockingTasks) {
this.dependsOn = dependsOn; this.blockingTasks = blockingTasks;
} }
public void addDependsOn(final Task task) { public void addBlockingTask(final TaskDependency blockingTask) {
dependsOn.add(task); this.blockingTasks.add(blockingTask);
} }
public void removeBlockingTask(final TaskDependency blockingTask) {
public void removeDependsOn(final Task task) { this.blockingTasks.remove(blockingTask);
dependsOn.remove(task);
} }
public List<TaskComment> getComments() { public List<TaskComment> getComments() {

View File

@ -0,0 +1,73 @@
/*
* Copyright (C) 2015 LibreCCM Foundation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package com.arsdigita.portation.modules.core.workflow;
import com.arsdigita.kernel.ACSObject;
import com.arsdigita.portation.Portable;
import com.arsdigita.portation.conversion.NgCoreCollection;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.JsonIdentityReference;
/**
* @author <a href="mailto:tosmers@uni-bremen.de>Tobias Osmers<\a>
* @version created the 12/12/17
*/
@JsonIdentityInfo(generator = TaskDependencyIdGenerator.class,
property = "customDepId")
public class TaskDependency implements Portable {
private long taskDependencyId;
@JsonIdentityReference(alwaysAsId = true)
private Task blockedTask;
@JsonIdentityReference(alwaysAsId = true)
private Task blockingTask;
public TaskDependency(final Task blockedTask, final Task blockingTask) {
this.taskDependencyId = ACSObject.generateID().longValue();
this.blockedTask = blockedTask;
this.blockingTask = blockingTask;
NgCoreCollection.taskDependencies.put(this.taskDependencyId, this);
}
public long getTaskDependencyId() {
return taskDependencyId;
}
public void setTaskDependencyId(long taskDependencyId) {
this.taskDependencyId = taskDependencyId;
}
public Task getBlockedTask() {
return blockedTask;
}
public void setBlockedTask(Task blockedTask) {
this.blockedTask = blockedTask;
}
public Task getBlockingTask() {
return blockingTask;
}
public void setBlockingTask(Task blockingTask) {
this.blockingTask = blockingTask;
}
}

View File

@ -0,0 +1,70 @@
/*
* Copyright (C) 2015 LibreCCM Foundation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package com.arsdigita.portation.modules.core.workflow;
import com.arsdigita.portation.modules.core.security.GroupMembership;
import com.fasterxml.jackson.annotation.ObjectIdGenerator;
/**
* @author <a href="mailto:tosmers@uni-bremen.de>Tobias Osmers<\a>
* @version created the 12/12/17
*/
public class TaskDependencyIdGenerator extends ObjectIdGenerator<String> {
@Override
public Class<?> getScope() {
return TaskDependency.class;
}
@Override
public boolean canUseFor(final ObjectIdGenerator<?> objectIdGenerator) {
return objectIdGenerator instanceof TaskDependencyIdGenerator;
}
@Override
public ObjectIdGenerator<String> forScope(final Class<?> aClass) {
return this;
}
@Override
public ObjectIdGenerator<String> newForSerialization(final Object o) {
return this;
}
@Override
public IdKey key(Object key) {
if (key == null) {
return null;
}
return new IdKey(TaskDependency.class, TaskDependency.class, key);
}
@Override
public String generateId(Object forPojo) {
if (!(forPojo instanceof TaskDependency)) {
throw new IllegalArgumentException(
"Only TaskDependency instances are supported.");
}
final TaskDependency dependency = (TaskDependency) forPojo;
return String.format("{%s}{%s}",
dependency.getBlockedTask().getUuid(),
dependency.getBlockingTask().getUuid());
}
}

View File

@ -0,0 +1,29 @@
/*
* Copyright (C) 2015 LibreCCM Foundation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package com.arsdigita.portation.modules.core.workflow;
import com.arsdigita.portation.AbstractMarshaller;
/**
* @author <a href="mailto:tosmers@uni-bremen.de>Tobias Osmers<\a>
* @version created the 12/12/17
*/
public class TaskDependencyMarshaller extends
AbstractMarshaller<TaskDependency> {
}