/*
* file: GanttMPXJSaver.java
* author: Jon Iles
* copyright: (c) Tapster Rock Limited 2005
* date: 04/02/2005
*/
/*
* 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.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
package org.ganttproject.impex.msproject;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import net.sourceforge.ganttproject.GanttResourcePanel;
import net.sourceforge.ganttproject.GanttTask;
import net.sourceforge.ganttproject.GanttTaskRelationship;
import net.sourceforge.ganttproject.IGanttProject;
import net.sourceforge.ganttproject.resource.HumanResource;
import net.sourceforge.ganttproject.resource.HumanResourceManager;
import net.sourceforge.ganttproject.task.ResourceAssignment;
import net.sourceforge.ganttproject.task.Task;
import net.sourceforge.ganttproject.task.TaskManager;
import net.sourceforge.ganttproject.task.dependency.TaskDependency;
import net.sourceforge.ganttproject.task.dependency.TaskDependencyConstraint;
import com.tapsterrock.mpx.ConstraintType;
import com.tapsterrock.mpx.MPXDuration;
import com.tapsterrock.mpx.MPXFile;
import com.tapsterrock.mpx.ProjectHeader;
import com.tapsterrock.mpx.Relation;
import com.tapsterrock.mpx.RelationType;
import com.tapsterrock.mpx.Resource;
import com.tapsterrock.mpx.TimeUnit;
/**
* This class implements the mechanism used to export Microsoft Project data
* from the GanttProject application using MPXJ.
*/
public class GanttMPXJSaver {
private HumanResourceManager myHrManager;
private TaskManager myTaskManager;
/**
* Constructor.
*
* @param project
* current project
* @param tree
* current task tree
* @param resources
* current resources
*/
protected GanttMPXJSaver(IGanttProject project) {
myHrManager = (HumanResourceManager) project.getHumanResourceManager();
myTaskManager = project.getTaskManager();
m_project = project;
}
/**
* Process resource data.
*/
private void processResources() {
try {
List resources = myHrManager.getResources();
HumanResource ganttResource;
Resource mpxResource;
for (int i = 0; i < resources.size(); i++) {
ganttResource = (HumanResource) resources.get(i);
mpxResource = m_mpx.addResource();
mpxResource.setName(ganttResource.getName());
mpxResource.setEmailAddress(ganttResource.getMail());
m_ganttMpxResourceMap.put(new Integer(ganttResource.getId()),
mpxResource.getUniqueID());
}
}
catch (Exception ex) {
System.out.println(ex);
}
}
/**
* Process task data.
*/
private void processTasks() {
// Enumeration children =
// ((DefaultMutableTreeNode)m_tree.getJTree().getModel().getRoot()).children();
Task[] children = myTaskManager.getTaskHierarchy().getNestedTasks(
myTaskManager.getTaskHierarchy().getRootTask());
for (int i = 0; i < children.length; i++) {
processTask(children[i], null);
}
}
/**
* This method is called recursively to process a single task and any child
* tasks.
*
* @param node
* Gantt task
* @param parent
* parent MPXJ task
*/
private void processTask(Task ganttTask, com.tapsterrock.mpx.Task parent) {
try {
//
// Process the current task
//
int percentageComplete = ganttTask.getCompletionPercentage();
boolean milestone = ganttTask.isMilestone();
long taskLength = milestone == false ? ganttTask.getDuration()
.getLength() : 0;
com.tapsterrock.mpx.Task mpxTask = parent == null ? m_mpx.addTask()
: parent.addTask();
mpxTask.setName(ganttTask.getName());
mpxTask.setMilestone(ganttTask.isMilestone());
mpxTask.setStart(ganttTask.getStart().getTime());
mpxTask.setConstraintDate(ganttTask.getStart().getTime());
mpxTask.setConstraintType(ConstraintType.MUST_START_ON);
mpxTask.setDuration(MPXDuration.getInstance(taskLength, TimeUnit.DAYS));
mpxTask.setPercentageComplete(percentageComplete);
mpxTask.setHyperlink(((GanttTask) ganttTask).getWebLink());
mpxTask.setNotes(ganttTask.getNotes());
if (percentageComplete != 0) {
mpxTask.setActualStart(mpxTask.getStart());
}
m_ganttMpxTaskMap.put(new Integer(ganttTask.getTaskID()), mpxTask
.getUniqueID());
//
// Process any child tasks
//
Task[] children = myTaskManager.getTaskHierarchy().getNestedTasks(
ganttTask);
for (int i = 0; i < children.length; i++) {
processTask(children[i], mpxTask);
}
}
catch (Exception e) {
System.out.println(e);
}
}
/**
* Process relationships.
*/
private void processRelationships() {
Task[] children = myTaskManager.getTaskHierarchy().getNestedTasks(
myTaskManager.getTaskHierarchy().getRootTask());
for (int i = 0; i < children.length; i++) {
processRelationships(children[i]);
}
}
/**
* Recursively process the relationships between tasks.
*
* @param element
* current task
*/
private void processRelationships(Task ganttTask) {
// Vector relationships = ganttTask.getPredecessorsOld();
TaskDependency[] dependencies = ganttTask.getDependencies().toArray();
TaskDependency relationship;
com.tapsterrock.mpx.Task mpxSuccessorTask;
com.tapsterrock.mpx.Task mpxPredecessorTask;
Integer mpxSuccessorTaskID;
Integer mpxPredecessorTaskID;
Relation mpxRelation;
for (int loop = 0; loop < dependencies.length; loop++) {
relationship = dependencies[loop];
mpxSuccessorTaskID = (Integer) m_ganttMpxTaskMap.get(new Integer(
relationship.getDependant().getTaskID()));
mpxPredecessorTaskID = (Integer) m_ganttMpxTaskMap.get(new Integer(
relationship.getDependee().getTaskID()));
if (mpxSuccessorTaskID != null && mpxPredecessorTaskID != null) {
mpxSuccessorTask = m_mpx.getTaskByUniqueID(mpxSuccessorTaskID
.intValue());
mpxPredecessorTask = m_mpx
.getTaskByUniqueID(mpxPredecessorTaskID.intValue());
mpxRelation = mpxSuccessorTask
.addPredecessor(mpxPredecessorTask);
TaskDependencyConstraint constraint = relationship
.getConstraint();
switch (constraint.getID()) {
case GanttTaskRelationship.SS: {
mpxRelation.setType(RelationType.START_START);
break;
}
case GanttTaskRelationship.SF: {
mpxRelation.setType(RelationType.START_FINISH);
break;
}
case GanttTaskRelationship.FS: {
mpxRelation.setType(RelationType.FINISH_START);
break;
}
case GanttTaskRelationship.FF: {
mpxRelation.setType(RelationType.FINISH_FINISH);
break;
}
}
}
}
Task[] children = myTaskManager.getTaskHierarchy().getNestedTasks(
ganttTask);
for (int i = 0; i < children.length; i++) {
processRelationships(children[i]);
}
}
/**
* Process resource assignments.
*/
private void processAssignments() {
Task[] children = myTaskManager.getTaskHierarchy().getNestedTasks(
myTaskManager.getTaskHierarchy().getRootTask());
for (int i = 0; i < children.length; i++) {
processAssignments(children[i]);
}
}
/**
* Recursively process resource assignments.
*
* @param node
* current task
*/
private void processAssignments(Task ganttTask) {
try {
//
// Process the current task
//
ResourceAssignment[] assignments = ganttTask.getAssignments();
for (int loop = 0; loop < assignments.length; loop++) {
processAssignment(ganttTask, assignments[loop]);
}
//
// Process any child tasks
//
Task[] children = myTaskManager.getTaskHierarchy().getNestedTasks(
ganttTask);
for (int i = 0; i < children.length; i++) {
processAssignments(children[i]);
}
}
catch (Exception e) {
System.out.println(e);
}
}
/**
* Process a single resource assignment.
*
* @param ganttTask
* parent task
* @param ganttAssignment
* resource assignment
* @throws Exception
*/
private void processAssignment(Task ganttTask,
ResourceAssignment ganttAssignment) throws Exception {
Integer mpxTaskID = (Integer) m_ganttMpxTaskMap.get(new Integer(
ganttTask.getTaskID()));
Integer mpxResourceID = (Integer) m_ganttMpxResourceMap
.get(new Integer(ganttAssignment.getResource().getId()));
if (mpxTaskID != null && mpxResourceID != null) {
com.tapsterrock.mpx.Task mpxTask = m_mpx
.getTaskByUniqueID(mpxTaskID.intValue());
com.tapsterrock.mpx.Resource mpxResource = m_mpx
.getResourceByUniqueID(mpxResourceID.intValue());
MPXDuration taskWork = mpxTask.getDuration();
MPXDuration resourceWork = MPXDuration.getInstance(
(taskWork.getDuration() * ganttAssignment.getLoad()) / 100,
taskWork.getUnits());
MPXDuration resourceActualWork = MPXDuration.getInstance(
(resourceWork.getDuration() * mpxTask
.getPercentageCompleteValue()) / 100, resourceWork
.getUnits());
com.tapsterrock.mpx.ResourceAssignment mpxResourceAssignment = mpxTask
.addResourceAssignment(mpxResource);
mpxResourceAssignment.setUnits(ganttAssignment.getLoad());
mpxResourceAssignment.setWork(resourceWork);
mpxResourceAssignment.setActualWork(resourceActualWork);
}
}
/**
* Main method called to save Gantt Project data in a Microsoft Project file
* format.
*
* @param file
* output file
* @param mpx
* MPXJ file instance
*/
protected void save(File file, MPXFile mpx) throws Exception {
m_mpx = mpx;
m_mpx.setAutoCalendarUniqueID(true);
m_mpx.setAutoOutlineLevel(true);
m_mpx.setAutoOutlineNumber(true);
m_mpx.setAutoResourceID(true);
m_mpx.setAutoResourceUniqueID(true);
m_mpx.setAutoTaskID(true);
m_mpx.setAutoTaskUniqueID(true);
m_mpx.setAutoWBS(true);
m_mpx.addDefaultBaseCalendar();
ProjectHeader header = m_mpx.getProjectHeader();
header.setProjectTitle(m_project.getProjectName());
header.setCompany(m_project.getOrganization());
header.setComments(m_project.getDescription());
processResources();
processTasks();
processRelationships();
processAssignments();
header.setStartDate(mpx.getStartDate());
mpx.write(file);
}
private final IGanttProject m_project;
// private GanttTree m_tree;
private GanttResourcePanel m_resources;
private MPXFile m_mpx;
private HashMap m_ganttMpxTaskMap = new HashMap();
private HashMap m_ganttMpxResourceMap = new HashMap();
}