src.com.ibm.as400.data.PcmlStruct Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jt400-jdk8 Show documentation
Show all versions of jt400-jdk8 Show documentation
The Open Source version of the IBM Toolbox for Java
///////////////////////////////////////////////////////////////////////////////
//
// JTOpen (IBM Toolbox for Java - OSS version)
//
// Filename: PcmlStruct.java
//
// The source code contained herein is licensed under the IBM Public License
// Version 1.0, which has been approved by the Open Source Initiative.
// Copyright (C) 1997-2003 International Business Machines Corporation and
// others. All rights reserved.
//
///////////////////////////////////////////////////////////////////////////////
package com.ibm.as400.data;
import com.ibm.as400.access.ProgramParameter;
import java.util.Enumeration;
import java.util.Hashtable;
import java.io.OutputStream;
class PcmlStruct extends PcmlDocNode
{
/***********************************************************
Static Members
***********************************************************/
// Serial verion unique identifier
static final long serialVersionUID = 5539999574454926624L;
private static final String STRUCTATTRIBUTES[] = {
"name",
"usage",
"count",
"minvrm",
"maxvrm",
"offset",
"offsetfrom",
"outputsize"
};
private static final int VERSION_1_ATTRIBUTE_COUNT = 8;
/***********************************************************
Instance Members
***********************************************************/
// The "m_name" and "m_usage" attributes are implemented by PcmlDocNode
// The following values are implemented by PcmlData and PcmlStruct
private int m_Count; // count=, integer literal
private String m_CountId; // count=, element name
private int m_Offset; // offset=, integer literal
private String m_OffsetId; // offset=, element name
private boolean m_OffsetfromFixed; // Flag indicating whether serialized version @A1A
// of this object contains fix for offsetfrom
private int m_Offsetfrom; // offsetfrom=, integer literal @A1A
private String m_OffsetfromId; // offsetfrom=, element name
private String m_Minvrm; // minvrm=, string literal
private int m_MinvrmInt; // minvrm=, from AS400.generateVRM()
private String m_Maxvrm; // maxvrm=, string literal
private int m_MaxvrmInt; // maxvrm=, from AS400.generateVRM()
private int m_Outputsize; // outputsize=, integer literal
private String m_OutputsizeId; // outputsize=, element name
// Default constructor
PcmlStruct()
{
}
// Constructor
public PcmlStruct(PcmlAttributeList attrs) // @C1C
{
super(attrs); // @C1C
setNodeType(PcmlNodeType.STRUCT); // @C1A
// **********************************
// Set attribute values
//
// The following code extracts the attribute values
// from the parsed document node and
// stores the values in private data members.
// **********************************
// Set count= attribute value
setCount(getAttributeValue("count"));
// Set offset= attribute value
setOffset(getAttributeValue("offset"));
// Set offsetfrom= attribute value
setOffsetfrom(getAttributeValue("offsetfrom"));
// Set outputsize= member variable
setOutputsize(getAttributeValue("outputsize"));
// Set minvrm= attribute value
setMinvrm(getAttributeValue("minvrm"));
// Set maxvrm= attribute value
setMaxvrm(getAttributeValue("maxvrm"));
}
/**
* Return the list of valid attributes for the data element.
**/
String[] getAttributeList() // @C7A
{
return STRUCTATTRIBUTES; // @C7A
}
int getCount(PcmlDimensions indices) throws PcmlException
{
return resolveIntegerValue( getCount(),
getCountId(),
indices );
}
// @D1 --New XPCML method
// @D1 -- Get the run-time dimension for this element but don't throw an exception if count not set
final int getXPCMLCount(PcmlDimensions indices) throws PcmlException //@D1
{
int rc;
try {
rc = resolveIntegerValue( getCount(),
getCountId(),
indices );
return rc;
}
catch (Exception e)
{
return 0;
}
}
// Returns an array of integers containing the array dimensions
// Notes:
// getDimensions().length == 0 for scalar data
PcmlDimensions getDimensions(PcmlDimensions indices) throws PcmlException
{
PcmlDimensions myDimensions = null;
PcmlNode node = getParent(); // @C8A
// Retrieve array dimensions from all ancestors
if (node instanceof PcmlData) // @C8C
{
myDimensions = ((PcmlData) node).getDimensions(indices); // @C8C
}
else
if (node instanceof PcmlStruct) // @@C8C
{
myDimensions = ((PcmlStruct) node).getDimensions(indices); // @C8C
}
else
{
myDimensions = new PcmlDimensions(getNbrOfDimensions());
}
// If this node is defined as an array, add its dimension
if (isArray())
{
int myCount = getCount(indices);
myDimensions.add(myCount);
}
return myDimensions;
}
// Returns an array of integers containing the timestamps
// for each of the array dimensions for this node.
// Notes:
// getNbrOfDimensions() == 0 for scalar data
// getNbrOfDimensions() == getDimensions().length
long[] getDimensionTimestamps(PcmlDimensions indices) throws PcmlException
{
long[] myTimestamps;
Integer myIndex = null;
long[] previousTimestamps;
PcmlNode node = getParent(); // @C8A
// If an array is defined at this node,
// remove its dimension from the array of indices
if (isArray())
{
myIndex = indices.integerAt(indices.size()-1);
indices.remove();
}
// Retrieve array dimensions from all ancestors
if (node instanceof PcmlData) // @C8C
{
previousTimestamps = ((PcmlData) node).getDimensionTimestamps(indices); // @C8C
}
else
if (node instanceof PcmlStruct) // @C8C
{
previousTimestamps = ((PcmlStruct) node).getDimensionTimestamps(indices); // @C8C
}
else
{
previousTimestamps = new long[0];
}
// If this node is defined as an array, add its dimension
// back to the array of indices and get the time stamp for this dimension.
if (myIndex != null)
{
int i;
indices.add(myIndex);
myTimestamps = new long[previousTimestamps.length + 1];
for (i = 0; i < previousTimestamps.length; i++)
{
myTimestamps[i] = previousTimestamps[i];
}
myTimestamps[i] = resolveDimensionTimestamp(indices);
if (i > 0)
{
myTimestamps[i] = Math.max(myTimestamps[i], myTimestamps[i-1]);
}
}
else
{
myTimestamps = previousTimestamps;
}
return myTimestamps;
}
// Returns the number of dimensions for this data node
// Notes:
// getNbrOfDimensions() == 0 for scalar data
// getNbrOfDimensions() == getDimensions().length
int getNbrOfDimensions()
{
int total = 0;
PcmlNode node = getParent(); // @C8A
if (isArray())
total++;
if (node instanceof PcmlData) // @C8C
total += ((PcmlData)node).getNbrOfDimensions(); // @C8C
else
if (node instanceof PcmlStruct) // @C8C
total += ((PcmlStruct)node).getNbrOfDimensions(); // @C8C
return total;
}
// Get the run-time offset value for this element
int getOffset(PcmlDimensions indices) throws PcmlException
{
return resolveIntegerValue( getOffset(),
getOffsetId(),
indices );
}
// Get the offset= integer literal value, if any
public final int getOffset()
{
return m_Offset;
}
// Get the offset= resolved element name, if any
public final String getOffsetId()
{
return resolveRelativeName(m_OffsetId);
}
// Get the offset= unresolved element name, if any
public final String getUnqualifiedOffsetId() // @C7A
{
return m_OffsetId; // @C7A
}
// Return indication of whether this object contains
// the fix for ofsetfrom
private final boolean isOffsetfromFixed() // @A1A
{ // @A1A
return m_OffsetfromFixed; // @A1A
} // @A1A
// Get the offsetfrom= integer literal value, if any
final int getOffsetfrom() // @A1C
{
if ( isOffsetfromFixed() ) // @A1A
return m_Offsetfrom; // @A1C
else // @A1A
return -1; // @A1A
}
// Get the offsetfrom= resolved element name, if any
final String getOffsetfromId()
{
return resolveRelativeName(m_OffsetfromId);
}
// Get the offsetfrom= unresolved element name, if any
public final String getUnqualifiedOffsetfromId() // @C7A
{
return m_OffsetfromId; // @C7A
}
// Return number of bytes to allocate in outpout buffer
int getOutputsize(PcmlDimensions indices) throws PcmlException
{
int totalSize = 0;
int myCount;
boolean processArray;
// If outputsize= was specified for this element use that
// as the output size for this and all descendents.
totalSize = resolveIntegerValue( getOutputsize(),
getOutputsizeId(),
indices );
if (totalSize > 0)
return totalSize;
if (isArray() && indices.size() < getNbrOfDimensions() )
{
myCount = getCount(indices);
processArray = true;
}
else
{
myCount = 1;
processArray = false;
}
for (int myIndex = 0; myIndex < myCount; myIndex++)
{
if (processArray)
{
indices.add(myIndex);
}
Enumeration children;
PcmlDocNode child;
children = getChildren();
while (children.hasMoreElements())
{
child = (PcmlDocNode) children.nextElement();
switch (child.getNodeType())
{
case PcmlNodeType.STRUCT:
totalSize += ((PcmlStruct) child).getOutputsize(indices);
break;
case PcmlNodeType.DATA:
totalSize += ((PcmlData) child).getOutputsize(indices);
break;
default:
throw new PcmlException(DAMRI.BAD_NODE_TYPE, new Object[] {new Integer(child.getNodeType()) , getNameForException()} );
}
}
if (processArray)
{
indices.remove();
}
} // END: for myIndex
return totalSize;
}
boolean isArray()
{
if ( getCount() > 0 )
return true;
else
if ( getCountId() != null )
return true;
return false;
}
// Returns true if this node is defined as an array or
// has an ancestor defined as an array.
boolean isInArray()
{
PcmlNode node = getParent(); // @C8A
if (isArray())
return true;
else
if (node instanceof PcmlData) // @C8C
return ((PcmlData)node).isArray(); // @C8C
else
if (node instanceof PcmlStruct) // @C8C
return ((PcmlStruct)node).isArray(); // @C8C
else
return false;
}
public int getCount()
{
return m_Count;
}
public String getCountId()
{
return resolveRelativeName(m_CountId);
}
// Get the count= unresolved element name, if any
public final String getUnqualifiedCountId() // @C7A
{
return m_CountId; // @C7A
}
// Get the maxvrm= integer value -- compatible w/ AS400.generateVRM()
// Returns Integer.MAX_VALUE is maxvrm= was not specified
public final int getMaxvrm()
{
return m_MaxvrmInt;
}
// Get the maxvrm= String value
public final String getMaxvrmString() // @C7A
{
return m_Maxvrm;
}
// Get the minvrm= integer value -- compatible w/ AS400.generateVRM()
// Returns Integer.MIN_VALUE minvrm= was not specified
public final int getMinvrm()
{
return m_MinvrmInt;
}
// Get the minvrm= String value
public final String getMinvrmString() // @C7A
{
return m_Minvrm;
}
// Get the outputsize= integer literal value, if any
public final int getOutputsize()
{
return m_Outputsize;
}
// Get the outputsize= resolved element name, if any
public final String getOutputsizeId()
{
return resolveRelativeName(m_OutputsizeId);
}
// Get the outputsize= unresolved element name, if any
public final String getUnqualifiedOutputsizeId() // @C7A
{
return m_OutputsizeId; // @C7A
}
private void setCount(String count)
{
if (count == null || count.equals(""))
{
m_Count = 0;
m_CountId = null;
return;
}
try
{
m_Count = Integer.parseInt(count);
m_CountId = null;
}
catch (NumberFormatException e)
{
m_Count = 0;
m_CountId = count;
// checkAttributes() will make sure m_CountId resolves to a element with type="int"
}
}
private void setMaxvrm(String maxvrm)
{
m_MaxvrmInt = Integer.MAX_VALUE;
if (maxvrm == null || maxvrm.equals(""))
{
m_Maxvrm = null;
return;
}
m_Maxvrm = maxvrm;
}
private void setMinvrm(String minvrm)
{
m_MinvrmInt = Integer.MIN_VALUE;
if (minvrm == null || minvrm.equals(""))
{
m_Minvrm = null;
return;
}
m_Minvrm = minvrm;
}
private void setOffset(String offset)
{
if (offset == null || offset.equals(""))
{
m_Offset = 0;
m_OffsetId = null;
return;
}
try
{
m_Offset = Integer.parseInt(offset);
m_OffsetId = null;
}
catch (NumberFormatException e)
{
m_Offset = 0;
m_OffsetId = offset;
// checkAttributes() will make sure m_OffsetId resolves to a element with type="int"
}
}
private void setOffsetfrom(String offsetfrom)
{
m_OffsetfromFixed = true; // @A1A
// Handle null or empty string
if (offsetfrom == null || offsetfrom.equals(""))
{
m_Offsetfrom = -1; // @A1A
m_OffsetfromId = null;
return;
}
try // @A1A
{ // @A1A
m_Offsetfrom = Integer.parseInt(offsetfrom); // @A1A
m_OffsetfromId = null; // @A1A
} // @A1A
catch (NumberFormatException e) // @A1A
{ // @A1A
m_Offsetfrom = 0; // @A1A
m_OffsetfromId = offsetfrom;
// checkAttributes() will make sure m_OffsetfromId resolves to a document element that
// an ancestor of this node.
} // @A1A
}
private void setOutputsize(String outputsize)
{
// Handle null or empty string
if (outputsize == null || outputsize.equals(""))
{
m_Outputsize = 0;
return;
}
// Try to parse an integer from the attribute value
try
{
m_Outputsize = Integer.parseInt(outputsize);
m_OutputsizeId = null;
}
// If value is not an integer, it must be an element name
// checkAttributes() will be caled later to verify the element name
catch (NumberFormatException e)
{
m_Outputsize = 0;
m_OutputsizeId = outputsize;
// checkAttributes() will make sure m_OutputsizeId resolves to a element with type="int"
}
}
protected void checkAttributes()
{
//String resolvedName = null;
PcmlDocNode resolvedNode;
super.checkAttributes();
// Verify the count= attribute
// If an integer was specified for the count, no checking is needed.
// If a document element ID was was specified, make sure
// it resolves to a element with type="int".
if (m_CountId != null)
{
resolvedNode = resolveRelativeNode(m_CountId);
if (resolvedNode == null)
{
getDoc().addPcmlSpecificationError(DAMRI.ATTR_REF_NOT_FOUND, new Object[] {makeQuotedAttr("count", m_CountId), getNameForException()} );
}
else
{
if (resolvedNode instanceof PcmlData)
{
if ( ((PcmlData)resolvedNode).getDataType() != PcmlData.INT )
{
getDoc().addPcmlSpecificationError(DAMRI.ATTR_REF_WRONG_NODETYPE, new Object[] {makeQuotedAttr("count", m_CountId), resolvedNode.getQualifiedName(), "", getNameForException()} );
}
}
else
{
getDoc().addPcmlSpecificationError(DAMRI.ATTR_REF_WRONG_DATATYPE, new Object[] {makeQuotedAttr("count", m_CountId), resolvedNode.getQualifiedName(), "type=\"int\"", getNameForException()} );
}
}
}
else
// Do not allow count= to be a literal value that is negative
if (m_Count < 0)
{
getDoc().addPcmlSpecificationError(DAMRI.BAD_ATTRIBUTE_VALUE, new Object[] {makeQuotedAttr("count", m_Count), getBracketedTagName(), getNameForException()} ); // @A1C
}
// Verify the offset= attribute
// If an integer was specified for the offset, no checking is needed.
// If a document element ID was was specified, make sure
// it resolves to a element with type="int".
if (m_OffsetId != null)
{
resolvedNode = resolveRelativeNode(m_OffsetId);
if (resolvedNode == null)
{
getDoc().addPcmlSpecificationError(DAMRI.ATTR_REF_NOT_FOUND, new Object[] {makeQuotedAttr("offset", m_OffsetId), getNameForException()} );
}
else
{
if (resolvedNode instanceof PcmlData)
{
if ( ((PcmlData)resolvedNode).getDataType() != PcmlData.INT )
{
getDoc().addPcmlSpecificationError(DAMRI.ATTR_REF_WRONG_NODETYPE, new Object[] {makeQuotedAttr("offset", m_OffsetId), resolvedNode.getQualifiedName(), "", getNameForException()} );
}
}
else
{
getDoc().addPcmlSpecificationError(DAMRI.ATTR_REF_WRONG_DATATYPE, new Object[] {makeQuotedAttr("offset", m_OffsetId), resolvedNode.getQualifiedName(), "type=\"int\"", getNameForException()} );
}
}
}
else
// Do not allow offset= to be a literal value that is negative
if (m_Offset < 0)
{
getDoc().addPcmlSpecificationError(DAMRI.BAD_ATTRIBUTE_VALUE, new Object[] {makeQuotedAttr("offset", m_Offset), getBracketedTagName(), getNameForException()} ); // @A1C
}
// Verify the offsetfrom= attribute
// If a document element ID was was specified, make sure
// it resolves to a document element that is an ancestor of this element.
if (m_OffsetfromId != null)
{
resolvedNode = resolveRelativeNode(m_OffsetfromId);
if (resolvedNode == null)
{
getDoc().addPcmlSpecificationError(DAMRI.ATTR_REF_NOT_FOUND, new Object[] {makeQuotedAttr("offsetfrom", m_OffsetfromId), getNameForException()} );
}
else
{
String qName = getQualifiedName();
if (qName.equals("")) // @A1A
{ // @A1A
qName = getNameForException(); // @A1A
} // @A1A
String qNameResolved = resolvedNode.getQualifiedName();
if (!qName.startsWith(qNameResolved + "."))
{
getDoc().addPcmlSpecificationError(DAMRI.OFFSETFROM_NOT_FOUND, new Object[] {m_OffsetfromId, getNameForException()} );
}
}
}
else // @A1A
// Do not allow offsetfrom= to be a literal value that is negative
if (m_Offsetfrom < -1) // @A1A
{ // @A1A
getDoc().addPcmlSpecificationError(DAMRI.BAD_ATTRIBUTE_VALUE, new Object[] {makeQuotedAttr("offsetfrom", m_Offsetfrom), getBracketedTagName(), getNameForException()} ); // @A1A
} // @A1A
// Verify the minvrm= attribute
if (m_Minvrm != null)
{
m_MinvrmInt = PcmlData.validateVRM(m_Minvrm);
if (m_MinvrmInt <= 0)
{
getDoc().addPcmlSpecificationError(DAMRI.BAD_ATTRIBUTE_VALUE, new Object[] {makeQuotedAttr("minvrm", m_Minvrm), getBracketedTagName(), getNameForException()} ); // @A1C
}
}
// Verify the maxvrm= attribute
if (m_Maxvrm != null)
{
m_MaxvrmInt = PcmlData.validateVRM(m_Maxvrm);
if (m_MaxvrmInt <= 0)
{
getDoc().addPcmlSpecificationError(DAMRI.BAD_ATTRIBUTE_VALUE, new Object[] {makeQuotedAttr("maxvrm", m_Maxvrm), getBracketedTagName(), getNameForException()} ); // @A1C
}
}
// Verify the outputsize= attribute
// If an integer was specified for the offset, make sure it is in valid range.
// If a document element ID was was specified, make sure
// it resolves to a element with type="int".
if (m_OutputsizeId != null)
{
resolvedNode = resolveRelativeNode(m_OutputsizeId);
if (resolvedNode == null)
{
getDoc().addPcmlSpecificationError(DAMRI.ATTR_REF_NOT_FOUND, new Object[] {makeQuotedAttr("outputsize", m_OutputsizeId), getNameForException()} );
}
else
{
if (resolvedNode instanceof PcmlData)
{
if ( ((PcmlData)resolvedNode).getDataType() != PcmlData.INT )
{
getDoc().addPcmlSpecificationError(DAMRI.ATTR_REF_WRONG_NODETYPE, new Object[] {makeQuotedAttr("outputsize", m_OutputsizeId), resolvedNode.getQualifiedName(), "", getNameForException()} );
}
}
else
{
getDoc().addPcmlSpecificationError(DAMRI.ATTR_REF_WRONG_DATATYPE, new Object[] {makeQuotedAttr("outputsize", m_OutputsizeId), resolvedNode.getQualifiedName(), "type=\"int\"", getNameForException()} );
}
}
}
else
// Do not allow offset= to be a literal value that is negative
if (m_Outputsize < 0)
{
getDoc().addPcmlSpecificationError(DAMRI.BAD_ATTRIBUTE_VALUE, new Object[] {makeQuotedAttr("outputsize", m_Outputsize), getBracketedTagName(), getNameForException()} ); // @A1C
}
}
// Returns true if this document element is supported at the
// at the VRM of the current host.
// Returns false if not.
boolean isSupportedAtHostVRM() throws PcmlException // @A1A
{ // @A1A
int hostVrm = getAs400VRM(); // VRM of the IBM i system @A1A
// If the minvrm= for this element is greater than the server VRM
// do not process this element. The item is not available at this release.
if (getMinvrm() > hostVrm) // @A1A
{ // @A1A
return false; // @A1A
} // @A1A
// If the maxvrm= for this element is less than the server VRM
// do not process this element. The item is not available at this release.
if (getMaxvrm() < hostVrm) // @A1A
{ // @A1A
return false; // @A1A
} // @A1A
return true; // @A1A
} // @A1A
// Convert data to IBM i system format
// Returns the number of bytes to'ed
int toBytes(OutputStream bytes, int offset, PcmlDimensions indices) throws PcmlException
{
Enumeration children;
PcmlDocNode child;
int totalBytes = 0;
int myCount;
boolean processArray;
// Do not process if this element is not supported at the
// VRM of the current host.
if ( !isSupportedAtHostVRM() ) // @A1C
return 0;
// If this is an array element, set up array processing information
if (isArray() && indices.size() < getNbrOfDimensions() )
{
myCount = getCount(indices);
processArray = true;
}
else // Non-array element, only process once.
// Note: Although this element is not an array
// (i.e. does not have a count= attribute)
// It may be a child of an element that is an array.
{
myCount = 1;
processArray = false;
}
for (int myIndex = 0; myIndex < myCount; myIndex++)
{
if (processArray)
{
indices.add(myIndex);
}
children = getChildren();
while (children.hasMoreElements())
{
child = (PcmlDocNode) children.nextElement();
switch (child.getNodeType())
{
case PcmlNodeType.STRUCT:
totalBytes += ((PcmlStruct) child).toBytes(bytes, offset + totalBytes, indices);
break;
case PcmlNodeType.DATA:
totalBytes += ((PcmlData) child).toBytes(bytes, offset + totalBytes, indices);
break;
default:
throw new PcmlException(DAMRI.BAD_NODE_TYPE, new Object[] {new Integer(child.getNodeType()) , getNameForException()} );
} // END: switch (child.getNodeType())
} // END: while (children.hasMoreElements())
if (processArray)
{
indices.remove();
}
}
return totalBytes;
} // END: public int toBytes(OutputStream bytes, int offset, PcmlDimensions indices)
// Parses array of bytes and stores for later conversion
// to Java objects. This allows for lazy data translation
// for performance.
// Returns the number of bytes consumed from the input byte array
// Note: This may be larger than the number of bytes saved for this element
// because of bytes skipped due to an offset value.
int parseBytes(byte[] bytes, int offset, Hashtable offsetStack, PcmlDimensions indices) throws PcmlException
{
PcmlData dataNode; // Child of this element that is a node
PcmlStruct structNode; // Child of this element that is a node
int nbrBytes = 0; // Number of bytes consumed from input byte array
Enumeration children; // Enumeration of children of this element
PcmlDocNode child; // Current child node being processed
boolean processArray; // Indicates whether this element is an array
int myCount; // Number of array elements to process,
// or set to 1 for non-array elements
// Do not process if this element is not supported at the
// VRM of the current host.
if ( !isSupportedAtHostVRM() ) // @A1C
return 0;
// If this is an array element, set up array processing information
if (isArray() && indices.size() < getNbrOfDimensions() )
{
myCount = getCount(indices);
processArray = true;
}
else // Non-array element, only process once.
// Note: Although this element is not an array
// (i.e. does not have a count= attribute)
// It may be a child of an element that is an array.
{
myCount = 1;
processArray = false;
}
// -----------------------------------------------------------
// Calculate bytes to skip based on the offset=
// and offsetfrom= attributes.
// -----------------------------------------------------------
int skipBytes = 0; // Initially, no need to skip bytes
int myOffset = getOffset(indices); // Retrieve offset value for this element
if (myOffset > 0) // If this element has a non-zero offset
{
// Determine from where the offset is based
Integer myOffsetbase = null;
String myOffsetfromId = getOffsetfromId(); // Get offsetfrom= element name, if any @A1C
// If offsetfrom= was specified with the name of another element,
// get the base for the offset from the offset stack.
// The offset stack is a stack of beginning offsets for all
// ancestors of the current element. The offsetfrom= value must be one
// of these ancestors or an error will be reported.
if (myOffsetfromId != null) // @A1C
{
myOffsetbase = (Integer) offsetStack.get(myOffsetfromId); // @A1C
if (myOffsetbase == null)
{
throw new PcmlException(DAMRI.OFFSETFROM_NOT_FOUND, new Object[] {myOffsetfromId, getNameForException()} ); // @A1C
}
}
else
{
// If offsetfrom= was specified with an integer literal, use it.
if (getOffsetfrom() >= 0) // @A1A
{ // @A1A
myOffsetbase = new Integer(getOffsetfrom()); // @A1A
} // @A1A
// getOffsetfrom() returns -1 to indicate that offset from was not specified.
// No offsetfrom= was specified, the offset will be relative to the
// beginning offset of the parent of this elements parent.
// This is the first (most recent) entry in the offset stack.
else // @A1A
{ // @A1A
myOffsetbase = (Integer) offsetStack.get( ((PcmlDocNode) getParent()).getQualifiedName());
} // @A1A
}
// Add the base value to the offset value
if (myOffsetbase != null)
{
myOffset = myOffset + myOffsetbase.intValue();
}
// If the total offset value is greater than the current
// offset into the input byte array, calculate the
// number of bytes to skip.
// (Bytes skipped over as a result ofthe offset=.)
if (myOffset > offset)
{
skipBytes = myOffset - offset;
}
} // End calculating bytes to skip because of offset= attribute
// -----------------------------------------------------------
// Now actually parse the bytes for this element
// -----------------------------------------------------------
for (int myIndex = 0; myIndex < myCount; myIndex++)
{
// -----------------------------------------------------------
// Add this node to the offset stack
// This element's current offset is put in the stack for use by descendent elements
// to resolve their offset= attributes.
// -----------------------------------------------------------
String qName = getQualifiedName();
if (!qName.equals(""))
{
offsetStack.put(qName, new Integer(offset + skipBytes + nbrBytes)); // pva 10/30
}
// Add the current index for this dimension to the indices
if (processArray)
{
indices.add(myIndex);
}
// Process each child element in this structure.
children = getChildren();
while (children.hasMoreElements())
{
child = (PcmlDocNode) children.nextElement();
switch (child.getNodeType())
{
case PcmlNodeType.STRUCT:
structNode = (PcmlStruct) child;
nbrBytes += structNode.parseBytes(bytes, offset + skipBytes + nbrBytes, offsetStack, indices);
break;
case PcmlNodeType.DATA:
dataNode = (PcmlData) child;
nbrBytes += dataNode.parseBytes(bytes, offset + skipBytes + nbrBytes, offsetStack, indices);
break;
default:
throw new PcmlException(DAMRI.BAD_NODE_TYPE, new Object[] {new Integer(child.getNodeType()) , getNameForException()} );
} // END: switch (child.getNodeType())
} // END: while (children.hasMoreElements())
// Remove the current index for this dimension from the indices
if (processArray)
{
indices.remove();
}
// -----------------------------------------------------------
// Remove this node from the offset stack
// -----------------------------------------------------------
if (!qName.equals(""))
{
offsetStack.remove(qName);
}
} // END: for myIndex
return nbrBytes + skipBytes;
} // public int parseBytes(byte[] bytes, int offset)
// Resolve an integer value from either a named element or a literal
private int resolveIntegerValue(int intLiteral, String name, PcmlDimensions indices) throws PcmlException
{
PcmlNode node;
PcmlData dataNode;
Object nodeValue;
if (name != null)
{
node = getDoc().getElement(name);
if (node instanceof PcmlData)
{
dataNode = (PcmlData) node;
nodeValue = dataNode.getValue(indices);
if (nodeValue instanceof String)
{
return Integer.parseInt((String) nodeValue);
}
else if (nodeValue instanceof Number)
{
return ((Number) nodeValue).intValue();
}
else
{
if (nodeValue == null)
throw new PcmlException(DAMRI.INPUT_VALUE_NOT_SET, new Object[] {dataNode.getNameForException()} );
else
throw new PcmlException(DAMRI.STRING_OR_NUMBER, new Object[] {nodeValue.getClass().getName(), dataNode.getNameForException()} );
}
}
else
{
if (node == null)
throw new PcmlException(DAMRI.ELEMENT_NOT_FOUND, new Object[] {name, ""} );
else
throw new PcmlException(DAMRI.WRONG_ELEMENT_TYPE, new Object[] {name, ""} );
}
}
return intLiteral;
}
// Resolve a timestamp for the given indices
private long resolveDimensionTimestamp(PcmlDimensions indices) throws PcmlException
{
PcmlNode node;
String name = getCountId();
if (name != null)
{
node = getDoc().getElement(name);
if (node instanceof PcmlData)
{
return ((PcmlData)node).getTimestamp(indices);
}
else
{
if (node == null)
throw new PcmlException(DAMRI.ELEMENT_NOT_FOUND, new Object[] {name, ""} );
else
throw new PcmlException(DAMRI.WRONG_ELEMENT_TYPE, new Object[] {name, ""} );
}
}
return Long.MIN_VALUE;
}
}