/* * file: MPP8Reader.java * author: Jon Iles * copyright: (c) Packwood Software 2002-2003 * date: 08/05/2003 */ /* * 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.mpp; import java.io.FileNotFoundException; import java.io.IOException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import net.sf.mpxj.AccrueType; import net.sf.mpxj.Column; import net.sf.mpxj.ConstraintType; import net.sf.mpxj.DateRange; import net.sf.mpxj.Day; import net.sf.mpxj.Duration; import net.sf.mpxj.EventManager; 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.ProjectFile; import net.sf.mpxj.ProjectProperties; import net.sf.mpxj.Rate; import net.sf.mpxj.Relation; import net.sf.mpxj.RelationType; import net.sf.mpxj.Resource; import net.sf.mpxj.ResourceAssignment; import net.sf.mpxj.Table; import net.sf.mpxj.TableContainer; import net.sf.mpxj.Task; import net.sf.mpxj.TaskType; import net.sf.mpxj.TimeUnit; import net.sf.mpxj.View; import net.sf.mpxj.common.MPPResourceField; import net.sf.mpxj.common.MPPTaskField; import net.sf.mpxj.common.NumberHelper; import net.sf.mpxj.common.Pair; import org.apache.poi.poifs.filesystem.DirectoryEntry; import org.apache.poi.poifs.filesystem.DocumentEntry; import org.apache.poi.poifs.filesystem.DocumentInputStream; /** * This class is used to represent a Microsoft Project MPP8 file. This * implementation allows the file to be read, and the data it contains * exported as a set of MPX objects. These objects can be interrogated * to retrieve any required data, or stored as an MPX file. */ final class MPP8Reader implements MPPVariantReader { /** * This method is used to process an MPP8 file. This is the file format * used by Project 98. * * @param reader parent file reader * @param file Parent MPX file * @param root Root of the POI file system. * @throws MPXJException * @throws IOException */ @Override public void process(MPPReader reader, ProjectFile file, DirectoryEntry root) throws MPXJException, IOException { try { populateMemberData(reader, file, root); processProjectProperties(); if (!reader.getReadPropertiesOnly()) { processCalendarData(); processResourceData(); processTaskData(); processConstraintData(); processAssignmentData(); if (reader.getReadPresentationData()) { processViewPropertyData(); processViewData(); processTableData(); } } } finally { clearMemberData(); } } /** * Populate member data used by the rest of the reader. * * @param reader parent file reader * @param file parent MPP file * @param root Root of the POI file system. */ private void populateMemberData(MPPReader reader, ProjectFile file, DirectoryEntry root) throws IOException { m_reader = reader; m_root = root; m_file = file; m_eventManager = file.getEventManager(); m_calendarMap = new HashMap<Integer, ProjectCalendar>(); m_projectDir = (DirectoryEntry) root.getEntry(" 1"); m_viewDir = (DirectoryEntry) root.getEntry(" 2"); m_file.getProjectProperties().setMppFileType(Integer.valueOf(8)); } /** * Clear transient member data. */ private void clearMemberData() { m_reader = null; m_root = null; m_eventManager = null; m_file = null; m_calendarMap = null; m_projectDir = null; m_viewDir = null; } /** * Process the project properties data. */ private void processProjectProperties() throws MPXJException, IOException { Props8 props = new Props8(new DocumentInputStream(((DocumentEntry) m_projectDir.getEntry("Props")))); ProjectPropertiesReader reader = new ProjectPropertiesReader(); reader.process(m_file, props, m_root); } /** * This method process the data held in the props file specific to the * visual appearance of the project data. */ private void processViewPropertyData() throws IOException { Props8 props = new Props8(new DocumentInputStream(((DocumentEntry) m_viewDir.getEntry("Props")))); ProjectProperties properties = m_file.getProjectProperties(); properties.setShowProjectSummaryTask(props.getBoolean(Props.SHOW_PROJECT_SUMMARY_TASK)); } /** * This method extracts and collates calendar data. * * @throws MPXJException * @throws IOException */ private void processCalendarData() throws MPXJException, IOException { DirectoryEntry calDir = (DirectoryEntry) m_projectDir.getEntry("TBkndCal"); FixFix calendarFixedData = new FixFix(36, new DocumentInputStream(((DocumentEntry) calDir.getEntry("FixFix 0")))); FixDeferFix calendarVarData = new FixDeferFix(new DocumentInputStream(((DocumentEntry) calDir.getEntry("FixDeferFix 0")))); ProjectCalendar cal; ProjectCalendarHours hours; ProjectCalendarException exception; String name; byte[] baseData; byte[] extData; int periodCount; int index; int offset; int defaultFlag; Date start; long duration; int exceptionCount; // // Configure default time ranges // SimpleDateFormat df = new SimpleDateFormat("HH:mm"); Date defaultStart1; Date defaultEnd1; Date defaultStart2; Date defaultEnd2; try { defaultStart1 = df.parse("08:00"); defaultEnd1 = df.parse("12:00"); defaultStart2 = df.parse("13:00"); defaultEnd2 = df.parse("17:00"); } catch (ParseException ex) { throw new MPXJException(MPXJException.INVALID_FORMAT, ex); } int calendars = calendarFixedData.getItemCount(); int calendarID; int baseCalendarID; int periodIndex; Day day; List<Pair<ProjectCalendar, Integer>> baseCalendars = new LinkedList<Pair<ProjectCalendar, Integer>>(); for (int loop = 0; loop < calendars; loop++) { baseData = calendarFixedData.getByteArrayValue(loop); calendarID = MPPUtility.getInt(baseData, 0); baseCalendarID = MPPUtility.getInt(baseData, 4); name = calendarVarData.getUnicodeString(getOffset(baseData, 20)); // // Uncommenting the call to this method is useful when trying // to determine the function of unknown task data. // //dumpUnknownData (name + " " + MPPUtility.getInt(baseData), UNKNOWN_CALENDAR_DATA, baseData); // // Skip calendars with negative ID values // if (calendarID < 0) { continue; } // // Populate the basic calendar // ExtendedData ed = new ExtendedData(calendarVarData, getOffset(baseData, 32)); offset = -1 - ed.getInt(Integer.valueOf(8)); if (offset == -1) { if (baseCalendarID > 0) { cal = m_file.addDefaultDerivedCalendar(); baseCalendars.add(new Pair<ProjectCalendar, Integer>(cal, Integer.valueOf(baseCalendarID))); } else { cal = m_file.addDefaultBaseCalendar(); cal.setName(name); } cal.setUniqueID(Integer.valueOf(calendarID)); } else { if (baseCalendarID > 0) { cal = m_file.addCalendar(); baseCalendars.add(new Pair<ProjectCalendar, Integer>(cal, Integer.valueOf(baseCalendarID))); } else { cal = m_file.addCalendar(); cal.setName(name); } cal.setUniqueID(Integer.valueOf(calendarID)); extData = calendarVarData.getByteArray(offset); for (index = 0; index < 7; index++) { offset = 4 + (40 * index); defaultFlag = MPPUtility.getShort(extData, offset); day = Day.getInstance(index + 1); if (defaultFlag == 1) { cal.setWorkingDay(day, DEFAULT_WORKING_WEEK[index]); if (cal.isWorkingDay(day) == true) { hours = cal.addCalendarHours(net.sf.mpxj.Day.getInstance(index + 1)); hours.addRange(new DateRange(defaultStart1, defaultEnd1)); hours.addRange(new DateRange(defaultStart2, defaultEnd2)); } } else { periodCount = MPPUtility.getShort(extData, offset + 2); if (periodCount == 0) { cal.setWorkingDay(day, false); } else { cal.setWorkingDay(day, true); hours = cal.addCalendarHours(Day.getInstance(index + 1)); for (periodIndex = 0; periodIndex < periodCount; periodIndex++) { start = MPPUtility.getTime(extData, offset + 8 + (periodIndex * 2)); duration = MPPUtility.getDuration(extData, offset + 16 + (periodIndex * 4)); hours.addRange(new DateRange(start, new Date(start.getTime() + duration))); } } } } // // Handle any exceptions // exceptionCount = MPPUtility.getShort(extData, 0); if (exceptionCount != 0) { for (index = 0; index < exceptionCount; index++) { offset = 4 + (40 * 7) + (index * 44); Date fromDate = MPPUtility.getDate(extData, offset); Date toDate = MPPUtility.getDate(extData, offset + 2); exception = cal.addCalendarException(fromDate, toDate); periodCount = MPPUtility.getShort(extData, offset + 6); if (periodCount != 0) { for (int exceptionPeriodIndex = 0; exceptionPeriodIndex < periodCount; exceptionPeriodIndex++) { start = MPPUtility.getTime(extData, offset + 12 + (exceptionPeriodIndex * 2)); duration = MPPUtility.getDuration(extData, offset + 20 + (exceptionPeriodIndex * 4)); exception.addRange(new DateRange(start, new Date(start.getTime() + duration))); } } } } } m_calendarMap.put(Integer.valueOf(calendarID), cal); m_eventManager.fireCalendarReadEvent(cal); } updateBaseCalendarNames(baseCalendars); } /** * The way calendars are stored in an MPP8 file means that there * can be forward references between the base calendar unique ID for a * derived calendar, and the base calendar itself. To get around this, * we initially populate the base calendar name attribute with the * base calendar unique ID, and now in this method we can convert those * ID values into the correct names. * * @param baseCalendars list of calendars and base calendar IDs */ private void updateBaseCalendarNames(List<Pair<ProjectCalendar, Integer>> baseCalendars) { for (Pair<ProjectCalendar, Integer> pair : baseCalendars) { ProjectCalendar cal = pair.getFirst(); Integer baseCalendarID = pair.getSecond(); ProjectCalendar baseCal = m_calendarMap.get(baseCalendarID); if (baseCal != null) { cal.setParent(baseCal); } } } /** * This method extracts and collates task data. * * @throws IOException */ private void processTaskData() throws IOException { DirectoryEntry taskDir = (DirectoryEntry) m_projectDir.getEntry("TBkndTask"); FixFix taskFixedData = new FixFix(316, new DocumentInputStream(((DocumentEntry) taskDir.getEntry("FixFix 0")))); if (taskFixedData.getDiff() != 0) { taskFixedData = new FixFix(366, new DocumentInputStream(((DocumentEntry) taskDir.getEntry("FixFix 0")))); } FixDeferFix taskVarData = null; ExtendedData taskExtData = null; int tasks = taskFixedData.getItemCount(); byte[] data; int uniqueID; int id; int deleted; Task task; boolean autoWBS = true; String notes; byte[] flags = new byte[3]; RecurringTaskReader recurringTaskReader = null; ProjectProperties properties = m_file.getProjectProperties(); TimeUnit defaultProjectTimeUnits = properties.getDefaultDurationUnits(); for (int loop = 0; loop < tasks; loop++) { data = taskFixedData.getByteArrayValue(loop); // // Test for a valid unique id // uniqueID = MPPUtility.getInt(data, 0); if (uniqueID < 1) { continue; } // // Test to ensure this task has not been deleted. // This appears to be a set of flags rather than a single value. // The data I have seen to date shows deleted tasks having values of // 0x0001 and 0x0002. Valid tasks have had values of 0x0000, 0x0914, // 0x0040, 0x004A, 0x203D and 0x0031 // deleted = MPPUtility.getShort(data, 272); if ((deleted & 0xC0) == 0 && (deleted & 0x03) != 0 && deleted != 0x0031 && deleted != 0x203D) { continue; } // // Load the var data if we have not already done so // if (taskVarData == null) { taskVarData = new FixDeferFix(new DocumentInputStream(((DocumentEntry) taskDir.getEntry("FixDeferFix 0")))); } // // Blank rows can be present in MPP files. The following flag // appears to indicate that a row is blank, and should be // ignored. // if ((data[8] & 0x01) != 0) { continue; } taskExtData = new ExtendedData(taskVarData, getOffset(data, 312)); byte[] recurringData = taskExtData.getByteArray(TASK_RECURRING_DATA); id = MPPUtility.getInt(data, 4); flags[0] = (byte) (data[268] & data[303]); flags[1] = (byte) (data[269] & data[304]); flags[2] = (byte) (data[270] & data[305]); task = m_file.addTask(); task.setActualCost(NumberHelper.getDouble(((double) MPPUtility.getLong6(data, 234)) / 100)); task.setActualDuration(MPPUtility.getAdjustedDuration(properties, MPPUtility.getInt(data, 74), MPPUtility.getDurationTimeUnits(MPPUtility.getShort(data, 72), defaultProjectTimeUnits))); task.setActualFinish(MPPUtility.getTimestamp(data, 108)); task.setActualOvertimeCost(NumberHelper.getDouble(((double) MPPUtility.getLong6(data, 210)) / 100)); task.setActualOvertimeWork(MPPUtility.getDuration(((double) MPPUtility.getLong6(data, 192)) / 100, TimeUnit.HOURS)); task.setActualStart(MPPUtility.getTimestamp(data, 104)); task.setActualWork(MPPUtility.getDuration(((double) MPPUtility.getLong6(data, 180)) / 100, TimeUnit.HOURS)); //task.setACWP(); // Calculated value //task.setAssignment(); // Calculated value //task.setAssignmentDelay(); // Calculated value //task.setAssignmentUnits(); // Calculated value task.setBaselineCost(NumberHelper.getDouble((double) MPPUtility.getLong6(data, 246) / 100)); task.setBaselineDuration(MPPUtility.getAdjustedDuration(properties, MPPUtility.getInt(data, 82), MPPUtility.getDurationTimeUnits(MPPUtility.getShort(data, 72), defaultProjectTimeUnits))); task.setBaselineFinish(MPPUtility.getTimestamp(data, 116)); task.setBaselineStart(MPPUtility.getTimestamp(data, 112)); task.setBaselineWork(MPPUtility.getDuration(((double) MPPUtility.getLong6(data, 174)) / 100, TimeUnit.HOURS)); //task.setBCWP(); // Calculated value //task.setBCWS(); // Calculated value //task.setConfirmed(); // Calculated value task.setConstraintDate(MPPUtility.getTimestamp(data, 120)); task.setConstraintType(ConstraintType.getInstance(MPPUtility.getShort(data, 88))); task.setContact(taskExtData.getUnicodeString(TASK_CONTACT)); task.setCost(NumberHelper.getDouble(((double) MPPUtility.getLong6(data, 222)) / 100)); task.setCost(1, NumberHelper.getDouble(((double) taskExtData.getLong(TASK_COST1)) / 100)); task.setCost(2, NumberHelper.getDouble(((double) taskExtData.getLong(TASK_COST2)) / 100)); task.setCost(3, NumberHelper.getDouble(((double) taskExtData.getLong(TASK_COST3)) / 100)); task.setCost(4, NumberHelper.getDouble(((double) taskExtData.getLong(TASK_COST4)) / 100)); task.setCost(5, NumberHelper.getDouble(((double) taskExtData.getLong(TASK_COST5)) / 100)); task.setCost(6, NumberHelper.getDouble(((double) taskExtData.getLong(TASK_COST6)) / 100)); task.setCost(7, NumberHelper.getDouble(((double) taskExtData.getLong(TASK_COST7)) / 100)); task.setCost(8, NumberHelper.getDouble(((double) taskExtData.getLong(TASK_COST8)) / 100)); task.setCost(9, NumberHelper.getDouble(((double) taskExtData.getLong(TASK_COST9)) / 100)); task.setCost(10, NumberHelper.getDouble(((double) taskExtData.getLong(TASK_COST10)) / 100)); //task.setCostRateTable(); // Calculated value //task.setCostVariance(); // Populated below task.setCreateDate(MPPUtility.getTimestamp(data, 138)); //task.setCritical(); // Calculated value //task.setCV(); // Calculated value task.setDate(1, taskExtData.getTimestamp(TASK_DATE1)); task.setDate(2, taskExtData.getTimestamp(TASK_DATE2)); task.setDate(3, taskExtData.getTimestamp(TASK_DATE3)); task.setDate(4, taskExtData.getTimestamp(TASK_DATE4)); task.setDate(5, taskExtData.getTimestamp(TASK_DATE5)); task.setDate(6, taskExtData.getTimestamp(TASK_DATE6)); task.setDate(7, taskExtData.getTimestamp(TASK_DATE7)); task.setDate(8, taskExtData.getTimestamp(TASK_DATE8)); task.setDate(9, taskExtData.getTimestamp(TASK_DATE9)); task.setDate(10, taskExtData.getTimestamp(TASK_DATE10)); //task.setDelay(); // No longer supported by MS Project? task.setDuration(MPPUtility.getAdjustedDuration(properties, MPPUtility.getInt(data, 68), MPPUtility.getDurationTimeUnits(MPPUtility.getShort(data, 72), defaultProjectTimeUnits))); task.setDuration(1, MPPUtility.getAdjustedDuration(properties, taskExtData.getInt(TASK_DURATION1), MPPUtility.getDurationTimeUnits(taskExtData.getShort(TASK_DURATION1_UNITS), defaultProjectTimeUnits))); task.setDuration(2, MPPUtility.getAdjustedDuration(properties, taskExtData.getInt(TASK_DURATION2), MPPUtility.getDurationTimeUnits(taskExtData.getShort(TASK_DURATION2_UNITS), defaultProjectTimeUnits))); task.setDuration(3, MPPUtility.getAdjustedDuration(properties, taskExtData.getInt(TASK_DURATION3), MPPUtility.getDurationTimeUnits(taskExtData.getShort(TASK_DURATION3_UNITS), defaultProjectTimeUnits))); task.setDuration(4, MPPUtility.getAdjustedDuration(properties, taskExtData.getInt(TASK_DURATION4), MPPUtility.getDurationTimeUnits(taskExtData.getShort(TASK_DURATION4_UNITS), defaultProjectTimeUnits))); task.setDuration(5, MPPUtility.getAdjustedDuration(properties, taskExtData.getInt(TASK_DURATION5), MPPUtility.getDurationTimeUnits(taskExtData.getShort(TASK_DURATION5_UNITS), defaultProjectTimeUnits))); task.setDuration(6, MPPUtility.getAdjustedDuration(properties, taskExtData.getInt(TASK_DURATION6), MPPUtility.getDurationTimeUnits(taskExtData.getShort(TASK_DURATION6_UNITS), defaultProjectTimeUnits))); task.setDuration(7, MPPUtility.getAdjustedDuration(properties, taskExtData.getInt(TASK_DURATION7), MPPUtility.getDurationTimeUnits(taskExtData.getShort(TASK_DURATION7_UNITS), defaultProjectTimeUnits))); task.setDuration(8, MPPUtility.getAdjustedDuration(properties, taskExtData.getInt(TASK_DURATION8), MPPUtility.getDurationTimeUnits(taskExtData.getShort(TASK_DURATION8_UNITS), defaultProjectTimeUnits))); task.setDuration(9, MPPUtility.getAdjustedDuration(properties, taskExtData.getInt(TASK_DURATION9), MPPUtility.getDurationTimeUnits(taskExtData.getShort(TASK_DURATION9_UNITS), defaultProjectTimeUnits))); task.setDuration(10, MPPUtility.getAdjustedDuration(properties, taskExtData.getInt(TASK_DURATION10), MPPUtility.getDurationTimeUnits(taskExtData.getShort(TASK_DURATION10_UNITS), defaultProjectTimeUnits))); //task.setDurationVariance(); // Calculated value task.setEarlyFinish(MPPUtility.getTimestamp(data, 20)); task.setEarlyStart(MPPUtility.getTimestamp(data, 96)); task.setEffortDriven((data[17] & 0x08) != 0); //task.setExternalTask(); // Calculated value task.setFinish(MPPUtility.getTimestamp(data, 20)); task.setFinish(1, taskExtData.getTimestamp(TASK_FINISH1)); task.setFinish(2, taskExtData.getTimestamp(TASK_FINISH2)); task.setFinish(3, taskExtData.getTimestamp(TASK_FINISH3)); task.setFinish(4, taskExtData.getTimestamp(TASK_FINISH4)); task.setFinish(5, taskExtData.getTimestamp(TASK_FINISH5)); task.setFinish(6, taskExtData.getTimestamp(TASK_FINISH6)); task.setFinish(7, taskExtData.getTimestamp(TASK_FINISH7)); task.setFinish(8, taskExtData.getTimestamp(TASK_FINISH8)); task.setFinish(9, taskExtData.getTimestamp(TASK_FINISH9)); task.setFinish(10, taskExtData.getTimestamp(TASK_FINISH10)); //task.setFinishVariance(); // Calculated value task.setFixedCost(NumberHelper.getDouble(((double) MPPUtility.getLong6(data, 228)) / 100)); task.setFixedCostAccrual(AccrueType.getInstance(MPPUtility.getShort(data, 136))); task.setFlag(1, (flags[0] & 0x02) != 0); task.setFlag(2, (flags[0] & 0x04) != 0); task.setFlag(3, (flags[0] & 0x08) != 0); task.setFlag(4, (flags[0] & 0x10) != 0); task.setFlag(5, (flags[0] & 0x20) != 0); task.setFlag(6, (flags[0] & 0x40) != 0); task.setFlag(7, (flags[0] & 0x80) != 0); task.setFlag(8, (flags[1] & 0x01) != 0); task.setFlag(9, (flags[1] & 0x02) != 0); task.setFlag(10, (flags[1] & 0x04) != 0); task.setFlag(11, (flags[1] & 0x08) != 0); task.setFlag(12, (flags[1] & 0x10) != 0); task.setFlag(13, (flags[1] & 0x20) != 0); task.setFlag(14, (flags[1] & 0x40) != 0); task.setFlag(15, (flags[1] & 0x80) != 0); task.setFlag(16, (flags[2] & 0x01) != 0); task.setFlag(17, (flags[2] & 0x02) != 0); task.setFlag(18, (flags[2] & 0x04) != 0); task.setFlag(19, (flags[2] & 0x08) != 0); task.setFlag(20, (flags[2] & 0x10) != 0); // note that this is not correct //task.setFreeSlack(); // Calculated value task.setHideBar((data[16] & 0x01) != 0); processHyperlinkData(task, taskVarData.getByteArray(-1 - taskExtData.getInt(TASK_HYPERLINK))); task.setID(Integer.valueOf(id)); //task.setIndicators(); // Calculated value task.setLateFinish(MPPUtility.getTimestamp(data, 160)); task.setLateStart(MPPUtility.getTimestamp(data, 24)); task.setLevelAssignments((data[19] & 0x10) != 0); task.setLevelingCanSplit((data[19] & 0x08) != 0); task.setLevelingDelay(MPPUtility.getDuration(((double) MPPUtility.getInt(data, 90)) / 3, MPPUtility.getDurationTimeUnits(MPPUtility.getShort(data, 94), defaultProjectTimeUnits))); //task.setLinkedFields(); // Calculated value task.setMarked((data[13] & 0x02) != 0); task.setMilestone((data[12] & 0x01) != 0); task.setName(taskVarData.getUnicodeString(getOffset(data, 264))); task.setNumber(1, NumberHelper.getDouble(taskExtData.getDouble(TASK_NUMBER1))); task.setNumber(2, NumberHelper.getDouble(taskExtData.getDouble(TASK_NUMBER2))); task.setNumber(3, NumberHelper.getDouble(taskExtData.getDouble(TASK_NUMBER3))); task.setNumber(4, NumberHelper.getDouble(taskExtData.getDouble(TASK_NUMBER4))); task.setNumber(5, NumberHelper.getDouble(taskExtData.getDouble(TASK_NUMBER5))); task.setNumber(6, NumberHelper.getDouble(taskExtData.getDouble(TASK_NUMBER6))); task.setNumber(7, NumberHelper.getDouble(taskExtData.getDouble(TASK_NUMBER7))); task.setNumber(8, NumberHelper.getDouble(taskExtData.getDouble(TASK_NUMBER8))); task.setNumber(9, NumberHelper.getDouble(taskExtData.getDouble(TASK_NUMBER9))); task.setNumber(10, NumberHelper.getDouble(taskExtData.getDouble(TASK_NUMBER10))); task.setNumber(11, NumberHelper.getDouble(taskExtData.getDouble(TASK_NUMBER11))); task.setNumber(12, NumberHelper.getDouble(taskExtData.getDouble(TASK_NUMBER12))); task.setNumber(13, NumberHelper.getDouble(taskExtData.getDouble(TASK_NUMBER13))); task.setNumber(14, NumberHelper.getDouble(taskExtData.getDouble(TASK_NUMBER14))); task.setNumber(15, NumberHelper.getDouble(taskExtData.getDouble(TASK_NUMBER15))); task.setNumber(16, NumberHelper.getDouble(taskExtData.getDouble(TASK_NUMBER16))); task.setNumber(17, NumberHelper.getDouble(taskExtData.getDouble(TASK_NUMBER17))); task.setNumber(18, NumberHelper.getDouble(taskExtData.getDouble(TASK_NUMBER18))); task.setNumber(19, NumberHelper.getDouble(taskExtData.getDouble(TASK_NUMBER19))); task.setNumber(20, NumberHelper.getDouble(taskExtData.getDouble(TASK_NUMBER20))); //task.setObjects(); // Calculated value task.setOutlineLevel(Integer.valueOf(MPPUtility.getShort(data, 48))); //task.setOutlineNumber(); // Calculated value //task.setOverallocated(); // Calculated value task.setOvertimeCost(NumberHelper.getDouble(((double) MPPUtility.getLong6(data, 204)) / 100)); //task.setOvertimeWork(); // Calculated value //task.getPredecessors(); // Calculated value task.setPercentageComplete(MPPUtility.getPercentage(data, 130)); task.setPercentageWorkComplete(MPPUtility.getPercentage(data, 132)); task.setPreleveledFinish(MPPUtility.getTimestamp(data, 148)); task.setPreleveledStart(MPPUtility.getTimestamp(data, 144)); task.setPriority(Priority.getInstance((MPPUtility.getShort(data, 128) + 1) * 100)); //task.setProject(); // Calculated value task.setRecurring(MPPUtility.getShort(data, 142) != 0); //task.setRegularWork(); // Calculated value task.setRemainingCost(NumberHelper.getDouble(((double) MPPUtility.getLong6(data, 240)) / 100)); task.setRemainingDuration(MPPUtility.getAdjustedDuration(properties, MPPUtility.getInt(data, 78), MPPUtility.getDurationTimeUnits(MPPUtility.getShort(data, 72), defaultProjectTimeUnits))); task.setRemainingOvertimeCost(NumberHelper.getDouble(((double) MPPUtility.getLong6(data, 216)) / 100)); task.setRemainingOvertimeWork(MPPUtility.getDuration(((double) MPPUtility.getLong6(data, 198)) / 100, TimeUnit.HOURS)); task.setRemainingWork(MPPUtility.getDuration(((double) MPPUtility.getLong6(data, 186)) / 100, TimeUnit.HOURS)); //task.setResourceGroup(); // Calculated value from resource //task.setResourceInitials(); // Calculated value from resource //task.setResourceNames(); // Calculated value from resource //task.setResourcePhonetics(); // Calculated value from resource //task.setResponsePending(); // Calculated value task.setResume(MPPUtility.getTimestamp(data, 32)); //task.setResumeNoEarlierThan(); // Not in MSP98? task.setRollup((data[15] & 0x04) != 0); task.setStart(MPPUtility.getTimestamp(data, 96)); task.setStart(1, taskExtData.getTimestamp(TASK_START1)); task.setStart(2, taskExtData.getTimestamp(TASK_START2)); task.setStart(3, taskExtData.getTimestamp(TASK_START3)); task.setStart(4, taskExtData.getTimestamp(TASK_START4)); task.setStart(5, taskExtData.getTimestamp(TASK_START5)); task.setStart(6, taskExtData.getTimestamp(TASK_START6)); task.setStart(7, taskExtData.getTimestamp(TASK_START7)); task.setStart(8, taskExtData.getTimestamp(TASK_START8)); task.setStart(9, taskExtData.getTimestamp(TASK_START9)); task.setStart(10, taskExtData.getTimestamp(TASK_START10)); //task.setStartVariance(); // Calculated value task.setStop(MPPUtility.getTimestamp(data, 124)); //task.setSubprojectFile(); //task.setSubprojectReadOnly(); //task.setSuccessors(); // Calculated value //task.setSummary(); // Automatically generated by MPXJ //task.setSV(); // Calculated value //task.teamStatusPending(); // Calculated value task.setText(1, taskExtData.getUnicodeString(TASK_TEXT1)); task.setText(2, taskExtData.getUnicodeString(TASK_TEXT2)); task.setText(3, taskExtData.getUnicodeString(TASK_TEXT3)); task.setText(4, taskExtData.getUnicodeString(TASK_TEXT4)); task.setText(5, taskExtData.getUnicodeString(TASK_TEXT5)); task.setText(6, taskExtData.getUnicodeString(TASK_TEXT6)); task.setText(7, taskExtData.getUnicodeString(TASK_TEXT7)); task.setText(8, taskExtData.getUnicodeString(TASK_TEXT8)); task.setText(9, taskExtData.getUnicodeString(TASK_TEXT9)); task.setText(10, taskExtData.getUnicodeString(TASK_TEXT10)); task.setText(11, taskExtData.getUnicodeString(TASK_TEXT11)); task.setText(12, taskExtData.getUnicodeString(TASK_TEXT12)); task.setText(13, taskExtData.getUnicodeString(TASK_TEXT13)); task.setText(14, taskExtData.getUnicodeString(TASK_TEXT14)); task.setText(15, taskExtData.getUnicodeString(TASK_TEXT15)); task.setText(16, taskExtData.getUnicodeString(TASK_TEXT16)); task.setText(17, taskExtData.getUnicodeString(TASK_TEXT17)); task.setText(18, taskExtData.getUnicodeString(TASK_TEXT18)); task.setText(19, taskExtData.getUnicodeString(TASK_TEXT19)); task.setText(20, taskExtData.getUnicodeString(TASK_TEXT20)); task.setText(21, taskExtData.getUnicodeString(TASK_TEXT21)); task.setText(22, taskExtData.getUnicodeString(TASK_TEXT22)); task.setText(23, taskExtData.getUnicodeString(TASK_TEXT23)); task.setText(24, taskExtData.getUnicodeString(TASK_TEXT24)); task.setText(25, taskExtData.getUnicodeString(TASK_TEXT25)); task.setText(26, taskExtData.getUnicodeString(TASK_TEXT26)); task.setText(27, taskExtData.getUnicodeString(TASK_TEXT27)); task.setText(28, taskExtData.getUnicodeString(TASK_TEXT28)); task.setText(29, taskExtData.getUnicodeString(TASK_TEXT29)); task.setText(30, taskExtData.getUnicodeString(TASK_TEXT30)); //task.setTotalSlack(); // Calculated value task.setType(TaskType.getInstance(MPPUtility.getShort(data, 134))); task.setUniqueID(Integer.valueOf(uniqueID)); //task.setUniqueIDPredecessors(); // Calculated value //task.setUniqueIDSuccessors(); // Calculated value //task.setUpdateNeeded(); // Calculated value task.setWBS(taskExtData.getUnicodeString(TASK_WBS)); task.setWork(MPPUtility.getDuration(((double) MPPUtility.getLong6(data, 168)) / 100, TimeUnit.HOURS)); //task.setWorkContour(); // Calculated from resource //task.setWorkVariance(); // Calculated value // // Retrieve task recurring data // if (recurringData != null) { if (recurringTaskReader == null) { recurringTaskReader = new RecurringTaskReader(properties); } recurringTaskReader.processRecurringTask(task, recurringData); } // // Retrieve the task notes. // notes = taskExtData.getString(TASK_NOTES); if (notes != null) { //claur // if (m_reader.getPreserveNoteFormatting() == false) // { // notes = RtfHelper.strip(notes); // } task.setNotes(notes); } // // If we have a WBS value from the MPP file, don't autogenerate // if (task.getWBS() != null) { autoWBS = false; } m_eventManager.fireTaskReadEvent(task); // // Uncommenting the call to this method is useful when trying // to determine the function of unknown task data. // //dumpUnknownData (task.getName(), UNKNOWN_TASK_DATA, data); } // // Enable auto WBS if necessary // m_file.getProjectConfig().setAutoWBS(autoWBS); } /** * This method is used to extract the task hyperlink attributes * from a block of data and call the appropriate modifier methods * to configure the specified task object. * * @param task task instance * @param data hyperlink data block */ private void processHyperlinkData(Task task, byte[] data) { if (data != null) { int offset = 12; String hyperlink; String address; String subaddress; offset += 12; hyperlink = MPPUtility.getUnicodeString(data, offset); offset += ((hyperlink.length() + 1) * 2); offset += 12; address = MPPUtility.getUnicodeString(data, offset); offset += ((address.length() + 1) * 2); offset += 12; subaddress = MPPUtility.getUnicodeString(data, offset); task.setHyperlink(hyperlink); task.setHyperlinkAddress(address); task.setHyperlinkSubAddress(subaddress); } } /** * This method extracts and collates constraint data. * * @throws IOException */ private void processConstraintData() throws IOException { // // Locate the directory containing the constraints // DirectoryEntry consDir; try { consDir = (DirectoryEntry) m_projectDir.getEntry("TBkndCons"); } catch (FileNotFoundException ex) { consDir = null; } // // It appears possible that valid MPP8 files can be generated without // this directory, so only process constraints if the directory // exists. // if (consDir != null) { FixFix consFixedData = new FixFix(36, new DocumentInputStream(((DocumentEntry) consDir.getEntry("FixFix 0")))); int count = consFixedData.getItemCount(); for (int loop = 0; loop < count; loop++) { byte[] data = consFixedData.getByteArrayValue(loop); if (MPPUtility.getInt(data, 28) == 0) { int taskID1 = MPPUtility.getInt(data, 12); int taskID2 = MPPUtility.getInt(data, 16); if (taskID1 != taskID2) { Task task1 = m_file.getTaskByUniqueID(Integer.valueOf(taskID1)); Task task2 = m_file.getTaskByUniqueID(Integer.valueOf(taskID2)); if (task1 != null && task2 != null) { RelationType type = RelationType.getInstance(MPPUtility.getShort(data, 20)); TimeUnit durationUnits = MPPUtility.getDurationTimeUnits(MPPUtility.getShort(data, 22)); Duration lag = MPPUtility.getDuration(MPPUtility.getInt(data, 24), durationUnits); Relation relation = task2.addPredecessor(task1, type, lag); m_eventManager.fireRelationReadEvent(relation); } } } } } } /** * This method extracts and collates resource data. * * @throws IOException */ private void processResourceData() throws IOException { DirectoryEntry rscDir = (DirectoryEntry) m_projectDir.getEntry("TBkndRsc"); FixFix rscFixedData = new FixFix(196, new DocumentInputStream(((DocumentEntry) rscDir.getEntry("FixFix 0")))); FixDeferFix rscVarData = null; ExtendedData rscExtData = null; int resources = rscFixedData.getItemCount(); byte[] data; int id; Resource resource; String notes; ProjectCalendar calendar; for (int loop = 0; loop < resources; loop++) { data = rscFixedData.getByteArrayValue(loop); // // Test for a valid unique id // id = MPPUtility.getInt(data, 0); if (id < 1) { continue; } // // Blank rows can be present in MPP files. The following flag // appears to indicate that a row is blank, and should be // ignored. // if ((data[8] & 0x01) != 0) { continue; } // // Test to ensure this resource has not been deleted // This may be an array of bit flags, as per the task // record. I have yet to see data to support this, so // the simple non-zero test remains. // if (MPPUtility.getShort(data, 164) != 0) { continue; } // // Load the var data if we have not already done so // if (rscVarData == null) { rscVarData = new FixDeferFix(new DocumentInputStream(((DocumentEntry) rscDir.getEntry("FixDeferFix 0")))); } rscExtData = new ExtendedData(rscVarData, getOffset(data, 192)); resource = m_file.addResource(); resource.setAccrueAt(AccrueType.getInstance(MPPUtility.getShort(data, 20))); resource.setActualCost(NumberHelper.getDouble(((double) MPPUtility.getLong6(data, 114)) / 100)); resource.setActualOvertimeCost(NumberHelper.getDouble(((double) MPPUtility.getLong6(data, 144)) / 100)); resource.setActualWork(MPPUtility.getDuration(((double) MPPUtility.getLong6(data, 62)) / 100, TimeUnit.HOURS)); resource.setAvailableFrom(MPPUtility.getTimestamp(data, 28)); resource.setAvailableTo(MPPUtility.getTimestamp(data, 32)); //resource.setBaseCalendar(); resource.setBaselineCost(NumberHelper.getDouble(((double) MPPUtility.getLong6(data, 126)) / 100)); resource.setBaselineWork(MPPUtility.getDuration(((double) MPPUtility.getLong6(data, 68)) / 100, TimeUnit.HOURS)); resource.setCode(rscExtData.getUnicodeString(RESOURCE_CODE)); resource.setCost(NumberHelper.getDouble(((double) MPPUtility.getLong6(data, 120)) / 100)); resource.setCost(1, NumberHelper.getDouble(((double) rscExtData.getLong(RESOURCE_COST1)) / 100)); resource.setCost(2, NumberHelper.getDouble(((double) rscExtData.getLong(RESOURCE_COST2)) / 100)); resource.setCost(3, NumberHelper.getDouble(((double) rscExtData.getLong(RESOURCE_COST3)) / 100)); resource.setCost(4, NumberHelper.getDouble(((double) rscExtData.getLong(RESOURCE_COST4)) / 100)); resource.setCost(5, NumberHelper.getDouble(((double) rscExtData.getLong(RESOURCE_COST5)) / 100)); resource.setCost(6, NumberHelper.getDouble(((double) rscExtData.getLong(RESOURCE_COST6)) / 100)); resource.setCost(7, NumberHelper.getDouble(((double) rscExtData.getLong(RESOURCE_COST7)) / 100)); resource.setCost(8, NumberHelper.getDouble(((double) rscExtData.getLong(RESOURCE_COST8)) / 100)); resource.setCost(9, NumberHelper.getDouble(((double) rscExtData.getLong(RESOURCE_COST9)) / 100)); resource.setCost(10, NumberHelper.getDouble(((double) rscExtData.getLong(RESOURCE_COST10)) / 100)); resource.setCostPerUse(NumberHelper.getDouble(((double) MPPUtility.getLong6(data, 80)) / 100)); resource.setDate(1, rscExtData.getTimestamp(RESOURCE_DATE1)); resource.setDate(2, rscExtData.getTimestamp(RESOURCE_DATE2)); resource.setDate(3, rscExtData.getTimestamp(RESOURCE_DATE3)); resource.setDate(4, rscExtData.getTimestamp(RESOURCE_DATE4)); resource.setDate(5, rscExtData.getTimestamp(RESOURCE_DATE5)); resource.setDate(6, rscExtData.getTimestamp(RESOURCE_DATE6)); resource.setDate(7, rscExtData.getTimestamp(RESOURCE_DATE7)); resource.setDate(8, rscExtData.getTimestamp(RESOURCE_DATE8)); resource.setDate(9, rscExtData.getTimestamp(RESOURCE_DATE9)); resource.setDate(10, rscExtData.getTimestamp(RESOURCE_DATE10)); resource.setDuration(1, MPPUtility.getDuration(rscExtData.getInt(RESOURCE_DURATION1), MPPUtility.getDurationTimeUnits(rscExtData.getShort(RESOURCE_DURATION1_UNITS)))); resource.setDuration(2, MPPUtility.getDuration(rscExtData.getInt(RESOURCE_DURATION2), MPPUtility.getDurationTimeUnits(rscExtData.getShort(RESOURCE_DURATION2_UNITS)))); resource.setDuration(3, MPPUtility.getDuration(rscExtData.getInt(RESOURCE_DURATION3), MPPUtility.getDurationTimeUnits(rscExtData.getShort(RESOURCE_DURATION3_UNITS)))); resource.setDuration(4, MPPUtility.getDuration(rscExtData.getInt(RESOURCE_DURATION4), MPPUtility.getDurationTimeUnits(rscExtData.getShort(RESOURCE_DURATION4_UNITS)))); resource.setDuration(5, MPPUtility.getDuration(rscExtData.getInt(RESOURCE_DURATION5), MPPUtility.getDurationTimeUnits(rscExtData.getShort(RESOURCE_DURATION5_UNITS)))); resource.setDuration(6, MPPUtility.getDuration(rscExtData.getInt(RESOURCE_DURATION6), MPPUtility.getDurationTimeUnits(rscExtData.getShort(RESOURCE_DURATION6_UNITS)))); resource.setDuration(7, MPPUtility.getDuration(rscExtData.getInt(RESOURCE_DURATION7), MPPUtility.getDurationTimeUnits(rscExtData.getShort(RESOURCE_DURATION7_UNITS)))); resource.setDuration(8, MPPUtility.getDuration(rscExtData.getInt(RESOURCE_DURATION8), MPPUtility.getDurationTimeUnits(rscExtData.getShort(RESOURCE_DURATION8_UNITS)))); resource.setDuration(9, MPPUtility.getDuration(rscExtData.getInt(RESOURCE_DURATION9), MPPUtility.getDurationTimeUnits(rscExtData.getShort(RESOURCE_DURATION9_UNITS)))); resource.setDuration(10, MPPUtility.getDuration(rscExtData.getInt(RESOURCE_DURATION10), MPPUtility.getDurationTimeUnits(rscExtData.getShort(RESOURCE_DURATION10_UNITS)))); resource.setEmailAddress(rscExtData.getUnicodeString(RESOURCE_EMAIL)); resource.setFinish(1, rscExtData.getTimestamp(RESOURCE_FINISH1)); resource.setFinish(2, rscExtData.getTimestamp(RESOURCE_FINISH2)); resource.setFinish(3, rscExtData.getTimestamp(RESOURCE_FINISH3)); resource.setFinish(4, rscExtData.getTimestamp(RESOURCE_FINISH4)); resource.setFinish(5, rscExtData.getTimestamp(RESOURCE_FINISH5)); resource.setFinish(6, rscExtData.getTimestamp(RESOURCE_FINISH6)); resource.setFinish(7, rscExtData.getTimestamp(RESOURCE_FINISH7)); resource.setFinish(8, rscExtData.getTimestamp(RESOURCE_FINISH8)); resource.setFinish(9, rscExtData.getTimestamp(RESOURCE_FINISH9)); resource.setFinish(10, rscExtData.getTimestamp(RESOURCE_FINISH10)); resource.setGroup(rscExtData.getUnicodeString(RESOURCE_GROUP)); resource.setID(Integer.valueOf(MPPUtility.getInt(data, 4))); resource.setInitials(rscVarData.getUnicodeString(getOffset(data, 160))); //resource.setLinkedFields(); // Calculated value resource.setMaxUnits(NumberHelper.getDouble(((double) MPPUtility.getInt(data, 52)) / 100)); resource.setName(rscVarData.getUnicodeString(getOffset(data, 156))); resource.setNumber(1, NumberHelper.getDouble(rscExtData.getDouble(RESOURCE_NUMBER1))); resource.setNumber(2, NumberHelper.getDouble(rscExtData.getDouble(RESOURCE_NUMBER2))); resource.setNumber(3, NumberHelper.getDouble(rscExtData.getDouble(RESOURCE_NUMBER3))); resource.setNumber(4, NumberHelper.getDouble(rscExtData.getDouble(RESOURCE_NUMBER4))); resource.setNumber(5, NumberHelper.getDouble(rscExtData.getDouble(RESOURCE_NUMBER5))); resource.setNumber(6, NumberHelper.getDouble(rscExtData.getDouble(RESOURCE_NUMBER6))); resource.setNumber(7, NumberHelper.getDouble(rscExtData.getDouble(RESOURCE_NUMBER7))); resource.setNumber(8, NumberHelper.getDouble(rscExtData.getDouble(RESOURCE_NUMBER8))); resource.setNumber(9, NumberHelper.getDouble(rscExtData.getDouble(RESOURCE_NUMBER9))); resource.setNumber(10, NumberHelper.getDouble(rscExtData.getDouble(RESOURCE_NUMBER10))); resource.setNumber(11, NumberHelper.getDouble(rscExtData.getDouble(RESOURCE_NUMBER11))); resource.setNumber(12, NumberHelper.getDouble(rscExtData.getDouble(RESOURCE_NUMBER12))); resource.setNumber(13, NumberHelper.getDouble(rscExtData.getDouble(RESOURCE_NUMBER13))); resource.setNumber(14, NumberHelper.getDouble(rscExtData.getDouble(RESOURCE_NUMBER14))); resource.setNumber(15, NumberHelper.getDouble(rscExtData.getDouble(RESOURCE_NUMBER15))); resource.setNumber(16, NumberHelper.getDouble(rscExtData.getDouble(RESOURCE_NUMBER16))); resource.setNumber(17, NumberHelper.getDouble(rscExtData.getDouble(RESOURCE_NUMBER17))); resource.setNumber(18, NumberHelper.getDouble(rscExtData.getDouble(RESOURCE_NUMBER18))); resource.setNumber(19, NumberHelper.getDouble(rscExtData.getDouble(RESOURCE_NUMBER19))); resource.setNumber(20, NumberHelper.getDouble(rscExtData.getDouble(RESOURCE_NUMBER20))); //resource.setObjects(); // Calculated value //resource.setOverallocated(); // Calculated value resource.setOvertimeCost(NumberHelper.getDouble(((double) MPPUtility.getLong6(data, 138)) / 100)); resource.setOvertimeRate(new Rate(MPPUtility.getDouble(data, 44), TimeUnit.HOURS)); resource.setOvertimeWork(MPPUtility.getDuration(((double) MPPUtility.getLong6(data, 74)) / 100, TimeUnit.HOURS)); resource.setPeakUnits(NumberHelper.getDouble(((double) MPPUtility.getInt(data, 110)) / 100)); //resource.setPercentageWorkComplete(); // Calculated value resource.setRegularWork(MPPUtility.getDuration(((double) MPPUtility.getLong6(data, 92)) / 100, TimeUnit.HOURS)); resource.setRemainingCost(NumberHelper.getDouble(((double) MPPUtility.getLong6(data, 132)) / 100)); resource.setRemainingOvertimeCost(NumberHelper.getDouble(((double) MPPUtility.getLong6(data, 150)) / 100)); resource.setRemainingWork(MPPUtility.getDuration(((double) MPPUtility.getLong6(data, 86)) / 100, TimeUnit.HOURS)); resource.setStandardRate(new Rate(MPPUtility.getDouble(data, 36), TimeUnit.HOURS)); resource.setStart(1, rscExtData.getTimestamp(RESOURCE_START1)); resource.setStart(2, rscExtData.getTimestamp(RESOURCE_START2)); resource.setStart(3, rscExtData.getTimestamp(RESOURCE_START3)); resource.setStart(4, rscExtData.getTimestamp(RESOURCE_START4)); resource.setStart(5, rscExtData.getTimestamp(RESOURCE_START5)); resource.setStart(6, rscExtData.getTimestamp(RESOURCE_START6)); resource.setStart(7, rscExtData.getTimestamp(RESOURCE_START7)); resource.setStart(8, rscExtData.getTimestamp(RESOURCE_START8)); resource.setStart(9, rscExtData.getTimestamp(RESOURCE_START9)); resource.setStart(10, rscExtData.getTimestamp(RESOURCE_START10)); resource.setText(1, rscExtData.getUnicodeString(RESOURCE_TEXT1)); resource.setText(2, rscExtData.getUnicodeString(RESOURCE_TEXT2)); resource.setText(3, rscExtData.getUnicodeString(RESOURCE_TEXT3)); resource.setText(4, rscExtData.getUnicodeString(RESOURCE_TEXT4)); resource.setText(5, rscExtData.getUnicodeString(RESOURCE_TEXT5)); resource.setText(6, rscExtData.getUnicodeString(RESOURCE_TEXT6)); resource.setText(7, rscExtData.getUnicodeString(RESOURCE_TEXT7)); resource.setText(8, rscExtData.getUnicodeString(RESOURCE_TEXT8)); resource.setText(9, rscExtData.getUnicodeString(RESOURCE_TEXT9)); resource.setText(10, rscExtData.getUnicodeString(RESOURCE_TEXT10)); resource.setText(11, rscExtData.getUnicodeString(RESOURCE_TEXT11)); resource.setText(12, rscExtData.getUnicodeString(RESOURCE_TEXT12)); resource.setText(13, rscExtData.getUnicodeString(RESOURCE_TEXT13)); resource.setText(14, rscExtData.getUnicodeString(RESOURCE_TEXT14)); resource.setText(15, rscExtData.getUnicodeString(RESOURCE_TEXT15)); resource.setText(16, rscExtData.getUnicodeString(RESOURCE_TEXT16)); resource.setText(17, rscExtData.getUnicodeString(RESOURCE_TEXT17)); resource.setText(18, rscExtData.getUnicodeString(RESOURCE_TEXT18)); resource.setText(19, rscExtData.getUnicodeString(RESOURCE_TEXT19)); resource.setText(20, rscExtData.getUnicodeString(RESOURCE_TEXT20)); resource.setText(21, rscExtData.getUnicodeString(RESOURCE_TEXT21)); resource.setText(22, rscExtData.getUnicodeString(RESOURCE_TEXT22)); resource.setText(23, rscExtData.getUnicodeString(RESOURCE_TEXT23)); resource.setText(24, rscExtData.getUnicodeString(RESOURCE_TEXT24)); resource.setText(25, rscExtData.getUnicodeString(RESOURCE_TEXT25)); resource.setText(26, rscExtData.getUnicodeString(RESOURCE_TEXT26)); resource.setText(27, rscExtData.getUnicodeString(RESOURCE_TEXT27)); resource.setText(28, rscExtData.getUnicodeString(RESOURCE_TEXT28)); resource.setText(29, rscExtData.getUnicodeString(RESOURCE_TEXT29)); resource.setText(30, rscExtData.getUnicodeString(RESOURCE_TEXT30)); resource.setUniqueID(Integer.valueOf(id)); resource.setWork(MPPUtility.getDuration(((double) MPPUtility.getLong6(data, 56)) / 100, TimeUnit.HOURS)); // // Attach the resource calendar // calendar = m_calendarMap.get(Integer.valueOf(MPPUtility.getInt(data, 24))); resource.setResourceCalendar(calendar); // // Retrieve the resource notes. // notes = rscExtData.getString(RESOURCE_NOTES); if (notes != null) { //claur // if (m_reader.getPreserveNoteFormatting() == false) // { // notes = RtfHelper.strip(notes); // } resource.setNotes(notes); } m_eventManager.fireResourceReadEvent(resource); } } /** * This method extracts and collates resource assignment data. * * @throws IOException */ private void processAssignmentData() throws IOException { DirectoryEntry assnDir = (DirectoryEntry) m_projectDir.getEntry("TBkndAssn"); FixFix assnFixedData = new FixFix(204, new DocumentInputStream(((DocumentEntry) assnDir.getEntry("FixFix 0")))); if (assnFixedData.getDiff() != 0 || (assnFixedData.getSize() % 238 == 0 && testAssignmentTasks(assnFixedData) == false)) { assnFixedData = new FixFix(238, new DocumentInputStream(((DocumentEntry) assnDir.getEntry("FixFix 0")))); } int count = assnFixedData.getItemCount(); FixDeferFix assnVarData = null; for (int loop = 0; loop < count; loop++) { if (assnVarData == null) { assnVarData = new FixDeferFix(new DocumentInputStream(((DocumentEntry) assnDir.getEntry("FixDeferFix 0")))); } byte[] data = assnFixedData.getByteArrayValue(loop); // // Check that the deleted flag isn't set // if (MPPUtility.getByte(data, 168) != 0x02) { Task task = m_file.getTaskByUniqueID(Integer.valueOf(MPPUtility.getInt(data, 16))); Resource resource = m_file.getResourceByUniqueID(Integer.valueOf(MPPUtility.getInt(data, 20))); if (task != null && resource != null) { ResourceAssignment assignment = task.addResourceAssignment(resource); assignment.setActualCost(NumberHelper.getDouble(((double) MPPUtility.getLong6(data, 138)) / 100)); assignment.setActualWork(MPPUtility.getDuration(((double) MPPUtility.getLong6(data, 96)) / 100, TimeUnit.HOURS)); assignment.setCost(NumberHelper.getDouble(((double) MPPUtility.getLong6(data, 132)) / 100)); //assignment.setDelay(); // Not sure what this field maps on to in MSP assignment.setFinish(MPPUtility.getTimestamp(data, 28)); assignment.setOvertimeWork(MPPUtility.getDuration(((double) MPPUtility.getLong6(data, 90)) / 100, TimeUnit.HOURS)); //assignment.setPlannedCost(); // Not sure what this field maps on to in MSP //assignment.setPlannedWork(); // Not sure what this field maps on to in MSP assignment.setRemainingWork(MPPUtility.getDuration(((double) MPPUtility.getLong6(data, 114)) / 100, TimeUnit.HOURS)); assignment.setStart(MPPUtility.getTimestamp(data, 24)); assignment.setUniqueID(Integer.valueOf(MPPUtility.getInt(data, 0))); assignment.setUnits(Double.valueOf(((double) MPPUtility.getShort(data, 80)) / 100)); assignment.setWork(MPPUtility.getDuration(((double) MPPUtility.getLong6(data, 84)) / 100, TimeUnit.HOURS)); m_eventManager.fireAssignmentReadEvent(assignment); } } } } /** * It appears that its is possible for task assignment data blocks to be * one of two sizes, 204 or 238 bytes. In most cases, simply dividing the * overall block size by these values will determine which of these is * the one to use, i.e. the one that returns a remainder of zero. * * Unfortunately it is possible that an overall block size will appear which * can be divided exactly by both of these values. In this case we call this * method to perform a "rule of thumb" test to determine if the selected * block size is correct. From observation it appears that assignment data * will always have a valid resource or task associated with it. If both * values are invalid, then we assume that we are not using the correct * block size. * * As stated above, this is a "rule of thumb" test, and it is quite likely * that we will encounter cases which incorrectly fail this test. We'll * just have to keep looking for a better way to determine the correct * block size! * * @param assnFixedData Task assignment fixed data * @return boolean flag */ private boolean testAssignmentTasks(FixFix assnFixedData) { boolean result = true; int count = assnFixedData.getItemCount(); byte[] data; Task task; Resource resource; for (int loop = 0; loop < count; loop++) { data = assnFixedData.getByteArrayValue(loop); task = m_file.getTaskByUniqueID(Integer.valueOf(MPPUtility.getInt(data, 16))); resource = m_file.getResourceByUniqueID(Integer.valueOf(MPPUtility.getInt(data, 20))); if (task == null && resource == null) { result = false; break; } } return (result); } /** * This method extracts view data from the MPP file. * * @throws IOException */ private void processViewData() throws IOException { DirectoryEntry dir = (DirectoryEntry) m_viewDir.getEntry("CV_iew"); FixFix ff = new FixFix(138, new DocumentInputStream(((DocumentEntry) dir.getEntry("FixFix 0")))); int items = ff.getItemCount(); byte[] data; View view; for (int loop = 0; loop < items; loop++) { data = ff.getByteArrayValue(loop); view = new View8(m_file, data); m_file.getViews().add(view); } } /** * This method extracts table data from the MPP file. * * @throws IOException */ private void processTableData() throws IOException { DirectoryEntry dir = (DirectoryEntry) m_viewDir.getEntry("CTable"); FixFix ff = new FixFix(126, new DocumentInputStream(((DocumentEntry) dir.getEntry("FixFix 0")))); FixDeferFix fdf = new FixDeferFix(new DocumentInputStream(((DocumentEntry) dir.getEntry("FixDeferFix 0")))); int items = ff.getItemCount(); StringBuilder sb = new StringBuilder(); TableContainer container = m_file.getTables(); for (int loop = 0; loop < items; loop++) { byte[] data = ff.getByteArrayValue(loop); Table table = new Table(); table.setID(MPPUtility.getInt(data, 0)); String name = MPPUtility.getUnicodeString(data, 4); if (name.indexOf('&') != -1) { sb.setLength(0); int index = 0; char c; while (index < name.length()) { c = name.charAt(index); if (c != '&') { sb.append(c); } ++index; } name = sb.toString(); } table.setName(MPPUtility.removeAmpersands(name)); container.add(table); byte[] extendedData = fdf.getByteArray(getOffset(data, 122)); if (extendedData != null) { byte[] columnData = fdf.getByteArray(getOffset(extendedData, 8)); processColumnData(table, columnData); } //System.out.println(table); } } /** * This method processes the column data associated with the * current table. * * @param table current table * @param data raw column data */ private void processColumnData(Table table, byte[] data) { int columnCount = MPPUtility.getShort(data, 4) + 1; int index = 8; int columnTitleOffset; Column column; int alignment; for (int loop = 0; loop < columnCount; loop++) { column = new Column(m_file); if (loop == 0) { if (MPPUtility.getShort(data, index) == 0) { table.setResourceFlag(true); } else { table.setResourceFlag(false); } } if (table.getResourceFlag() == false) { column.setFieldType(MPPTaskField.getInstance(MPPUtility.getShort(data, index))); } else { column.setFieldType(MPPResourceField.getInstance(MPPUtility.getShort(data, index))); } column.setWidth(MPPUtility.getByte(data, index + 4)); columnTitleOffset = MPPUtility.getShort(data, index + 6); if (columnTitleOffset != 0) { column.setTitle(MPPUtility.getUnicodeString(data, columnTitleOffset)); } alignment = MPPUtility.getByte(data, index + 8); if (alignment == 32) { column.setAlignTitle(Column.ALIGN_LEFT); } else { if (alignment == 33) { column.setAlignTitle(Column.ALIGN_CENTER); } else { column.setAlignTitle(Column.ALIGN_RIGHT); } } alignment = MPPUtility.getByte(data, index + 10); if (alignment == 32) { column.setAlignData(Column.ALIGN_LEFT); } else { if (alignment == 33) { column.setAlignData(Column.ALIGN_CENTER); } else { column.setAlignData(Column.ALIGN_RIGHT); } } table.addColumn(column); index += 12; } } /** * This method is used to extract a value from a fixed data block, * which represents an offset into a variable data block. * * @param data Fixed data block * @param offset Offset in fixed data block * @return Offset in var data block */ private int getOffset(byte[] data, int offset) { return (-1 - MPPUtility.getInt(data, offset)); } // private static void dumpUnknownData (String name, int[][] spec, byte[] data) // { // System.out.println (name); // for (int loop=0; loop < spec.length; loop++) // { // System.out.println (spec[loop][0] + ": "+ MPPUtility.hexdump(data, spec[loop][0], spec[loop][1], false)); // } // System.out.println (); // } // // private static final int[][] UNKNOWN_TASK_DATA = new int[][] // { // {8, 12}, // includes known flags // {36, 12}, // {50, 18}, // {86, 2}, // {142, 2}, // {144, 4}, // {148, 4}, // {152, 4}, // {164, 4}, // {268, 4}, // includes known flags // {274, 32}, // includes known flags // {306, 6} // }; // // private static final int[][] UNKNOWN_CALENDAR_DATA = new int[][] // { // {8, 12}, // {24, 8} // }; // // private static final int[][] UNKNOWN_ASSIGNMENT_DATA = new int[][] // { // {4, 12}, // {32, 79}, // {82, 2}, // {102, 6}, // {108, 6}, // {120, 12}, // {102, 6}, // {144, 12}, // {162, 42} // }; private MPPReader m_reader; private ProjectFile m_file; private EventManager m_eventManager; private HashMap<Integer, ProjectCalendar> m_calendarMap; private DirectoryEntry m_root; private DirectoryEntry m_projectDir; private DirectoryEntry m_viewDir; /** * Task data types. */ private static final Integer TASK_WBS = Integer.valueOf(104); private static final Integer TASK_CONTACT = Integer.valueOf(105); private static final Integer TASK_TEXT1 = Integer.valueOf(106); private static final Integer TASK_TEXT2 = Integer.valueOf(107); private static final Integer TASK_TEXT3 = Integer.valueOf(108); private static final Integer TASK_TEXT4 = Integer.valueOf(109); private static final Integer TASK_TEXT5 = Integer.valueOf(110); private static final Integer TASK_TEXT6 = Integer.valueOf(111); private static final Integer TASK_TEXT7 = Integer.valueOf(112); private static final Integer TASK_TEXT8 = Integer.valueOf(113); private static final Integer TASK_TEXT9 = Integer.valueOf(114); private static final Integer TASK_TEXT10 = Integer.valueOf(115); private static final Integer TASK_START1 = Integer.valueOf(116); private static final Integer TASK_FINISH1 = Integer.valueOf(117); private static final Integer TASK_START2 = Integer.valueOf(118); private static final Integer TASK_FINISH2 = Integer.valueOf(119); private static final Integer TASK_START3 = Integer.valueOf(120); private static final Integer TASK_FINISH3 = Integer.valueOf(121); private static final Integer TASK_START4 = Integer.valueOf(122); private static final Integer TASK_FINISH4 = Integer.valueOf(123); private static final Integer TASK_START5 = Integer.valueOf(124); private static final Integer TASK_FINISH5 = Integer.valueOf(125); private static final Integer TASK_START6 = Integer.valueOf(126); private static final Integer TASK_FINISH6 = Integer.valueOf(127); private static final Integer TASK_START7 = Integer.valueOf(128); private static final Integer TASK_FINISH7 = Integer.valueOf(129); private static final Integer TASK_START8 = Integer.valueOf(130); private static final Integer TASK_FINISH8 = Integer.valueOf(131); private static final Integer TASK_START9 = Integer.valueOf(132); private static final Integer TASK_FINISH9 = Integer.valueOf(133); private static final Integer TASK_START10 = Integer.valueOf(134); private static final Integer TASK_FINISH10 = Integer.valueOf(135); private static final Integer TASK_NUMBER1 = Integer.valueOf(137); private static final Integer TASK_NUMBER2 = Integer.valueOf(138); private static final Integer TASK_NUMBER3 = Integer.valueOf(139); private static final Integer TASK_NUMBER4 = Integer.valueOf(140); private static final Integer TASK_NUMBER5 = Integer.valueOf(141); private static final Integer TASK_NUMBER6 = Integer.valueOf(142); private static final Integer TASK_NUMBER7 = Integer.valueOf(143); private static final Integer TASK_NUMBER8 = Integer.valueOf(144); private static final Integer TASK_NUMBER9 = Integer.valueOf(145); private static final Integer TASK_NUMBER10 = Integer.valueOf(146); private static final Integer TASK_DURATION1 = Integer.valueOf(147); private static final Integer TASK_DURATION1_UNITS = Integer.valueOf(148); private static final Integer TASK_DURATION2 = Integer.valueOf(149); private static final Integer TASK_DURATION2_UNITS = Integer.valueOf(150); private static final Integer TASK_DURATION3 = Integer.valueOf(151); private static final Integer TASK_DURATION3_UNITS = Integer.valueOf(152); private static final Integer TASK_DURATION4 = Integer.valueOf(153); private static final Integer TASK_DURATION4_UNITS = Integer.valueOf(154); private static final Integer TASK_DURATION5 = Integer.valueOf(155); private static final Integer TASK_DURATION5_UNITS = Integer.valueOf(156); private static final Integer TASK_DURATION6 = Integer.valueOf(157); private static final Integer TASK_DURATION6_UNITS = Integer.valueOf(158); private static final Integer TASK_DURATION7 = Integer.valueOf(159); private static final Integer TASK_DURATION7_UNITS = Integer.valueOf(160); private static final Integer TASK_DURATION8 = Integer.valueOf(161); private static final Integer TASK_DURATION8_UNITS = Integer.valueOf(162); private static final Integer TASK_DURATION9 = Integer.valueOf(163); private static final Integer TASK_DURATION9_UNITS = Integer.valueOf(164); private static final Integer TASK_DURATION10 = Integer.valueOf(165); private static final Integer TASK_DURATION10_UNITS = Integer.valueOf(166); private static final Integer TASK_RECURRING_DATA = Integer.valueOf(168); private static final Integer TASK_DATE1 = Integer.valueOf(174); private static final Integer TASK_DATE2 = Integer.valueOf(175); private static final Integer TASK_DATE3 = Integer.valueOf(176); private static final Integer TASK_DATE4 = Integer.valueOf(177); private static final Integer TASK_DATE5 = Integer.valueOf(178); private static final Integer TASK_DATE6 = Integer.valueOf(179); private static final Integer TASK_DATE7 = Integer.valueOf(180); private static final Integer TASK_DATE8 = Integer.valueOf(181); private static final Integer TASK_DATE9 = Integer.valueOf(182); private static final Integer TASK_DATE10 = Integer.valueOf(183); private static final Integer TASK_TEXT11 = Integer.valueOf(184); private static final Integer TASK_TEXT12 = Integer.valueOf(185); private static final Integer TASK_TEXT13 = Integer.valueOf(186); private static final Integer TASK_TEXT14 = Integer.valueOf(187); private static final Integer TASK_TEXT15 = Integer.valueOf(188); private static final Integer TASK_TEXT16 = Integer.valueOf(189); private static final Integer TASK_TEXT17 = Integer.valueOf(190); private static final Integer TASK_TEXT18 = Integer.valueOf(191); private static final Integer TASK_TEXT19 = Integer.valueOf(192); private static final Integer TASK_TEXT20 = Integer.valueOf(193); private static final Integer TASK_TEXT21 = Integer.valueOf(194); private static final Integer TASK_TEXT22 = Integer.valueOf(195); private static final Integer TASK_TEXT23 = Integer.valueOf(196); private static final Integer TASK_TEXT24 = Integer.valueOf(197); private static final Integer TASK_TEXT25 = Integer.valueOf(198); private static final Integer TASK_TEXT26 = Integer.valueOf(199); private static final Integer TASK_TEXT27 = Integer.valueOf(200); private static final Integer TASK_TEXT28 = Integer.valueOf(201); private static final Integer TASK_TEXT29 = Integer.valueOf(202); private static final Integer TASK_TEXT30 = Integer.valueOf(203); private static final Integer TASK_NUMBER11 = Integer.valueOf(204); private static final Integer TASK_NUMBER12 = Integer.valueOf(205); private static final Integer TASK_NUMBER13 = Integer.valueOf(206); private static final Integer TASK_NUMBER14 = Integer.valueOf(207); private static final Integer TASK_NUMBER15 = Integer.valueOf(208); private static final Integer TASK_NUMBER16 = Integer.valueOf(209); private static final Integer TASK_NUMBER17 = Integer.valueOf(210); private static final Integer TASK_NUMBER18 = Integer.valueOf(211); private static final Integer TASK_NUMBER19 = Integer.valueOf(212); private static final Integer TASK_NUMBER20 = Integer.valueOf(213); private static final Integer TASK_HYPERLINK = Integer.valueOf(236); private static final Integer TASK_COST1 = Integer.valueOf(237); private static final Integer TASK_COST2 = Integer.valueOf(238); private static final Integer TASK_COST3 = Integer.valueOf(239); private static final Integer TASK_COST4 = Integer.valueOf(240); private static final Integer TASK_COST5 = Integer.valueOf(241); private static final Integer TASK_COST6 = Integer.valueOf(242); private static final Integer TASK_COST7 = Integer.valueOf(243); private static final Integer TASK_COST8 = Integer.valueOf(244); private static final Integer TASK_COST9 = Integer.valueOf(245); private static final Integer TASK_COST10 = Integer.valueOf(246); private static final Integer TASK_NOTES = Integer.valueOf(247); /** * Resource data types. */ private static final Integer RESOURCE_GROUP = Integer.valueOf(61); private static final Integer RESOURCE_CODE = Integer.valueOf(62); private static final Integer RESOURCE_EMAIL = Integer.valueOf(63); private static final Integer RESOURCE_TEXT1 = Integer.valueOf(64); private static final Integer RESOURCE_TEXT2 = Integer.valueOf(65); private static final Integer RESOURCE_TEXT3 = Integer.valueOf(66); private static final Integer RESOURCE_TEXT4 = Integer.valueOf(67); private static final Integer RESOURCE_TEXT5 = Integer.valueOf(68); private static final Integer RESOURCE_TEXT6 = Integer.valueOf(69); private static final Integer RESOURCE_TEXT7 = Integer.valueOf(70); private static final Integer RESOURCE_TEXT8 = Integer.valueOf(71); private static final Integer RESOURCE_TEXT9 = Integer.valueOf(72); private static final Integer RESOURCE_TEXT10 = Integer.valueOf(73); private static final Integer RESOURCE_TEXT11 = Integer.valueOf(74); private static final Integer RESOURCE_TEXT12 = Integer.valueOf(75); private static final Integer RESOURCE_TEXT13 = Integer.valueOf(76); private static final Integer RESOURCE_TEXT14 = Integer.valueOf(77); private static final Integer RESOURCE_TEXT15 = Integer.valueOf(78); private static final Integer RESOURCE_TEXT16 = Integer.valueOf(79); private static final Integer RESOURCE_TEXT17 = Integer.valueOf(80); private static final Integer RESOURCE_TEXT18 = Integer.valueOf(81); private static final Integer RESOURCE_TEXT19 = Integer.valueOf(82); private static final Integer RESOURCE_TEXT20 = Integer.valueOf(83); private static final Integer RESOURCE_TEXT21 = Integer.valueOf(84); private static final Integer RESOURCE_TEXT22 = Integer.valueOf(85); private static final Integer RESOURCE_TEXT23 = Integer.valueOf(86); private static final Integer RESOURCE_TEXT24 = Integer.valueOf(87); private static final Integer RESOURCE_TEXT25 = Integer.valueOf(88); private static final Integer RESOURCE_TEXT26 = Integer.valueOf(89); private static final Integer RESOURCE_TEXT27 = Integer.valueOf(90); private static final Integer RESOURCE_TEXT28 = Integer.valueOf(91); private static final Integer RESOURCE_TEXT29 = Integer.valueOf(92); private static final Integer RESOURCE_TEXT30 = Integer.valueOf(93); private static final Integer RESOURCE_START1 = Integer.valueOf(94); private static final Integer RESOURCE_START2 = Integer.valueOf(95); private static final Integer RESOURCE_START3 = Integer.valueOf(96); private static final Integer RESOURCE_START4 = Integer.valueOf(97); private static final Integer RESOURCE_START5 = Integer.valueOf(98); private static final Integer RESOURCE_START6 = Integer.valueOf(99); private static final Integer RESOURCE_START7 = Integer.valueOf(100); private static final Integer RESOURCE_START8 = Integer.valueOf(101); private static final Integer RESOURCE_START9 = Integer.valueOf(102); private static final Integer RESOURCE_START10 = Integer.valueOf(103); private static final Integer RESOURCE_FINISH1 = Integer.valueOf(104); private static final Integer RESOURCE_FINISH2 = Integer.valueOf(105); private static final Integer RESOURCE_FINISH3 = Integer.valueOf(106); private static final Integer RESOURCE_FINISH4 = Integer.valueOf(107); private static final Integer RESOURCE_FINISH5 = Integer.valueOf(108); private static final Integer RESOURCE_FINISH6 = Integer.valueOf(109); private static final Integer RESOURCE_FINISH7 = Integer.valueOf(110); private static final Integer RESOURCE_FINISH8 = Integer.valueOf(111); private static final Integer RESOURCE_FINISH9 = Integer.valueOf(112); private static final Integer RESOURCE_FINISH10 = Integer.valueOf(113); private static final Integer RESOURCE_NUMBER1 = Integer.valueOf(114); private static final Integer RESOURCE_NUMBER2 = Integer.valueOf(115); private static final Integer RESOURCE_NUMBER3 = Integer.valueOf(116); private static final Integer RESOURCE_NUMBER4 = Integer.valueOf(117); private static final Integer RESOURCE_NUMBER5 = Integer.valueOf(118); private static final Integer RESOURCE_NUMBER6 = Integer.valueOf(119); private static final Integer RESOURCE_NUMBER7 = Integer.valueOf(120); private static final Integer RESOURCE_NUMBER8 = Integer.valueOf(121); private static final Integer RESOURCE_NUMBER9 = Integer.valueOf(122); private static final Integer RESOURCE_NUMBER10 = Integer.valueOf(123); private static final Integer RESOURCE_NUMBER11 = Integer.valueOf(124); private static final Integer RESOURCE_NUMBER12 = Integer.valueOf(125); private static final Integer RESOURCE_NUMBER13 = Integer.valueOf(126); private static final Integer RESOURCE_NUMBER14 = Integer.valueOf(127); private static final Integer RESOURCE_NUMBER15 = Integer.valueOf(128); private static final Integer RESOURCE_NUMBER16 = Integer.valueOf(129); private static final Integer RESOURCE_NUMBER17 = Integer.valueOf(130); private static final Integer RESOURCE_NUMBER18 = Integer.valueOf(131); private static final Integer RESOURCE_NUMBER19 = Integer.valueOf(132); private static final Integer RESOURCE_NUMBER20 = Integer.valueOf(133); private static final Integer RESOURCE_DURATION1 = Integer.valueOf(134); private static final Integer RESOURCE_DURATION2 = Integer.valueOf(135); private static final Integer RESOURCE_DURATION3 = Integer.valueOf(136); private static final Integer RESOURCE_DURATION4 = Integer.valueOf(137); private static final Integer RESOURCE_DURATION5 = Integer.valueOf(138); private static final Integer RESOURCE_DURATION6 = Integer.valueOf(139); private static final Integer RESOURCE_DURATION7 = Integer.valueOf(140); private static final Integer RESOURCE_DURATION8 = Integer.valueOf(141); private static final Integer RESOURCE_DURATION9 = Integer.valueOf(142); private static final Integer RESOURCE_DURATION10 = Integer.valueOf(143); private static final Integer RESOURCE_DURATION1_UNITS = Integer.valueOf(144); private static final Integer RESOURCE_DURATION2_UNITS = Integer.valueOf(145); private static final Integer RESOURCE_DURATION3_UNITS = Integer.valueOf(146); private static final Integer RESOURCE_DURATION4_UNITS = Integer.valueOf(147); private static final Integer RESOURCE_DURATION5_UNITS = Integer.valueOf(148); private static final Integer RESOURCE_DURATION6_UNITS = Integer.valueOf(149); private static final Integer RESOURCE_DURATION7_UNITS = Integer.valueOf(150); private static final Integer RESOURCE_DURATION8_UNITS = Integer.valueOf(151); private static final Integer RESOURCE_DURATION9_UNITS = Integer.valueOf(152); private static final Integer RESOURCE_DURATION10_UNITS = Integer.valueOf(153); private static final Integer RESOURCE_DATE1 = Integer.valueOf(157); private static final Integer RESOURCE_DATE2 = Integer.valueOf(158); private static final Integer RESOURCE_DATE3 = Integer.valueOf(159); private static final Integer RESOURCE_DATE4 = Integer.valueOf(160); private static final Integer RESOURCE_DATE5 = Integer.valueOf(161); private static final Integer RESOURCE_DATE6 = Integer.valueOf(162); private static final Integer RESOURCE_DATE7 = Integer.valueOf(163); private static final Integer RESOURCE_DATE8 = Integer.valueOf(164); private static final Integer RESOURCE_DATE9 = Integer.valueOf(165); private static final Integer RESOURCE_DATE10 = Integer.valueOf(166); private static final Integer RESOURCE_NOTES = Integer.valueOf(169); private static final Integer RESOURCE_COST1 = Integer.valueOf(170); private static final Integer RESOURCE_COST2 = Integer.valueOf(171); private static final Integer RESOURCE_COST3 = Integer.valueOf(172); private static final Integer RESOURCE_COST4 = Integer.valueOf(173); private static final Integer RESOURCE_COST5 = Integer.valueOf(174); private static final Integer RESOURCE_COST6 = Integer.valueOf(175); private static final Integer RESOURCE_COST7 = Integer.valueOf(176); private static final Integer RESOURCE_COST8 = Integer.valueOf(177); private static final Integer RESOURCE_COST9 = Integer.valueOf(178); private static final Integer RESOURCE_COST10 = Integer.valueOf(179); /** * Default working week. */ private static final boolean[] DEFAULT_WORKING_WEEK = { false, true, true, true, true, true, false }; }