/*
* file: PrimaveraPMFileReader.java
* author: Jon Iles
* copyright: (c) Packwood Software 2011
* date: 08/08/2011
*/
/*
* 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 net.sf.mpxj.primavera;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.sax.SAXSource;
import net.sf.mpxj.AssignmentField;
import net.sf.mpxj.ConstraintType;
import net.sf.mpxj.CustomFieldContainer;
import net.sf.mpxj.DateRange;
import net.sf.mpxj.Day;
import net.sf.mpxj.DayType;
import net.sf.mpxj.Duration;
import net.sf.mpxj.EventManager;
import net.sf.mpxj.FieldContainer;
import net.sf.mpxj.FieldType;
import net.sf.mpxj.MPXJException;
import net.sf.mpxj.Priority;
import net.sf.mpxj.ProjectCalendar;
import net.sf.mpxj.ProjectCalendarException;
import net.sf.mpxj.ProjectCalendarHours;
import net.sf.mpxj.ProjectConfig;
import net.sf.mpxj.ProjectFile;
import net.sf.mpxj.ProjectProperties;
import net.sf.mpxj.Relation;
import net.sf.mpxj.RelationType;
import net.sf.mpxj.Resource;
import net.sf.mpxj.ResourceAssignment;
import net.sf.mpxj.Task;
import net.sf.mpxj.TaskField;
import net.sf.mpxj.TimeUnit;
import net.sf.mpxj.common.BooleanHelper;
import net.sf.mpxj.common.DateHelper;
import net.sf.mpxj.common.NumberHelper;
import net.sf.mpxj.listener.ProjectListener;
import net.sf.mpxj.primavera.schema.APIBusinessObjects;
import net.sf.mpxj.primavera.schema.ActivityType;
import net.sf.mpxj.primavera.schema.CalendarType;
import net.sf.mpxj.primavera.schema.CalendarType.HolidayOrExceptions;
import net.sf.mpxj.primavera.schema.CalendarType.HolidayOrExceptions.HolidayOrException;
import net.sf.mpxj.primavera.schema.CalendarType.StandardWorkWeek;
import net.sf.mpxj.primavera.schema.CalendarType.StandardWorkWeek.StandardWorkHours;
import net.sf.mpxj.primavera.schema.CurrencyType;
import net.sf.mpxj.primavera.schema.GlobalPreferencesType;
import net.sf.mpxj.primavera.schema.ProjectType;
import net.sf.mpxj.primavera.schema.RelationshipType;
import net.sf.mpxj.primavera.schema.ResourceAssignmentType;
import net.sf.mpxj.primavera.schema.ResourceType;
import net.sf.mpxj.primavera.schema.WBSType;
import net.sf.mpxj.primavera.schema.WorkTimeType;
import net.sf.mpxj.reader.AbstractProjectReader;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
/**
* This class creates a new ProjectFile instance by reading a Primavera PM file.
*/
public final class PrimaveraPMFileReader extends AbstractProjectReader
{
/**
* {@inheritDoc}
*/
@Override public void addProjectListener(ProjectListener listener)
{
if (m_projectListeners == null)
{
m_projectListeners = new LinkedList<ProjectListener>();
}
m_projectListeners.add(listener);
}
/**
* {@inheritDoc}
*/
@Override public ProjectFile read(InputStream stream) throws MPXJException
{
try
{
//
// This is a hack to ensure that the incoming file has a namespace
// which JAXB will accept.
//
InputStream namespaceCorrectedStream = new ReplaceOnceStream(stream, NAMESPACE_REGEX, NAMESPACE_REPLACEMENT, NAMESPACE_SCOPE, UTF8);
m_projectFile = new ProjectFile();
m_eventManager = m_projectFile.getEventManager();
ProjectConfig config = m_projectFile.getProjectConfig();
config.setAutoTaskUniqueID(false);
config.setAutoResourceUniqueID(false);
config.setAutoCalendarUniqueID(false);
config.setAutoAssignmentUniqueID(false);
CustomFieldContainer fields = m_projectFile.getCustomFields();
fields.getCustomField(TaskField.TEXT1).setAlias("WBS Code");
fields.getCustomField(TaskField.TEXT2).setAlias("Task ID");
m_eventManager.addProjectListeners(m_projectListeners);
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
factory.setNamespaceAware(true);
SAXParser saxParser = factory.newSAXParser();
XMLReader xmlReader = saxParser.getXMLReader();
SAXSource doc = new SAXSource(xmlReader, new InputSource(namespaceCorrectedStream));
if (CONTEXT == null)
{
throw CONTEXT_EXCEPTION;
}
Unmarshaller unmarshaller = CONTEXT.createUnmarshaller();
APIBusinessObjects apibo = (APIBusinessObjects) unmarshaller.unmarshal(doc);
List<ProjectType> projects = apibo.getProject();
ProjectType project = null;
for (ProjectType currentProject : projects)
{
if (!BooleanHelper.getBoolean(currentProject.isExternal()))
{
project = currentProject;
break;
}
}
if (project == null)
{
throw new MPXJException("Unable to locate any non-external projects in a list of " + projects.size() + " projects");
}
processProjectProperties(apibo, project);
processCalendars(apibo);
processResources(apibo);
processTasks(project);
processPredecessors(project);
processAssignments(project);
//
// Ensure that the unique ID counters are correct
//
config.updateUniqueCounters();
return (m_projectFile);
}
catch (ParserConfigurationException ex)
{
throw new MPXJException("Failed to parse file", ex);
}
catch (JAXBException ex)
{
throw new MPXJException("Failed to parse file", ex);
}
catch (SAXException ex)
{
throw new MPXJException("Failed to parse file", ex);
}
finally
{
m_projectFile = null;
m_clashMap.clear();
m_calMap.clear();
}
}
/**
* Process project properties.
*
* @param apibo top level object
* @param project xml container
*/
private void processProjectProperties(APIBusinessObjects apibo, ProjectType project)
{
ProjectProperties properties = m_projectFile.getProjectProperties();
properties.setCreationDate(project.getCreateDate());
properties.setFinishDate(project.getFinishDate());
properties.setName(project.getName());
properties.setStartDate(project.getPlannedStartDate());
properties.setStatusDate(project.getDataDate());
properties.setProjectTitle(project.getId());
List<GlobalPreferencesType> list = apibo.getGlobalPreferences();
if (!list.isEmpty())
{
GlobalPreferencesType prefs = list.get(0);
properties.setCreationDate(prefs.getCreateDate());
properties.setLastSaved(prefs.getLastUpdateDate());
properties.setMinutesPerDay(Integer.valueOf((int) (NumberHelper.getDouble(prefs.getHoursPerDay()) * 60)));
properties.setMinutesPerWeek(Integer.valueOf((int) (NumberHelper.getDouble(prefs.getHoursPerWeek()) * 60)));
properties.setWeekStartDay(Day.getInstance(NumberHelper.getInt(prefs.getStartDayOfWeek())));
List<CurrencyType> currencyList = apibo.getCurrency();
for (CurrencyType currency : currencyList)
{
if (currency.getObjectId().equals(prefs.getBaseCurrencyObjectId()))
{
properties.setCurrencySymbol(currency.getSymbol());
break;
}
}
}
}
/**
* Process project calendars.
*
* @param apibo xml container
*/
private void processCalendars(APIBusinessObjects apibo)
{
for (CalendarType row : apibo.getCalendar())
{
ProjectCalendar calendar = m_projectFile.addCalendar();
Integer id = row.getObjectId();
m_calMap.put(id, calendar);
calendar.setName(row.getName());
calendar.setUniqueID(id);
StandardWorkWeek stdWorkWeek = row.getStandardWorkWeek();
if (stdWorkWeek != null)
{
for (StandardWorkHours hours : stdWorkWeek.getStandardWorkHours())
{
Day day = DAY_MAP.get(hours.getDayOfWeek());
List<WorkTimeType> workTime = hours.getWorkTime();
if (workTime.isEmpty() || workTime.get(0) == null)
{
calendar.setWorkingDay(day, false);
}
else
{
calendar.setWorkingDay(day, true);
ProjectCalendarHours calendarHours = calendar.addCalendarHours(day);
for (WorkTimeType work : workTime)
{
if (work != null)
{
calendarHours.addRange(new DateRange(work.getStart(), work.getFinish()));
}
}
}
}
}
HolidayOrExceptions hoe = row.getHolidayOrExceptions();
if (hoe != null)
{
for (HolidayOrException ex : hoe.getHolidayOrException())
{
Date startDate = DateHelper.getDayStartDate(ex.getDate());
Date endDate = DateHelper.getDayEndDate(ex.getDate());
ProjectCalendarException pce = calendar.addCalendarException(startDate, endDate);
List<WorkTimeType> workTime = ex.getWorkTime();
for (WorkTimeType work : workTime)
{
if (work != null)
{
pce.addRange(new DateRange(work.getStart(), work.getFinish()));
}
}
}
}
}
}
/**
* Process resources.
*
* @param apibo xml container
*/
private void processResources(APIBusinessObjects apibo)
{
List<ResourceType> resources = apibo.getResource();
for (ResourceType xml : resources)
{
Resource resource = m_projectFile.addResource();
resource.setUniqueID(xml.getObjectId());
resource.setName(xml.getName());
resource.setCode(xml.getEmployeeId());
resource.setEmailAddress(xml.getEmailAddress());
resource.setNotes(xml.getResourceNotes());
resource.setCreationDate(xml.getCreateDate());
resource.setType(RESOURCE_TYPE_MAP.get(xml.getResourceType()));
Integer calendarID = xml.getCalendarObjectId();
if (calendarID != null)
{
ProjectCalendar calendar = m_calMap.get(calendarID);
if (calendar != null)
{
//
// If the resource is linked to a base calendar, derive
// a default calendar from the base calendar.
//
if (!calendar.isDerived())
{
ProjectCalendar resourceCalendar = m_projectFile.addCalendar();
resourceCalendar.setParent(calendar);
resourceCalendar.setWorkingDay(Day.MONDAY, DayType.DEFAULT);
resourceCalendar.setWorkingDay(Day.TUESDAY, DayType.DEFAULT);
resourceCalendar.setWorkingDay(Day.WEDNESDAY, DayType.DEFAULT);
resourceCalendar.setWorkingDay(Day.THURSDAY, DayType.DEFAULT);
resourceCalendar.setWorkingDay(Day.FRIDAY, DayType.DEFAULT);
resourceCalendar.setWorkingDay(Day.SATURDAY, DayType.DEFAULT);
resourceCalendar.setWorkingDay(Day.SUNDAY, DayType.DEFAULT);
resource.setResourceCalendar(resourceCalendar);
}
else
{
//
// Primavera seems to allow a calendar to be shared between resources
// whereas in the MS Project model there is a one-to-one
// relationship. If we find a shared calendar, take a copy of it
//
if (calendar.getResource() == null)
{
resource.setResourceCalendar(calendar);
}
else
{
ProjectCalendar copy = m_projectFile.addCalendar();
copy.copy(calendar);
resource.setResourceCalendar(copy);
}
}
}
}
m_eventManager.fireResourceReadEvent(resource);
}
}
/**
* Process tasks.
*
* @param project xml container
*/
private void processTasks(ProjectType project)
{
List<WBSType> wbs = project.getWBS();
List<ActivityType> tasks = project.getActivity();
Set<Integer> uniqueIDs = new HashSet<Integer>();
//
// Read WBS entries and create tasks
//
for (WBSType row : wbs)
{
Task task = m_projectFile.addTask();
Integer uniqueID = row.getObjectId();
uniqueIDs.add(uniqueID);
task.setUniqueID(uniqueID);
task.setName(row.getName());
task.setBaselineCost(row.getSummaryBaselineTotalCost());
task.setRemainingCost(row.getSummaryRemainingTotalCost());
task.setRemainingDuration(getDuration(row.getSummaryRemainingDuration()));
task.setStart(row.getAnticipatedStartDate());
task.setFinish(row.getAnticipatedFinishDate());
task.setText(1, row.getCode());
}
//
// Create hierarchical structure
//
m_projectFile.getChildTasks().clear();
for (WBSType row : wbs)
{
Task task = m_projectFile.getTaskByUniqueID(row.getObjectId());
Task parentTask = m_projectFile.getTaskByUniqueID(row.getParentObjectId());
if (parentTask == null)
{
m_projectFile.getChildTasks().add(task);
}
else
{
m_projectFile.getChildTasks().remove(task);
parentTask.getChildTasks().add(task);
}
}
//
// Read Task entries and create tasks
//
int nextID = 1;
m_clashMap.clear();
for (ActivityType row : tasks)
{
Integer uniqueID = row.getObjectId();
if (uniqueIDs.contains(uniqueID))
{
while (uniqueIDs.contains(Integer.valueOf(nextID)))
{
++nextID;
}
Integer newUniqueID = Integer.valueOf(nextID);
m_clashMap.put(uniqueID, newUniqueID);
uniqueID = newUniqueID;
}
uniqueIDs.add(uniqueID);
Task task;
Integer parentTaskID = row.getWBSObjectId();
Task parentTask = m_projectFile.getTaskByUniqueID(parentTaskID);
if (parentTask == null)
{
task = m_projectFile.addTask();
}
else
{
task = parentTask.addTask();
}
task.setUniqueID(uniqueID);
task.setPercentageComplete(NumberHelper.getDouble(row.getPercentComplete().doubleValue() * 100.0));
task.setName(row.getName());
task.setRemainingDuration(getDuration(row.getRemainingDuration()));
task.setActualWork(getDuration(row.getActualDuration()));
task.setRemainingWork(getDuration(row.getRemainingTotalUnits()));
task.setBaselineDuration(getDuration(row.getPlannedDuration()));
task.setActualDuration(getDuration(row.getActualDuration()));
task.setDuration(getDuration(row.getAtCompletionDuration()));
// ActualCost and RemainingCost will be set when we resolve the resource assignments
task.setActualCost(NumberHelper.DOUBLE_ZERO);
task.setRemainingCost(NumberHelper.DOUBLE_ZERO);
task.setBaselineCost(NumberHelper.DOUBLE_ZERO);
task.setConstraintDate(row.getPrimaryConstraintDate());
task.setConstraintType(CONSTRAINT_TYPE_MAP.get(row.getPrimaryConstraintType()));
task.setActualStart(row.getActualStartDate());
task.setActualFinish(row.getActualFinishDate());
task.setLateStart(row.getRemainingLateStartDate());
task.setLateFinish(row.getRemainingLateFinishDate());
task.setEarlyStart(row.getRemainingEarlyStartDate());
task.setEarlyFinish(row.getRemainingEarlyFinishDate());
task.setBaselineStart(row.getPlannedStartDate());
task.setBaselineFinish(row.getPlannedFinishDate());
task.setPriority(PRIORITY_MAP.get(row.getLevelingPriority()));
task.setCreateDate(row.getCreateDate());
task.setText(1, row.getId());
task.setMilestone(BooleanHelper.getBoolean(MILESTONE_MAP.get(row.getType())));
task.setCritical(task.getEarlyStart() != null && task.getLateStart() != null && !(task.getLateStart().compareTo(task.getEarlyStart()) > 0));
Integer calId = row.getCalendarObjectId();
ProjectCalendar cal = m_calMap.get(calId);
task.setCalendar(cal);
task.setStart(row.getStartDate());
task.setFinish(row.getFinishDate());
populateField(task, TaskField.WORK, TaskField.BASELINE_WORK, TaskField.ACTUAL_WORK);
m_eventManager.fireTaskReadEvent(task);
}
updateStructure();
}
/**
* Populates a field based on baseline and actual values.
*
* @param container field container
* @param target target field
* @param baseline baseline field
* @param actual actual field
*/
private void populateField(FieldContainer container, FieldType target, FieldType baseline, FieldType actual)
{
Object value = container.getCachedValue(actual);
if (value == null)
{
value = container.getCachedValue(baseline);
}
container.set(target, value);
}
/**
* Iterates through the tasks setting the correct
* outline level and ID values.
*/
private void updateStructure()
{
int id = 1;
Integer outlineLevel = Integer.valueOf(1);
for (Task task : m_projectFile.getChildTasks())
{
id = updateStructure(id, task, outlineLevel);
}
}
/**
* Iterates through the tasks setting the correct
* outline level and ID values.
*
* @param id current ID value
* @param task current task
* @param outlineLevel current outline level
* @return next ID value
*/
private int updateStructure(int id, Task task, Integer outlineLevel)
{
task.setID(Integer.valueOf(id++));
task.setOutlineLevel(outlineLevel);
outlineLevel = Integer.valueOf(outlineLevel.intValue() + 1);
for (Task childTask : task.getChildTasks())
{
id = updateStructure(id, childTask, outlineLevel);
}
return id;
}
/**
* Process predecessors.
*
* @param project xml container
*/
private void processPredecessors(ProjectType project)
{
for (RelationshipType row : project.getRelationship())
{
Task currentTask = m_projectFile.getTaskByUniqueID(mapTaskID(row.getSuccessorActivityObjectId()));
Task predecessorTask = m_projectFile.getTaskByUniqueID(mapTaskID(row.getPredecessorActivityObjectId()));
if (currentTask != null && predecessorTask != null)
{
RelationType type = RELATION_TYPE_MAP.get(row.getType());
Duration lag = getDuration(row.getLag());
Relation relation = currentTask.addPredecessor(predecessorTask, type, lag);
m_eventManager.fireRelationReadEvent(relation);
}
}
}
/**
* Process resource assignments.
*
* @param project xml container
*/
private void processAssignments(ProjectType project)
{
List<ResourceAssignmentType> assignments = project.getResourceAssignment();
for (ResourceAssignmentType row : assignments)
{
Task task = m_projectFile.getTaskByUniqueID(mapTaskID(row.getActivityObjectId()));
Resource resource = m_projectFile.getResourceByUniqueID(row.getResourceObjectId());
if (task != null && resource != null)
{
ResourceAssignment assignment = task.addResourceAssignment(resource);
assignment.setUniqueID(row.getObjectId());
assignment.setRemainingWork(getDuration(row.getRemainingUnits()));
assignment.setBaselineWork(getDuration(row.getPlannedUnits()));
assignment.setActualWork(getDuration(row.getActualUnits()));
assignment.setRemainingCost(row.getRemainingCost());
assignment.setBaselineCost(row.getPlannedCost());
assignment.setActualCost(row.getActualCost());
assignment.setActualStart(row.getActualStartDate());
assignment.setActualFinish(row.getActualFinishDate());
assignment.setBaselineStart(row.getPlannedStartDate());
assignment.setBaselineFinish(row.getPlannedFinishDate());
task.setActualCost(Double.valueOf(task.getActualCost().doubleValue() + assignment.getActualCost().doubleValue()));
task.setRemainingCost(Double.valueOf(task.getRemainingCost().doubleValue() + assignment.getRemainingCost().doubleValue()));
task.setBaselineCost(Double.valueOf(task.getBaselineCost().doubleValue() + assignment.getBaselineCost().doubleValue()));
populateField(assignment, AssignmentField.WORK, AssignmentField.BASELINE_WORK, AssignmentField.ACTUAL_WORK);
populateField(assignment, AssignmentField.COST, AssignmentField.BASELINE_COST, AssignmentField.ACTUAL_COST);
populateField(assignment, AssignmentField.START, AssignmentField.BASELINE_START, AssignmentField.ACTUAL_START);
populateField(assignment, AssignmentField.FINISH, AssignmentField.BASELINE_FINISH, AssignmentField.ACTUAL_FINISH);
m_eventManager.fireAssignmentReadEvent(assignment);
}
}
}
/**
* Extracts a duration from a JAXBElement instance.
*
* @param duration duration expressed in hours
* @return duration instance
*/
private Duration getDuration(Double duration)
{
Duration result = null;
if (duration != null)
{
result = Duration.getInstance(NumberHelper.getDouble(duration), TimeUnit.HOURS);
}
return result;
}
/**
* Cached context to minimise construction cost.
*/
private static JAXBContext CONTEXT;
/**
* Note any error occurring during context construction.
*/
private static JAXBException CONTEXT_EXCEPTION;
static
{
try
{
//
// JAXB RI property to speed up construction
//
System.setProperty("com.sun.xml.bind.v2.runtime.JAXBContextImpl.fastBoot", "true");
//
// Construct the context
//
CONTEXT = JAXBContext.newInstance("net.sf.mpxj.primavera.schema", PrimaveraPMFileReader.class.getClassLoader());
}
catch (JAXBException ex)
{
CONTEXT_EXCEPTION = ex;
CONTEXT = null;
}
}
/**
* Deals with the case where we have had to map a task ID to a new value.
*
* @param id task ID from database
* @return mapped task ID
*/
private Integer mapTaskID(Integer id)
{
Integer mappedID = m_clashMap.get(id);
if (mappedID == null)
{
mappedID = id;
}
return (mappedID);
}
private ProjectFile m_projectFile;
private EventManager m_eventManager;
private List<ProjectListener> m_projectListeners;
private Map<Integer, Integer> m_clashMap = new HashMap<Integer, Integer>();
private Map<Integer, ProjectCalendar> m_calMap = new HashMap<Integer, ProjectCalendar>();
private static final Charset UTF8 = Charset.forName("UTF8");
private static final int NAMESPACE_SCOPE = 512;
private static final String NAMESPACE_REGEX = "xmlns=\\\".*\\\"";
private static final String NAMESPACE_REPLACEMENT = "xmlns=\"http://xmlns.oracle.com/Primavera/P6/V8.3/API/BusinessObjects\"";
private static final Map<String, net.sf.mpxj.ResourceType> RESOURCE_TYPE_MAP = new HashMap<String, net.sf.mpxj.ResourceType>();
static
{
RESOURCE_TYPE_MAP.put(null, net.sf.mpxj.ResourceType.WORK);
RESOURCE_TYPE_MAP.put("Labor", net.sf.mpxj.ResourceType.WORK);
RESOURCE_TYPE_MAP.put("Material", net.sf.mpxj.ResourceType.MATERIAL);
RESOURCE_TYPE_MAP.put("Nonlabor", net.sf.mpxj.ResourceType.MATERIAL);
}
private static final Map<String, ConstraintType> CONSTRAINT_TYPE_MAP = new HashMap<String, ConstraintType>();
static
{
CONSTRAINT_TYPE_MAP.put("Start On", ConstraintType.MUST_START_ON);
CONSTRAINT_TYPE_MAP.put("Start On or Before", ConstraintType.START_NO_LATER_THAN);
CONSTRAINT_TYPE_MAP.put("Start On or After", ConstraintType.START_NO_EARLIER_THAN);
CONSTRAINT_TYPE_MAP.put("Finish On", ConstraintType.MUST_FINISH_ON);
CONSTRAINT_TYPE_MAP.put("Finish On or Before", ConstraintType.FINISH_NO_LATER_THAN);
CONSTRAINT_TYPE_MAP.put("Finish On or After", ConstraintType.FINISH_NO_EARLIER_THAN);
CONSTRAINT_TYPE_MAP.put("As Late As Possible", ConstraintType.AS_LATE_AS_POSSIBLE);
CONSTRAINT_TYPE_MAP.put("Mandatory Start", ConstraintType.MUST_START_ON);
CONSTRAINT_TYPE_MAP.put("Mandatory Finish", ConstraintType.MUST_FINISH_ON);
}
private static final Map<String, Priority> PRIORITY_MAP = new HashMap<String, Priority>();
static
{
PRIORITY_MAP.put("Top", Priority.getInstance(Priority.HIGHEST));
PRIORITY_MAP.put("High", Priority.getInstance(Priority.HIGH));
PRIORITY_MAP.put("Normal", Priority.getInstance(Priority.MEDIUM));
PRIORITY_MAP.put("Low", Priority.getInstance(Priority.LOW));
PRIORITY_MAP.put("Lowest", Priority.getInstance(Priority.LOWEST));
}
private static final Map<String, RelationType> RELATION_TYPE_MAP = new HashMap<String, RelationType>();
static
{
RELATION_TYPE_MAP.put("Finish to Start", RelationType.FINISH_START);
RELATION_TYPE_MAP.put("Finish to Finish", RelationType.FINISH_FINISH);
RELATION_TYPE_MAP.put("Start to Start", RelationType.START_START);
RELATION_TYPE_MAP.put("Start to Finish", RelationType.START_FINISH);
}
private static final Map<String, Day> DAY_MAP = new HashMap<String, Day>();
static
{
DAY_MAP.put("Monday", Day.MONDAY);
DAY_MAP.put("Tuesday", Day.TUESDAY);
DAY_MAP.put("Wednesday", Day.WEDNESDAY);
DAY_MAP.put("Thursday", Day.THURSDAY);
DAY_MAP.put("Friday", Day.FRIDAY);
DAY_MAP.put("Saturday", Day.SATURDAY);
DAY_MAP.put("Sunday", Day.SUNDAY);
}
private static final Map<String, Boolean> MILESTONE_MAP = new HashMap<String, Boolean>();
static
{
MILESTONE_MAP.put("Task Dependent", Boolean.FALSE);
MILESTONE_MAP.put("Resource Dependent", Boolean.FALSE);
MILESTONE_MAP.put("Level of Effort", Boolean.FALSE);
MILESTONE_MAP.put("Start Milestone", Boolean.TRUE);
MILESTONE_MAP.put("Finish Milestone", Boolean.TRUE);
MILESTONE_MAP.put("WBS Summary", Boolean.FALSE);
}
}