/*
* file: GraphicalIndicatorReader.java
* author: Jon Iles
* copyright: (c) Packwood Software 2006
* date: 16-Feb-2006
*/
/*
* 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.util.Date;
import net.sf.mpxj.CustomFieldContainer;
import net.sf.mpxj.Duration;
import net.sf.mpxj.FieldType;
import net.sf.mpxj.GraphicalIndicator;
import net.sf.mpxj.GraphicalIndicatorCriteria;
import net.sf.mpxj.ProjectProperties;
import net.sf.mpxj.TestOperator;
import net.sf.mpxj.common.FieldTypeHelper;
import net.sf.mpxj.common.MPPResourceField;
import net.sf.mpxj.common.MPPTaskField;
/**
* This class allows graphical indicator definitions to be read from an MPP
* file.
*/
public final class GraphicalIndicatorReader
{
/**
* The main entry point for processing graphical indicator definitions.
*
* @param indicators graphical indicators container
* @param properties project properties
* @param props properties data
*/
public void process(CustomFieldContainer indicators, ProjectProperties properties, Props props)
{
m_container = indicators;
m_properties = properties;
m_data = props.getByteArray(Props.TASK_FIELD_ATTRIBUTES);
if (m_data != null)
{
int columnsCount = MPPUtility.getInt(m_data, 4);
m_headerOffset = 8;
for (int loop = 0; loop < columnsCount; loop++)
{
processColumns();
}
}
}
/**
* Processes graphical indicator definitions for each column.
*/
private void processColumns()
{
int fieldType = MPPUtility.getShort(m_data, m_headerOffset);
m_headerOffset += 2;
// unknown bytes
m_headerOffset += 1;
int entityType = MPPUtility.getByte(m_data, m_headerOffset);
m_headerOffset += 1;
m_dataOffset = MPPUtility.getInt(m_data, m_headerOffset);
m_headerOffset += 4;
FieldType type = null;
switch (entityType)
{
case 0x0B:
{
type = MPPTaskField.getInstance(fieldType);
break;
}
case 0x0C:
{
type = MPPResourceField.getInstance(fieldType);
break;
}
}
//System.out.println("Header: " + type);
//System.out.println(MPPUtility.hexdump(m_data, m_dataOffset, 36, false, 16, ""));
GraphicalIndicator indicator = m_container.getCustomField(type).getGraphicalIndicator();
indicator.setFieldType(type);
int flags = m_data[m_dataOffset];
indicator.setProjectSummaryInheritsFromSummaryRows((flags & 0x08) != 0);
indicator.setSummaryRowsInheritFromNonSummaryRows((flags & 0x04) != 0);
indicator.setDisplayGraphicalIndicators((flags & 0x02) != 0);
indicator.setShowDataValuesInToolTips((flags & 0x01) != 0);
m_dataOffset += 20;
int nonSummaryRowOffset = MPPUtility.getInt(m_data, m_dataOffset) - 36;
m_dataOffset += 4;
int summaryRowOffset = MPPUtility.getInt(m_data, m_dataOffset) - 36;
m_dataOffset += 4;
int projectSummaryOffset = MPPUtility.getInt(m_data, m_dataOffset) - 36;
m_dataOffset += 4;
int dataSize = MPPUtility.getInt(m_data, m_dataOffset) - 36;
m_dataOffset += 4;
//System.out.println("Data");
//System.out.println(MPPUtility.hexdump(m_data, m_dataOffset, dataSize, false, 16, ""));
int maxNonSummaryRowOffset = m_dataOffset + summaryRowOffset;
int maxSummaryRowOffset = m_dataOffset + projectSummaryOffset;
int maxProjectSummaryOffset = m_dataOffset + dataSize;
m_dataOffset += nonSummaryRowOffset;
while (m_dataOffset + 2 < maxNonSummaryRowOffset)
{
indicator.addNonSummaryRowCriteria(processCriteria(type));
}
while (m_dataOffset + 2 < maxSummaryRowOffset)
{
indicator.addSummaryRowCriteria(processCriteria(type));
}
while (m_dataOffset + 2 < maxProjectSummaryOffset)
{
indicator.addProjectSummaryCriteria(processCriteria(type));
}
}
/**
* Process the graphical indicator criteria for a single column.
*
* @param type field type
* @return indicator criteria data
*/
private GraphicalIndicatorCriteria processCriteria(FieldType type)
{
GraphicalIndicatorCriteria criteria = new GraphicalIndicatorCriteria(m_properties);
criteria.setLeftValue(type);
int indicatorType = MPPUtility.getInt(m_data, m_dataOffset);
m_dataOffset += 4;
criteria.setIndicator(indicatorType);
if (m_dataOffset + 4 < m_data.length)
{
int operatorValue = MPPUtility.getInt(m_data, m_dataOffset);
m_dataOffset += 4;
TestOperator operator = (operatorValue == 0 ? TestOperator.IS_ANY_VALUE : TestOperator.getInstance(operatorValue - 0x3E7));
criteria.setOperator(operator);
if (operator != TestOperator.IS_ANY_VALUE)
{
processOperandValue(0, type, criteria);
if (operator == TestOperator.IS_WITHIN || operator == TestOperator.IS_NOT_WITHIN)
{
processOperandValue(1, type, criteria);
}
}
}
return (criteria);
}
/**
* Process an operand value used in the definition of the graphical
* indicator criteria.
*
* @param index position in operand list
* @param type field type
* @param criteria indicator criteria
*/
private void processOperandValue(int index, FieldType type, GraphicalIndicatorCriteria criteria)
{
boolean valueFlag = (MPPUtility.getInt(m_data, m_dataOffset) == 1);
m_dataOffset += 4;
if (valueFlag == false)
{
int fieldID = MPPUtility.getInt(m_data, m_dataOffset);
criteria.setRightValue(index, FieldTypeHelper.getInstance(fieldID));
m_dataOffset += 4;
}
else
{
//int dataTypeValue = MPPUtility.getShort(m_data, m_dataOffset);
m_dataOffset += 2;
switch (type.getDataType())
{
case DURATION: // 0x03
{
Duration value = MPPUtility.getAdjustedDuration(m_properties, MPPUtility.getInt(m_data, m_dataOffset), MPPUtility.getDurationTimeUnits(MPPUtility.getShort(m_data, m_dataOffset + 4)));
m_dataOffset += 6;
criteria.setRightValue(index, value);
break;
}
case NUMERIC: // 0x05
{
Double value = Double.valueOf(MPPUtility.getDouble(m_data, m_dataOffset));
m_dataOffset += 8;
criteria.setRightValue(index, value);
break;
}
case CURRENCY: // 0x06
{
Double value = Double.valueOf(MPPUtility.getDouble(m_data, m_dataOffset) / 100);
m_dataOffset += 8;
criteria.setRightValue(index, value);
break;
}
case STRING: // 0x08
{
String value = MPPUtility.getUnicodeString(m_data, m_dataOffset);
m_dataOffset += ((value.length() + 1) * 2);
criteria.setRightValue(index, value);
break;
}
case BOOLEAN: // 0x0B
{
int value = MPPUtility.getShort(m_data, m_dataOffset);
m_dataOffset += 2;
criteria.setRightValue(index, value == 1 ? Boolean.TRUE : Boolean.FALSE);
break;
}
case DATE: // 0x13
{
Date value = MPPUtility.getTimestamp(m_data, m_dataOffset);
m_dataOffset += 4;
criteria.setRightValue(index, value);
break;
}
default:
{
break;
}
}
}
}
private byte[] m_data;
private int m_headerOffset;
private int m_dataOffset;
private CustomFieldContainer m_container;
private ProjectProperties m_properties;
}