/*
GanttProject is an opensource project management tool.
Copyright (C) 2011 GanttProject Team
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, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package net.sourceforge.ganttproject.task;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import net.sourceforge.ganttproject.resource.HumanResource;
import net.sourceforge.ganttproject.resource.HumanResourceManager;
import net.sourceforge.ganttproject.roles.Role;
class ResourceAssignmentCollectionImpl implements ResourceAssignmentCollection {
private final Map<HumanResource, ResourceAssignment> myAssignments = new LinkedHashMap<HumanResource, ResourceAssignment>();
private final TaskImpl myTask;
private HumanResourceManager myResourceManager;
public ResourceAssignmentCollectionImpl(TaskImpl task, HumanResourceManager resourceManager) {
myTask = task;
myResourceManager = resourceManager;
}
private ResourceAssignmentCollectionImpl(ResourceAssignmentCollectionImpl collection) {
myTask = collection.myTask;
ResourceAssignment[] assignments = collection.getAssignments();
for (int i = 0; i < assignments.length; i++) {
ResourceAssignment next = assignments[i];
ResourceAssignment copy = new ResourceAssignmentImpl(next.getResource());
copy.setLoad(next.getLoad());
copy.setCoordinator(next.isCoordinator());
copy.setRoleForAssignment(next.getRoleForAssignment());
addAssignment(copy);
}
}
@Override
public void clear() {
ResourceAssignment[] assignments = getAssignments();
for (int i = 0; i < assignments.length; i++) {
assignments[i].delete();
}
}
@Override
public ResourceAssignment[] getAssignments() {
return myAssignments.values().toArray(new ResourceAssignment[myAssignments.size()]);
}
@Override
public ResourceAssignment getAssignment(HumanResource resource) {
return myAssignments.get(resource);
}
@Override
public ResourceAssignmentMutator createMutator() {
return new ResourceAssignmentMutatorImpl();
}
ResourceAssignmentCollectionImpl copy() {
return new ResourceAssignmentCollectionImpl(this);
}
@Override
public ResourceAssignment addAssignment(HumanResource resource) {
return auxAddAssignment(resource);
}
@Override
public void deleteAssignment(HumanResource resource) {
myAssignments.remove(resource);
}
private ResourceAssignment auxAddAssignment(HumanResource resource) {
final ResourceAssignment result = new ResourceAssignmentImpl(resource);
addAssignment(result);
return result;
}
private void addAssignment(ResourceAssignment assignment) {
myAssignments.put(assignment.getResource(), assignment);
}
/**
* Removes the assignments related to the given resource.
*
* @param resource
* Assigned resource
*/
public void removeAssignment(HumanResource resource) {
new ResourceAssignmentImpl(resource).delete();
}
private Task getTask() {
return myTask;
}
private class ResourceAssignmentImpl implements ResourceAssignment {
private ResourceAssignment myAssignmentToResource;
public ResourceAssignmentImpl(HumanResource resource) {
myAssignmentToResource = resource.createAssignment(this);
// resource.setAssignmentCollection(ResourceAssignmentCollectionImpl.this);
}
@Override
public Task getTask() {
return ResourceAssignmentCollectionImpl.this.getTask();
}
@Override
public HumanResource getResource() {
return myAssignmentToResource.getResource();
}
@Override
public float getLoad() {
return myAssignmentToResource.getLoad();
}
// TODO transaction
@Override
public void setLoad(float load) {
myAssignmentToResource.setLoad(load);
}
/**
* Deletes all the assignments and all the related assignments
*/
@Override
public void delete() {
ResourceAssignmentCollectionImpl.this.deleteAssignment(getResource());
myAssignmentToResource.delete();
}
@Override
public void setCoordinator(boolean responsible) {
myAssignmentToResource.setCoordinator(responsible);
}
@Override
public boolean isCoordinator() {
return myAssignmentToResource.isCoordinator();
}
@Override
public Role getRoleForAssignment() {
return myAssignmentToResource.getRoleForAssignment();
}
@Override
public void setRoleForAssignment(Role role) {
myAssignmentToResource.setRoleForAssignment(role);
}
@Override
public String toString() {
return this.getResource().getName() + " -> " + this.getTask().getName();
}
}
private class ResourceAssignmentStub implements ResourceAssignment {
private final HumanResource myResource;
private float myLoad;
private boolean myCoordinator;
private Role myRoleForAssignment;
public ResourceAssignmentStub(HumanResource resource) {
myResource = resource;
}
@Override
public Task getTask() {
return ResourceAssignmentCollectionImpl.this.getTask();
}
@Override
public HumanResource getResource() {
return myResource;
}
@Override
public float getLoad() {
return myLoad;
}
@Override
public void setLoad(float load) {
myLoad = load;
}
@Override
public void delete() {
}
@Override
public void setCoordinator(boolean responsible) {
myCoordinator = responsible;
}
@Override
public boolean isCoordinator() {
return myCoordinator;
}
@Override
public Role getRoleForAssignment() {
return myRoleForAssignment;
}
@Override
public void setRoleForAssignment(Role role) {
myRoleForAssignment = role;
}
@Override
public String toString() {
return this.getResource().getName() + " -> " + this.getTask().getName();
}
}
private class ResourceAssignmentMutatorImpl implements ResourceAssignmentMutator {
private Map<HumanResource, MutationInfo> myQueue = new HashMap<HumanResource, MutationInfo>();
@Override
public ResourceAssignment addAssignment(HumanResource resource) {
ResourceAssignment result = new ResourceAssignmentStub(resource);
myQueue.put(resource, new MutationInfo(result, MutationInfo.ADD));
return result;
}
@Override
public void deleteAssignment(HumanResource resource) {
MutationInfo info = myQueue.get(resource);
if (info == null) {
myQueue.put(resource, new MutationInfo(resource, MutationInfo.DELETE));
} else if (info.myOperation == MutationInfo.ADD) {
myQueue.remove(resource);
}
}
@Override
public void commit() {
List<MutationInfo> mutations = new ArrayList<MutationInfo>(myQueue.values());
Collections.sort(mutations);
for (int i = 0; i < mutations.size(); i++) {
MutationInfo next = mutations.get(i);
switch (next.myOperation) {
case MutationInfo.DELETE: {
myAssignments.remove(next.myResource);
break;
}
case MutationInfo.ADD: {
ResourceAssignment result = auxAddAssignment(next.myResource);
result.setLoad(next.myAssignment.getLoad());
result.setCoordinator(next.myAssignment.isCoordinator());
result.setRoleForAssignment(next.myAssignment.getRoleForAssignment());
}
default:
break;
}
}
}
}
private static class MutationInfo implements Comparable<MutationInfo> {
static final int ADD = 0;
static final int DELETE = 1;
private final ResourceAssignment myAssignment;
private final int myOrder;
private static int ourOrder;
private int myOperation;
private final HumanResource myResource;
public MutationInfo(ResourceAssignment assignment, int operation) {
myAssignment = assignment;
myOrder = ourOrder++;
myOperation = operation;
myResource = assignment.getResource();
}
public MutationInfo(HumanResource resource, int operation) {
this.myAssignment = null;
this.myOrder = ourOrder++;
this.myOperation = operation;
this.myResource = resource;
}
@Override
public boolean equals(Object o) {
boolean result = o instanceof MutationInfo;
if (result) {
result = myAssignment.getResource().equals(((MutationInfo) o).myAssignment.getResource());
}
return result;
}
@Override
public int compareTo(MutationInfo o) {
if (!(o instanceof MutationInfo)) {
throw new IllegalArgumentException();
}
return myOrder - o.myOrder;
}
}
public void importData(ResourceAssignmentCollection assignmentCollection) {
if (myTask.isUnplugged()) {
ResourceAssignment[] assignments = assignmentCollection.getAssignments();
for (int i = 0; i < assignments.length; i++) {
ResourceAssignment next = assignments[i];
addAssignment(next);
}
} else {
ResourceAssignment[] assignments = assignmentCollection.getAssignments();
for (int i = 0; i < assignments.length; i++) {
ResourceAssignment next = assignments[i];
HumanResource nextResource = next.getResource();
HumanResource nextImportedResource = myResourceManager.getById(nextResource.getId());
if (nextImportedResource != null) {
ResourceAssignment copy = new ResourceAssignmentImpl(nextImportedResource);
copy.setLoad(next.getLoad());
copy.setCoordinator(next.isCoordinator());
copy.setRoleForAssignment(next.getRoleForAssignment());
addAssignment(copy);
}
}
}
}
@Override
public HumanResource getCoordinator() {
for (Iterator<ResourceAssignment> assignments = myAssignments.values().iterator(); assignments.hasNext();) {
ResourceAssignment next = assignments.next();
if (next.isCoordinator()) {
return next.getResource();
}
}
return null;
}
}