package net.sf.mpxj.mpp;
import java.io.FileNotFoundException;
import java.io.IOException;
import net.sf.mpxj.Duration;
import net.sf.mpxj.EventManager;
import net.sf.mpxj.ProjectFile;
import net.sf.mpxj.ProjectProperties;
import net.sf.mpxj.Relation;
import net.sf.mpxj.RelationType;
import net.sf.mpxj.Task;
import net.sf.mpxj.TimeUnit;
import net.sf.mpxj.common.NumberHelper;
import org.apache.poi.poifs.filesystem.DirectoryEntry;
import org.apache.poi.poifs.filesystem.DocumentEntry;
import org.apache.poi.poifs.filesystem.DocumentInputStream;
/**
* Common implementation detail to extract task constraint data from
* MPP9, MPP12, and MPP14 files.
*/
public class ConstraintFactory
{
/**
* Main entry point when called to process constraint data.
*
* @param projectDir project directory
* @param file parent project file
* @param inputStreamFactory factory to create input stream
*/
public void process(DirectoryEntry projectDir, ProjectFile file, DocumentInputStreamFactory inputStreamFactory) throws IOException
{
DirectoryEntry consDir;
try
{
consDir = (DirectoryEntry) projectDir.getEntry("TBkndCons");
}
catch (FileNotFoundException ex)
{
consDir = null;
}
if (consDir != null)
{
FixedMeta consFixedMeta = new FixedMeta(new DocumentInputStream(((DocumentEntry) consDir.getEntry("FixedMeta"))), 10);
FixedData consFixedData = new FixedData(consFixedMeta, 20, inputStreamFactory.getInstance(consDir, "FixedData"));
// FixedMeta consFixed2Meta = new FixedMeta(new DocumentInputStream(((DocumentEntry) consDir.getEntry("Fixed2Meta"))), 9);
// FixedData consFixed2Data = new FixedData(consFixed2Meta, 48, getEncryptableInputStream(consDir, "Fixed2Data"));
int count = consFixedMeta.getAdjustedItemCount();
int lastConstraintID = -1;
ProjectProperties properties = file.getProjectProperties();
EventManager eventManager = file.getEventManager();
boolean project15 = NumberHelper.getInt(properties.getMppFileType()) == 14 && properties.getFullApplicationName().equals("Microsoft.Project 15.0");
int durationUnitsOffset = project15 ? 18 : 14;
int durationOffset = project15 ? 14 : 16;
for (int loop = 0; loop < count; loop++)
{
byte[] metaData = consFixedMeta.getByteArrayValue(loop);
//
// SourceForge bug 2209477: we were reading an int here, but
// it looks like the deleted flag is just a short.
//
if (MPPUtility.getShort(metaData, 0) == 0)
{
int index = consFixedData.getIndexFromOffset(MPPUtility.getInt(metaData, 4));
if (index != -1)
{
// byte[] metaData2 = consFixed2Meta.getByteArrayValue(loop);
// int index2 = consFixed2Data.getIndexFromOffset(MPPUtility.getInt(metaData2, 4));
// byte[] data2 = consFixed2Data.getByteArrayValue(index2);
byte[] data = consFixedData.getByteArrayValue(index);
int constraintID = MPPUtility.getInt(data, 0);
if (constraintID > lastConstraintID)
{
lastConstraintID = constraintID;
int taskID1 = MPPUtility.getInt(data, 4);
int taskID2 = MPPUtility.getInt(data, 8);
if (taskID1 != taskID2)
{
Task task1 = file.getTaskByUniqueID(Integer.valueOf(taskID1));
Task task2 = file.getTaskByUniqueID(Integer.valueOf(taskID2));
if (task1 != null && task2 != null)
{
RelationType type = RelationType.getInstance(MPPUtility.getShort(data, 12));
TimeUnit durationUnits = MPPUtility.getDurationTimeUnits(MPPUtility.getShort(data, durationUnitsOffset));
Duration lag = MPPUtility.getAdjustedDuration(properties, MPPUtility.getInt(data, durationOffset), durationUnits);
Relation relation = task2.addPredecessor(task1, type, lag);
eventManager.fireRelationReadEvent(relation);
}
}
}
}
}
}
}
}
}