/*
GanttProject is an opensource project management tool. License: GPL3
Copyright (C) 2010 Dmitry Barashev
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 biz.ganttproject.impex.msproject2;
import biz.ganttproject.core.calendar.CalendarEvent;
import biz.ganttproject.core.calendar.GPCalendar.DayType;
import biz.ganttproject.core.calendar.GPCalendarCalc;
import biz.ganttproject.core.calendar.GanttDaysOff;
import biz.ganttproject.core.calendar.walker.WorkingUnitCounter;
import biz.ganttproject.core.table.ColumnList;
import biz.ganttproject.core.time.CalendarFactory;
import biz.ganttproject.core.time.TimeDuration;
import biz.ganttproject.core.time.impl.GPTimeUnitStack;
import biz.ganttproject.core.time.impl.GregorianTimeUnitStack;
import com.beust.jcommander.internal.Maps;
import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import net.sf.mpxj.*;
import net.sf.mpxj.mpp.MPPReader;
import net.sf.mpxj.mpx.MPXReader;
import net.sf.mpxj.mspdi.MSPDIReader;
import net.sf.mpxj.reader.ProjectReader;
import net.sourceforge.ganttproject.*;
import net.sourceforge.ganttproject.gui.TaskTreeUIFacade;
import net.sourceforge.ganttproject.resource.HumanResource;
import net.sourceforge.ganttproject.task.CustomColumnsException;
import net.sourceforge.ganttproject.task.Task.Priority;
import net.sourceforge.ganttproject.task.TaskManager;
import net.sourceforge.ganttproject.task.TaskManager.TaskBuilder;
import net.sourceforge.ganttproject.task.dependency.TaskDependency;
import net.sourceforge.ganttproject.task.dependency.TaskDependencyConstraint;
import net.sourceforge.ganttproject.task.dependency.TaskDependencyException;
import net.sourceforge.ganttproject.task.dependency.constraint.FinishFinishConstraintImpl;
import net.sourceforge.ganttproject.task.dependency.constraint.FinishStartConstraintImpl;
import net.sourceforge.ganttproject.task.dependency.constraint.StartFinishConstraintImpl;
import net.sourceforge.ganttproject.task.dependency.constraint.StartStartConstraintImpl;
import net.sourceforge.ganttproject.util.collect.Pair;
import javax.xml.transform.*;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import java.io.*;
import java.math.BigDecimal;
import java.text.MessageFormat;
import java.util.*;
import java.util.logging.Level;
import java.util.regex.Pattern;
class ProjectFileImporter {
private final IGanttProject myNativeProject;
private final ProjectReader myReader;
private final File myForeignFile;
private Map<ResourceField, CustomPropertyDefinition> myResourceCustomPropertyMapping;
private Map<TaskField, CustomPropertyDefinition> myTaskCustomPropertyMapping;
private Map<String, Object> myCustomPropertyUniqueValueMapping = new HashMap<String, Object>();
private ColumnList myTaskFields;
private List<Pair<Level, String>> myErrors = Lists.newArrayList();
private ProjectFile myProjectFile;
private Map<GanttTask, Date> myNativeTask2foreignStart;
private static ProjectReader createReader(File file) {
int lastDot = file.getName().lastIndexOf('.');
if (lastDot == file.getName().length() - 1) {
return null;
}
String fileExt = file.getName().substring(lastDot + 1).toLowerCase();
if ("mpp".equals(fileExt)) {
return new MPPReader();
} else if ("xml".equals(fileExt)) {
return new MSPDIReader();
} else if ("mpx".equals(fileExt)) {
return new MPXReader();
}
return null;
}
private static interface HolidayAdder {
void addHoliday(Date date);
}
public ProjectFileImporter(IGanttProject nativeProject, TaskTreeUIFacade taskTreeUIFacade, File foreignProjectFile) {
myNativeProject = nativeProject;
myTaskFields = taskTreeUIFacade.getVisibleFields();
myReader = ProjectFileImporter.createReader(foreignProjectFile);
myForeignFile = foreignProjectFile;
}
private TaskManager getTaskManager() {
return myNativeProject.getTaskManager();
}
private static InputStream createPatchedStream(final File inputFile) throws TransformerConfigurationException,
TransformerFactoryConfigurationError, IOException {
final Transformer transformer = SAXTransformerFactory.newInstance().newTransformer(
new StreamSource(ProjectFileImporter.class.getResourceAsStream("/mspdi_fix.xsl")));
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
ByteArrayOutputStream transformationOut = new ByteArrayOutputStream();
try {
transformer.transform(new StreamSource(inputFile), new StreamResult(transformationOut));
} catch (TransformerException e) {
GPLogger.log(new RuntimeException("Failed to transform file=" + inputFile.getAbsolutePath(), e));
}
return new ByteArrayInputStream(transformationOut.toByteArray());
}
@SuppressWarnings("unused")
private List<String> debugTransformation() throws MPXJException {
try {
BufferedReader is = new BufferedReader(new InputStreamReader(createPatchedStream(myForeignFile)));
for (String s = is.readLine(); s != null; s = is.readLine()) {
System.out.println(s);
}
} catch (Throwable e) {
e.printStackTrace();
}
return Collections.emptyList();
}
public void run() throws MPXJException {
ProjectFile pf;
try {
pf = (myReader instanceof MSPDIReader) ? myReader.read(createPatchedStream(myForeignFile))
: myReader.read(myForeignFile);
} catch (TransformerConfigurationException e) {
throw new MPXJException("Failed to read input file=" + myForeignFile.getAbsolutePath() + "<br>" + e.getMessage(),
e);
} catch (TransformerFactoryConfigurationError e) {
throw new MPXJException("Failed to create a transformer factory");
} catch (IOException e) {
throw new MPXJException("Failed to read input file=" + myForeignFile.getAbsolutePath(), e);
} catch (RuntimeException e) {
throw new MPXJException("Failed to read input file=" + myForeignFile.getAbsolutePath(), e);
}
myProjectFile = pf;
Map<Integer, GanttTask> foreignId2nativeTask = new HashMap<Integer, GanttTask>();
myNativeTask2foreignStart = Maps.newHashMap();
Map<Integer, HumanResource> foreignId2nativeResource = new HashMap<Integer, HumanResource>();
importCalendar(pf);
importResources(pf, foreignId2nativeResource);
importTasks(pf, foreignId2nativeTask, myNativeTask2foreignStart);
hideCustomProperties();
importDependencies(pf, foreignId2nativeTask);
List<net.sourceforge.ganttproject.task.Task> leafTasks = Lists.newArrayList();
for (GanttTask task : foreignId2nativeTask.values()) {
if (!getTaskManager().getTaskHierarchy().hasNestedTasks(task)) {
leafTasks.add(task);
}
}
myNativeProject.getTaskManager().getAlgorithmCollection().getAdjustTaskBoundsAlgorithm().run(leafTasks);
importResourceAssignments(pf, foreignId2nativeTask, foreignId2nativeResource);
}
List<Pair<Level, String>> getErrors() {
return myErrors;
}
Map<GanttTask, Date> getOriginalStartDates() {
return myNativeTask2foreignStart;
}
private void hideCustomProperties() {
for (Map.Entry<String, Object> it : myCustomPropertyUniqueValueMapping.entrySet()) {
if (it.getValue() != null) {
hideCustomColumn(it.getKey());
}
}
}
private void hideCustomColumn(String key) {
for (int i = 0; i < myTaskFields.getSize(); i++) {
if (key.equals(myTaskFields.getField(i).getName())) {
myTaskFields.getField(i).setVisible(false);
}
}
}
private void importCalendar(ProjectFile pf) {
ProjectCalendar defaultCalendar = pf.getDefaultCalendar();
if (defaultCalendar == null) {
return;
}
importWeekends(defaultCalendar);
List<ProjectCalendarException> exceptions = defaultCalendar.getCalendarExceptions();
for (ProjectCalendarException e : exceptions) {
if (!e.getWorking()) {
final List<CalendarEvent> holidays = Lists.newArrayList();
importHolidays(e, new HolidayAdder() {
@Override
public void addHoliday(Date date) {
holidays.add(CalendarEvent.newEvent(date, false, CalendarEvent.Type.HOLIDAY, null, null));
}
});
getNativeCalendar().setPublicHolidays(holidays);
}
}
}
private void importWeekends(ProjectCalendar calendar) {
importDayType(calendar, Day.MONDAY, Calendar.MONDAY);
importDayType(calendar, Day.TUESDAY, Calendar.TUESDAY);
importDayType(calendar, Day.WEDNESDAY, Calendar.WEDNESDAY);
importDayType(calendar, Day.THURSDAY, Calendar.THURSDAY);
importDayType(calendar, Day.FRIDAY, Calendar.FRIDAY);
importDayType(calendar, Day.SATURDAY, Calendar.SATURDAY);
importDayType(calendar, Day.SUNDAY, Calendar.SUNDAY);
}
private void importDayType(ProjectCalendar foreignCalendar, Day foreignDay, int nativeDay) {
getNativeCalendar().setWeekDayType(nativeDay,
foreignCalendar.isWorkingDay(foreignDay) ? DayType.WORKING : DayType.WEEKEND);
}
private GPCalendarCalc getNativeCalendar() {
return myNativeProject.getActiveCalendar();
}
private void importHolidays(ProjectCalendarException e, HolidayAdder adder) {
if (e.getRangeCount() > 0) {
for (DateRange range : e) {
importHolidays(range.getStart(), range.getEnd(), adder);
}
} else {
importHolidays(e.getFromDate(), e.getToDate(), adder);
}
}
private void importHolidays(Date start, Date end, HolidayAdder adder) {
TimeDuration oneDay = getTaskManager().createLength(GregorianTimeUnitStack.DAY, 1.0f);
for (Date dayStart = start; !dayStart.after(end);) {
// myNativeProject.getActiveCalendar().setPublicHoliDayType(dayStart);
adder.addHoliday(dayStart);
dayStart = GPCalendarCalc.PLAIN.shiftDate(dayStart, oneDay);
}
}
private void importResources(ProjectFile pf, Map<Integer, HumanResource> foreignId2humanResource) {
myResourceCustomPropertyMapping = new HashMap<ResourceField, CustomPropertyDefinition>();
for (Resource r : pf.getAllResources()) {
HumanResource nativeResource = myNativeProject.getHumanResourceManager().newHumanResource();
nativeResource.setId(r.getUniqueID());
nativeResource.setName(r.getName());
nativeResource.setMail(r.getEmailAddress());
Rate standardRate = r.getStandardRate();
if (standardRate != null && standardRate.getAmount() != 0.0 && r.getStandardRateUnits() == TimeUnit.DAYS) {
nativeResource.setStandardPayRate(new BigDecimal(standardRate.getAmount()));
}
myNativeProject.getHumanResourceManager().add(nativeResource);
importDaysOff(r, nativeResource);
importCustomProperties(r, nativeResource);
foreignId2humanResource.put(r.getUniqueID(), nativeResource);
}
}
private void importCustomProperties(Resource r, HumanResource nativeResource) {
for (ResourceField rf : ResourceField.values()) {
if (r.getCurrentValue(rf) == null || !isCustomField(rf)) {
continue;
}
CustomPropertyDefinition def = myResourceCustomPropertyMapping.get(rf);
if (def == null) {
String typeAsString = convertDataType(rf);
String name = r.getParentFile().getCustomFields().getCustomField(rf).getAlias();
if (name == null) {
name = rf.getName();
}
def = myNativeProject.getResourceCustomPropertyManager().createDefinition(typeAsString, name, null);
def.getAttributes().put(CustomPropertyMapping.MSPROJECT_TYPE, rf.name());
myResourceCustomPropertyMapping.put(rf, def);
}
nativeResource.setCustomField(def, convertDataValue(rf, r.getCurrentValue(rf)));
}
}
private void importDaysOff(Resource r, final HumanResource nativeResource) {
ProjectCalendar c = r.getResourceCalendar();
if (c == null) {
return;
}
for (ProjectCalendarException e : c.getCalendarExceptions()) {
importHolidays(e, new HolidayAdder() {
@Override
public void addHoliday(Date date) {
nativeResource.addDaysOff(new GanttDaysOff(date, GregorianTimeUnitStack.DAY.adjustRight(date)));
}
});
}
}
private void importTasks(ProjectFile foreignProject, Map<Integer, GanttTask> foreignId2nativeTask, Map<GanttTask, Date> nativeTask2foreignStart) {
myTaskCustomPropertyMapping = new HashMap<TaskField, CustomPropertyDefinition>();
for (Task t : foreignProject.getChildTasks()) {
importTask(foreignProject, t, getTaskManager().getRootTask(), foreignId2nativeTask, nativeTask2foreignStart);
}
}
private Function<Task, Pair<TimeDuration, TimeDuration>> findDurationFunction(Task t, StringBuilder reportBuilder) {
if (t.getStart() != null && t.getFinish() != null) {
return DURATION_FROM_START_FINISH;
}
reportBuilder.append("start+finish not found");
if (t.getStart() != null && t.getDuration() != null) {
return DURATION_FROM_START_AND_DURATION;
}
reportBuilder.append(", start+duration not found");
return null;
}
private void importTask(ProjectFile foreignProject, Task t, net.sourceforge.ganttproject.task.Task supertask,
Map<Integer, GanttTask> foreignId2nativeTask, Map<GanttTask, Date> nativeTask2foreignStart) {
if (t.getNull()) {
myErrors.add(Pair.create(Level.INFO,
MessageFormat.format("Task with id={0} is blank task. Skipped", foreignId(t))));
return;
}
if (t.getUniqueID() == 0) {
boolean isRealTask = t.getName() != null && !t.getChildTasks().isEmpty();
if (!isRealTask) {
for (Task child : t.getChildTasks()) {
importTask(foreignProject, child, getTaskManager().getRootTask(), foreignId2nativeTask, nativeTask2foreignStart);
}
return;
}
}
StringBuilder report = new StringBuilder();
Function<Task, Pair<TimeDuration, TimeDuration>> getDuration = findDurationFunction(t, report);
if (getDuration == null) {
myErrors.add(Pair.create(Level.SEVERE,
String.format("Can't determine the duration of task %s (%s). Skipped", t, report)));
return;
}
TaskBuilder taskBuilder = getTaskManager().newTaskBuilder()
.withParent(supertask)
.withName(t.getName())
.withNotes(t.getNotes())
.withWebLink(t.getHyperlink());
if (t.getPriority() != null) {
taskBuilder = taskBuilder.withPriority(convertPriority(t.getPriority()));
}
Date foreignStartDate = convertStartTime(t.getStart());
if (t.getChildTasks().isEmpty()) {
taskBuilder.withStartDate(foreignStartDate);
if (t.getPercentageComplete() != null) {
taskBuilder.withCompletion(t.getPercentageComplete().intValue());
}
if (t.getMilestone()) {
taskBuilder.withLegacyMilestone();
}
Pair<TimeDuration, TimeDuration> durations = getDuration.apply(t);
TimeDuration workingDuration = durations.first();
TimeDuration nonWorkingDuration = durations.second();
TimeDuration defaultDuration = myNativeProject.getTaskManager().createLength(
myNativeProject.getTimeUnitStack().getDefaultTimeUnit(), 1.0f);
if (!t.getMilestone()) {
if (workingDuration.getLength() > 0) {
taskBuilder.withDuration(workingDuration);
} else if (nonWorkingDuration.getLength() > 0) {
myErrors.add(Pair.create(Level.INFO, MessageFormat.format(
"[FYI] Task with id={0}, name={1}, start date={2}, end date={3}, milestone={4} has working time={5} and non working time={6}.\n"
+ "We set its duration to {6}", foreignId(t), t.getName(), t.getStart(), t.getFinish(),
t.getMilestone(), workingDuration, nonWorkingDuration)));
taskBuilder.withDuration(nonWorkingDuration);
} else {
myErrors.add(Pair.create(Level.INFO, MessageFormat.format(
"[FYI] Task with id={0}, name={1}, start date={2}, end date={3}, milestone={4} has working time={5} and non working time={6}.\n"
+ "We set its duration to default={7}", foreignId(t), t.getName(), t.getStart(), t.getFinish(),
t.getMilestone(), workingDuration, nonWorkingDuration, defaultDuration)));
taskBuilder.withDuration(defaultDuration);
}
} else {
taskBuilder.withDuration(defaultDuration);
}
}
GanttTask nativeTask = (GanttTask) taskBuilder.build();
if (t.getCost() != null) {
nativeTask.getCost().setCalculated(false);
nativeTask.getCost().setValue(BigDecimal.valueOf(t.getCost().doubleValue()));
}
if (!t.getChildTasks().isEmpty()) {
for (Task child : t.getChildTasks()) {
importTask(foreignProject, child, nativeTask, foreignId2nativeTask, nativeTask2foreignStart);
}
}
importCustomFields(t, nativeTask);
foreignId2nativeTask.put(foreignId(t), nativeTask);
nativeTask2foreignStart.put(nativeTask, foreignStartDate);
}
private Date convertStartTime(Date start) {
return myNativeProject.getTimeUnitStack().getDefaultTimeUnit().adjustLeft(start);
}
private void importCustomFields(Task t, GanttTask nativeTask) {
for (TaskField tf : TaskField.values()) {
if (!isCustomField(tf) || t.getCurrentValue(tf) == null) {
continue;
}
CustomPropertyDefinition def = myTaskCustomPropertyMapping.get(tf);
if (def == null) {
String typeAsString = convertDataType(tf);
String name = t.getParentFile().getCustomFields().getCustomField(tf).getAlias();
if (name == null) {
name = tf.getName();
}
def = myNativeProject.getTaskCustomColumnManager().createDefinition(typeAsString, name, null);
def.getAttributes().put(CustomPropertyMapping.MSPROJECT_TYPE, tf.name());
myTaskCustomPropertyMapping.put(tf, def);
}
try {
Object value = convertDataValue(tf, t.getCurrentValue(tf));
if (!myCustomPropertyUniqueValueMapping.containsKey(def.getName())) {
myCustomPropertyUniqueValueMapping.put(def.getName(), value);
} else {
if (!value.equals(myCustomPropertyUniqueValueMapping.get(def.getName()))) {
myCustomPropertyUniqueValueMapping.put(def.getName(), null);
}
}
nativeTask.getCustomValues().setValue(def, value);
} catch (CustomColumnsException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private static Pattern CUSTOM_FIELD_NAME = Pattern.compile("^\\p{Lower}+\\p{Digit}+$");
private boolean isCustomField(FieldType tf) {
return tf != null && tf.getName() != null
&& ProjectFileImporter.CUSTOM_FIELD_NAME.matcher(tf.getName().toLowerCase()).matches();
}
private String convertDataType(FieldType tf) {
switch (tf.getDataType()) {
case ACCRUE:
case CONSTRAINT:
case DURATION:
case PRIORITY:
case RELATION_LIST:
case RESOURCE_TYPE:
case STRING:
case TASK_TYPE:
case UNITS:
return CustomPropertyClass.TEXT.name().toLowerCase();
case BOOLEAN:
return CustomPropertyClass.BOOLEAN.name().toLowerCase();
case DATE:
return CustomPropertyClass.DATE.name().toLowerCase();
case CURRENCY:
case NUMERIC:
case PERCENTAGE:
case RATE:
return CustomPropertyClass.DOUBLE.name().toLowerCase();
}
return null;
}
private Object convertDataValue(FieldType tf, Object value) {
switch (tf.getDataType()) {
case ACCRUE:
case CONSTRAINT:
case DURATION:
case PRIORITY:
case RELATION_LIST:
case RESOURCE_TYPE:
case STRING:
case TASK_TYPE:
case UNITS:
return String.valueOf(value);
case BOOLEAN:
assert value instanceof Boolean;
return value;
case DATE:
assert value instanceof Date;
return CalendarFactory.createGanttCalendar((Date) value);
case CURRENCY:
case NUMERIC:
case PERCENTAGE:
assert value instanceof Number;
return ((Number) value).doubleValue();
case RATE:
assert value instanceof Rate;
return ((Rate) value).getAmount();
}
return null;
}
private Priority convertPriority(net.sf.mpxj.Priority priority) {
switch (priority.getValue()) {
case net.sf.mpxj.Priority.HIGHEST:
case net.sf.mpxj.Priority.VERY_HIGH:
return Priority.HIGHEST;
case net.sf.mpxj.Priority.HIGHER:
case net.sf.mpxj.Priority.HIGH:
return Priority.HIGH;
case net.sf.mpxj.Priority.MEDIUM:
return Priority.NORMAL;
case net.sf.mpxj.Priority.LOWER:
case net.sf.mpxj.Priority.LOW:
return Priority.LOW;
case net.sf.mpxj.Priority.VERY_LOW:
case net.sf.mpxj.Priority.LOWEST:
return Priority.LOWEST;
default:
return Priority.NORMAL;
}
}
private Pair<TimeDuration, TimeDuration> getDurations(Date start, Date end) {
WorkingUnitCounter unitCounter = new WorkingUnitCounter(getNativeCalendar(),
myNativeProject.getTimeUnitStack().getDefaultTimeUnit());
TimeDuration workingDuration = unitCounter.run(start, end);
TimeDuration nonWorkingDuration = unitCounter.getNonWorkingTime();
return Pair.create(workingDuration, nonWorkingDuration);
}
private final Function<Task, Pair<TimeDuration, TimeDuration>> DURATION_FROM_START_FINISH =
new Function<Task, Pair<TimeDuration,TimeDuration>>() {
@Override
public Pair<TimeDuration, TimeDuration> apply(Task t) {
if (t.getMilestone()) {
return Pair.create(getTaskManager().createLength(1), null);
}
return getDurations(t.getStart(), myNativeProject.getTimeUnitStack().getDefaultTimeUnit().adjustRight(t.getFinish()));
}
};
private final Function<Task, Pair<TimeDuration, TimeDuration>> DURATION_FROM_START_AND_DURATION =
new Function<Task, Pair<TimeDuration,TimeDuration>>() {
@Override
public Pair<TimeDuration, TimeDuration> apply(Task t) {
if (t.getMilestone()) {
return Pair.create(getTaskManager().createLength(1), null);
}
Duration dayUnits = t.getDuration().convertUnits(TimeUnit.DAYS, myProjectFile.getProjectProperties());
TimeDuration gpDuration = getTaskManager().createLength(GPTimeUnitStack.DAY, (float) dayUnits.getDuration());
Date endDate = getTaskManager().shift(t.getStart(), gpDuration);
return getDurations(t.getStart(), endDate);
}
};
private static Integer foreignId(Task mpxjTask) {
Integer result = mpxjTask.getID();
if (result != null) {
return result;
}
result = mpxjTask.getUniqueID();
if (result != null) {
return result;
}
throw new IllegalStateException("No ID found in task=" + mpxjTask);
}
private void importDependencies(ProjectFile pf, Map<Integer, GanttTask> foreignId2nativeTask) {
for (Task t : pf.getAllTasks()) {
if (t.getPredecessors() == null) {
continue;
}
for (Relation r : t.getPredecessors()) {
GanttTask dependant = foreignId2nativeTask.get(foreignId(r.getSourceTask()));
GanttTask dependee = foreignId2nativeTask.get(foreignId(r.getTargetTask()));
if (dependant == null) {
myErrors.add(Pair.create(Level.SEVERE, String.format(
"Failed to import relation=%s because source task=%s was not found", r, foreignId(r.getSourceTask()))));
continue;
}
if (dependee == null) {
myErrors.add(Pair.create(Level.SEVERE, String.format(
"Failed to import relation=%s because target task=%s", t, foreignId(r.getTargetTask()))));
continue;
}
try {
TaskDependency dependency = getTaskManager().getDependencyCollection().createDependency(dependant, dependee);
dependency.setConstraint(convertConstraint(r));
if (r.getLag().getDuration() != 0.0) {
// TODO(dbarashev): get rid of days
dependency.setDifference((int) r.getLag().convertUnits(TimeUnit.DAYS, pf.getProjectProperties()).getDuration());
}
dependency.setHardness(TaskDependency.Hardness.parse(getTaskManager().getDependencyHardnessOption().getValue()));
} catch (TaskDependencyException e) {
GPLogger.getLogger("MSProject").log(Level.SEVERE, "Failed to import relation=" + r, e);
myErrors.add(Pair.create(Level.SEVERE, String.format("Failed to import relation=%s: %s", r, e.getMessage())));
}
}
}
}
private TaskDependencyConstraint convertConstraint(Relation r) {
switch (r.getType()) {
case FINISH_FINISH:
return new FinishFinishConstraintImpl();
case FINISH_START:
return new FinishStartConstraintImpl();
case START_FINISH:
return new StartFinishConstraintImpl();
case START_START:
return new StartStartConstraintImpl();
default:
throw new IllegalStateException("Uknown relation type=" + r.getType());
}
}
private void importResourceAssignments(ProjectFile pf, Map<Integer, GanttTask> foreignId2nativeTask,
Map<Integer, HumanResource> foreignId2nativeResource) {
for (ResourceAssignment ra : pf.getAllResourceAssignments()) {
GanttTask nativeTask = foreignId2nativeTask.get(foreignId(ra.getTask()));
if (nativeTask == null) {
myErrors.add(Pair.create(Level.SEVERE, String.format(
"Failed to import resource assignment=%s because its task with ID=%d and name=%s was not found or not imported", ra, foreignId(ra.getTask()), ra.getTask().getName())));
continue;
}
Resource resource = ra.getResource();
if (resource == null) {
continue;
}
HumanResource nativeResource = foreignId2nativeResource.get(resource.getUniqueID());
if (nativeResource == null) {
myErrors.add(Pair.create(Level.SEVERE, String.format(
"Failed to import resource assignment=%s because its resource with ID=%d and name=%s was not found or not imported", ra, resource.getUniqueID(), resource.getName())));
continue;
}
net.sourceforge.ganttproject.task.ResourceAssignment nativeAssignment = nativeTask.getAssignmentCollection().addAssignment(
nativeResource);
Preconditions.checkNotNull(nativeAssignment);
if (ra.getUnits() == null) {
myErrors.add(Pair.create(Level.INFO, String.format(
"Units not found in resource assignment=%s. Replaced with 100", ra)));
nativeAssignment.setLoad(100f);
} else {
nativeAssignment.setLoad(ra.getUnits().floatValue());
}
}
}
}