com.ibm.as400.data.PcmlDataValues Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jt400 Show documentation
Show all versions of jt400 Show documentation
The Open Source version of the IBM Toolbox for Java
The newest version!
///////////////////////////////////////////////////////////////////////////////
//
// JTOpen (IBM Toolbox for Java - OSS version)
//
// Filename: PcmlDataValues.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-2000 International Business Machines Corporation and
// others. All rights reserved.
//
///////////////////////////////////////////////////////////////////////////////
package com.ibm.as400.data;
import com.ibm.as400.access.AS400DataType;
import com.ibm.as400.access.AS400Text;
import com.ibm.as400.access.AS400Date;
import com.ibm.as400.access.AS400Time;
import com.ibm.as400.access.AS400Timestamp;
import com.ibm.as400.access.BidiStringType;
import com.ibm.as400.access.BinaryConverter;
import com.ibm.as400.access.Trace; // @D3A
import java.math.BigDecimal;
import java.math.BigInteger;
import java.io.IOException; // @C1A
import java.io.ObjectInputStream; // @C1A
import java.io.ObjectOutputStream; // @C1A
import java.io.OutputStream;
import java.io.Serializable; // @C1A
import java.util.Hashtable;
import java.util.StringTokenizer;
import java.util.TimeZone;
class PcmlDataValues extends Object implements Serializable // @C1C
{
static final long serialVersionUID = -8169008879805188674L; // @C1A
private PcmlData m_owner; // PcmlData node that owns this object
private PcmlDimensions m_indices; // Indices into owning PcmlNode's vectors of PcmlDataValues
private Object m_value; // Java native value: (String, Short, Integer, Long, Float, Double, BigDecimal. byte[])
private long m_valueTs; // Correlation id of Java native value from PcmlDocument.getCorrelationID()
private byte[] m_bytes; // IBM i bytes (ebcdic/big-endian)
private long m_bytesTs; // Correlation id of IBM i bytes from PcmlDocument.getCorrelationID()
private int m_bidiStringType; // Type of string that is contained in the value @C6A
// Default constructor
private PcmlDataValues()
{
m_value = null;
m_bytes = null;
m_valueTs = 0;
m_bytesTs = 0;
m_bidiStringType = BidiStringType.DEFAULT; // @C6A
}
// Constructor
PcmlDataValues(PcmlData creator, PcmlDimensions indices)
{
this();
m_owner = creator;
m_indices = new PcmlDimensions(indices);
}
// Custom serialization
private void writeObject(ObjectOutputStream out) throws IOException // @C1A
{ // @C1A
synchronized (this) // @C1A
{ // @C1A
// For input values, serialize only the IBM i byte value
// if it is current than the Java value
if ( m_owner.getUsage() == PcmlDocNode.INPUT ) // @C1A
{ // @C1A
// If the byte value is more recent than the Java value
// convert the bytes to a Java value
if (m_bytesTs > m_valueTs) // @C1A
{ // @C1A
m_value = null; // @C1A
m_valueTs = 0; // @C1A
} // @C1A
} // @C1A
// For ouput values, serialize only the Java value
// if it is current than the IBM i byte value
if ( m_owner.getUsage() == PcmlDocNode.OUTPUT ) // @C1A
{
// If the byte value is more recent than the Java value
// convert the bytes to a Java value
if (m_valueTs > m_bytesTs) // @C1A
{ // @C1A
m_bytes = null; // @C1A
m_bytesTs = 0; // @C1A
} // @C1A
} // @C1A
// Perform default serialization
out.defaultWriteObject(); // @C1A
} // end of synchronized code // @C1A
} // @C1A
// Custom deserialization
private void readObject(ObjectInputStream in)
throws IOException, ClassNotFoundException // @C1A
{ // @C1A
// Default deserialization
in.defaultReadObject(); // @C1A
} // @C1A
// Custom deserialization post-processing
// This processing cannot be done during readObject() because
// references to parent objects in the document are not yet set
// due to the recursive nature of deserialization.
void readObjectPostprocessing() // @C1A
{ // @C1A
if (m_valueTs == m_bytesTs && m_valueTs > 0) // @C1A
{ // @C1A
m_valueTs = m_owner.getDoc().getDeserializationTimestamp(); // @C1A
m_bytesTs = m_owner.getDoc().getDeserializationTimestamp(); // @C1A
} // @C1A
if (m_valueTs > m_bytesTs) // @C1A
{ // @C1A
m_valueTs = m_owner.getDoc().getDeserializationTimestamp(); // @C1A
m_bytesTs = 0; // @C1A
} // @C1A
if (m_bytesTs > m_valueTs) // @C1A
{ // @C1A
m_bytesTs = m_owner.getDoc().getDeserializationTimestamp(); // @C1A
m_valueTs = 0; // @C1A
} // @C1A
} // @C1A
// Flush data values
// This allows the object to be reused when the
// m_owner (PcmlData object) redimensions its vectors.
void flushValues()
{
m_value = null;
m_bytes = null;
m_valueTs = 0;
m_bytesTs = 0;
}
// Get qualified name of data object
String getQualifiedName()
{
return m_owner.getQualifiedName();
}
// Get name for exceptions
String getNameForException()
{
return m_owner.getNameForException();
}
// Get Timestamp of data
long getTimestamp()
{
return Math.max(m_valueTs, m_bytesTs);
}
// Get Java native value
public Object getValue() throws PcmlException
{
return bytesToValue();
}
// Set Java native value
public void setValue(Object v) throws PcmlException
{
// Do not allow a null value to be set
if (v == null)
throw new PcmlException(DAMRI.NULL_VALUE, new Object[] {getNameForException()} );
// If the new value matches the Java type for this element
// store the new value.
if (getDataType() == PcmlData.STRUCT) { // @D0A
throw new PcmlException(DAMRI.STRUCT_VALUE, new Object[] {getNameForException()} ); // @D0A
}
if (getDataType() == PcmlData.CHAR &&
(v instanceof String || v instanceof char[])) { //@AI6A
m_value = v;
}
else if ( v.getClass().equals(getValueClass()))
{
if (v instanceof BigDecimal) {
m_value = ((BigDecimal)v).setScale(getPrecision(), BigDecimal.ROUND_HALF_EVEN); // @D0A
}
else {
m_value = v;
}
}
// New value does not match the Java type for this element.
// Convert to the Java type needed -- errors may occur.
else
{
// Determine the timezone
TimeZone timeZone = m_owner.getDoc().getTimeZone();
m_value = convertValue(v, getDataType(), getLength(), getPrecision(), getNameForException(), timeZone);
}
// Update the value timestamp
m_valueTs = m_owner.getDoc().getCorrelationID();
}
// Set IBM i bytes
public void setBytes(byte[] ba)
{
m_bytes = ba;
m_bytesTs = m_owner.getDoc().getCorrelationID(); // @C7C
}
// Set the bidi string type
public void setStringType(int type) // @C6A
{
if (m_bidiStringType == type) // @C6A
{
// If new type is same as old, just return
return; // @C6A
}
// If we are setting a new string type, we want to
// clear the java value and timestamp. This will ensure
// that the correct conversion occurs on subsequent
// getValue() calls
m_bidiStringType = type; // @C6A
m_value = null; // @C6A
m_valueTs = 0; // @C6A
}
// Convert IBM i bytes to Java native value
private Object bytesToValue() throws PcmlException
{
// If the byte value is more recent than the Java value
// convert the bytes to a Java value
if (m_bytesTs > m_valueTs)
{
m_valueTs = m_bytesTs; // Update value timestamp
toObject(m_bytes);
}
// If value is not set and there is an
// init= value specified, initialize the value
if (m_value == null)
{
String initValue = m_owner.getInit();
if (initValue != null)
setValue(initValue);
}
if (m_value == null) // If value has not been set @C5A
return m_value; // return null @C5A
// Return the Java value
if (getDataType() == PcmlData.BYTE)
{
// Make a copy of the byte array, so caller can
// modify the value without repercussions
byte[] srcArray = (byte[]) m_value;
byte[] cloneArray = new byte[srcArray.length];
System.arraycopy(srcArray, 0, cloneArray, 0, srcArray.length);
return cloneArray;
}
else
{
// No need to make copy for other data type because they
// are immutable objects.
return m_value;
}
}
int getDataType()
{
return m_owner.getDataType();
}
int getLength() throws PcmlException
{
String charType = m_owner.getCharType(); // @D2A
if ((charType != null) && (charType.equals("twobyte")))
{
return (resolveIntegerValue( m_owner.getLength(),
m_owner.getLengthId() ) * 2); // @D2A
}
else
{
return resolveIntegerValue( m_owner.getLength(),
m_owner.getLengthId() );
}
}
int getOffset() throws PcmlException
{
return resolveIntegerValue( m_owner.getOffset(),
m_owner.getOffsetId() );
}
int getCcsid() throws PcmlException
{
int tmpCcsid = resolveIntegerValue( m_owner.getCcsid(),
m_owner.getCcsidId() );
// If a CCSID is not explicitly defined for this element,
// use the CCSID from the element
if (tmpCcsid == 0)
{ // @C2A
PcmlNode node = m_owner.getParent(); // @C2A
node = node.getParent(); // get next ancestor @C7A
while (node != m_owner.getDoc()) // @C2A @C7C
node = node.getParent(); // @C2A
// If this element is a descendent of a Program element
// use the CCSID saved the last time the
if (node instanceof PcmlProgram) // @C2A
return ((PcmlProgram) node).getProgramCCSID(); // @C2A
else if (node instanceof RfmlDocument) // @D0A
return ((RfmlDocument) node).getCcsidInt(); // @D0A
else // @C2A
return m_owner.getDoc().getAs400().getCcsid(); // @C2A
} // @C2A
else
return tmpCcsid;
}
// Returns the precision= attribute
// The precision is only meaningful when type=int or packed
// For type=int:
// A 2-byte signed integer is: length=2 precision=15
// A 2-byte unsigned integer is: length=2 precision=16
// A 4-byte signed integer is: length=4 precision=31
// A 4-byte unsigned integer is: length=4 precision=32
// For type=packed:
// length= species the total number of digits
// precision= specifies the number of decimal digits
int getPrecision()
{
return m_owner.getPrecision();
}
// Returns the dateformat= attribute
// The dateformat is only meaningful when type=date
String getDateFormat()
{
return m_owner.getDateFormat();
}
// Returns the dateseparator= attribute
// The dateseparator is only meaningful when type=date
String getDateSeparator()
{
return m_owner.getDateSeparator();
}
// Returns the timeformat= attribute
// The timeformat is only meaningful when type=time
String getTimeFormat()
{
return m_owner.getTimeFormat();
}
// Returns the timeseparator= attribute
// The timeseparator is only meaningful when type=time
String getTimeSeparator()
{
return m_owner.getTimeSeparator();
}
String getTrim() // @D1A
{ // @D1A
return m_owner.getTrim(); // @D1A
} // @D1A
boolean isArray()
{
return m_owner.isArray();
}
// Return number of bytes required to perform toBytes();
// This is similar to C++ DataObject::FlattenedLengthAt()
public int byteLength() throws PcmlException
{
int length = getLength();
switch (getDataType())
{
case PcmlData.CHAR:
case PcmlData.INT:
case PcmlData.FLOAT:
case PcmlData.BYTE:
return length;
case PcmlData.PACKED:
return length / 2 + 1; // Packed contains 2 digits per byte plus sign
case PcmlData.ZONED:
return length; // Zoned contains 1 digit per byte, sign is in low order digit
case PcmlData.DATE:
if (length == 0) {
String format = getDateFormat();
if (format != null) {
length = AS400Date.getByteLength(AS400Date.toFormat(format), PcmlNode.separatorAsChar(getDateSeparator()));
}
}
return length;
case PcmlData.TIME:
if (length == 0) {
String format = getTimeFormat();
if (format != null) {
length = AS400Time.getByteLength(AS400Time.toFormat(format), PcmlNode.separatorAsChar(getTimeSeparator()));
}
}
return length;
case PcmlData.TIMESTAMP:
if (length == 0) {
//length = AS400Timestamp.getByteLength(null);
length = 26; // we publicly support only the 26-byte timestamp format
}
return length;
default:
throw new PcmlException(DAMRI.BAD_DATA_TYPE, new Object[] {Integer.valueOf(getDataType()) , getNameForException()} );
}
}
// Converts an object to the correct type (class) for
// the defined data tpe.
// The setValue method allows most data types to be set using
// either the Java class associaed with the data type or using
// a String. This method converts the value to the Java class
// defined for the data type. Exceptions such as
// NumberFormatException may result.
private Class getValueClass() throws PcmlException
{
int dataLength = getLength();
int dataPrecision = getPrecision();
int dataType = getDataType();
//try //@O6D
{
switch (dataType)
{
case PcmlData.CHAR:
return java.lang.String.class;// @O6C Class.forName("java.lang.String");
case PcmlData.VARCHAR:
return java.lang.String.class;
case PcmlData.INT:
if (dataLength == 2)
{
if (dataPrecision == 16)
{
return java.lang.Integer.class; //@O6C Class.forName("java.lang.Integer");
}
else
{ // dataPrecision == 15 or defaulted
return java.lang.Short.class; //@O6C Class.forName("java.lang.Short");
}
}
else
if (dataLength == 4) // @C3A
{ // dataLength == 4
if (dataPrecision == 32)
{
return java.lang.Long.class;//@O6C Class.forName("java.lang.Long");
}
else
{ // dataPrecision == 31 or defaulted
return java.lang.Integer.class;//@O6C Class.forName("java.lang.Integer");
}
}
else // @C3A
if (dataLength == 8) // @C3A
{ // dataLength == 8 // @C3A
if (dataPrecision == 64)
{
return java.math.BigInteger.class;//@O6C Class.forName("java.math.BigInteger");
}
else
{ // dataPrecision == 63 or defaulted
return java.lang.Long.class;//@O6C Class.forName("java.lang.Long"); // @C3A
}
} // @C3A
case PcmlData.PACKED:
case PcmlData.ZONED:
return java.math.BigDecimal.class;//@O6C Class.forName("java.math.BigDecimal");
case PcmlData.FLOAT:
if (dataLength == 4)
{
return java.lang.Float.class;//@O6C Class.forName("java.lang.Float");
}
else
{ // Must be length=8
return java.lang.Double.class;//@O6C Class.forName("java.lang.Double");
}
case PcmlData.BYTE:
return (new byte[0]).getClass();
case PcmlData.DATE:
return java.sql.Date.class;//@O6C Class.forName("java.sql.Date");
case PcmlData.TIME:
return java.sql.Time.class;//@O6C Class.forName("java.sql.Time");
case PcmlData.TIMESTAMP:
return java.sql.Timestamp.class;//@O6C Class.forName("java.sql.Timestamp");
default:
throw new PcmlException(DAMRI.BAD_DATA_TYPE, new Object[] {Integer.valueOf(getDataType()) , getNameForException()} );
} // END: switch (getDataType())
}
/* catch (ClassNotFoundException e) //@O6D
{
throw new PcmlException(DAMRI.CLASS_NOT_FOUND, new Object[] {Integer.valueOf(getDataType()) , getNameForException()} );
}*/
}
// Convert Java object IBM i bytes
// Returns the number of bytes converted
public int toBytes(OutputStream bytes, int offset) throws PcmlException
{
Object value = null;
int dataType = getDataType();
int dataLength = getLength();
if (dataLength == 0) { // this can happen with date, time, timestamp
dataLength = byteLength();
}
int bytesConverted = 0; // @B2A
// Get the Java object and make sure it has been set.
value = getValue();
if (value == null)
{
throw new PcmlException(DAMRI.INPUT_VALUE_NOT_SET, new Object[] {getNameForException()} );
}
// Get a converter from the PcmlDocument node.
// PcmlDocument will either create a converter or return an existing one.
AS400DataType converter = m_owner.getDoc().getConverter(dataType, dataLength, getPrecision(), getCcsid(), getDateFormat(), getDateSeparator(), getTimeFormat(), getTimeSeparator());
byte[] byteArray = new byte[dataLength];
if (dataType != PcmlData.CHAR) // @C6A
{
synchronized(converter) // @B1A
{ // @B1A
converter.toBytes(value, byteArray);
bytesConverted = converter.getByteLength(); // @B2A
} // @B1A
}
else // We need to use the string type for the conversion @C6A
{
synchronized(converter) // @C6A
{
((AS400Text)converter).toBytes(value, byteArray, 0, m_bidiStringType); // @C6A
bytesConverted = converter.getByteLength(); // @C6A
}
}
try { bytes.write(byteArray, 0, bytesConverted); }
catch (IOException e) { throw new PcmlException(e); }
// Detail tracing of data conversion
if (Trace.isTracePCMLOn()) // @D3C
{ // @B2A
String parseMsg; // @B2A
if (m_indices.size() > 0) // @B2A
{ // @B2A
parseMsg = SystemResourceFinder.format(DAMRI.WRITE_DATA_W_INDICES, new Object[] {Integer.toHexString(offset), Integer.toString(bytesConverted), getNameForException(), m_indices.toString(), PcmlMessageLog.toHexString(byteArray, 0, bytesConverted)} ); // @B2A
} // @B2A
else // @B2A
{ // @B2A
parseMsg = SystemResourceFinder.format(DAMRI.WRITE_DATA, new Object[] {Integer.toHexString(offset), Integer.toString(bytesConverted), getNameForException(), PcmlMessageLog.toHexString(byteArray, 0, bytesConverted)} ); // @B2A
} // @B2A
parseMsg = parseMsg + "\t " + Thread.currentThread(); // @B2A
Trace.log(Trace.PCML, parseMsg); // @D3C
} // @B2A
return bytesConverted; // @B2A
} // public int toBytes(OutputStream bytes, int offset)
// Convert IBM i bytes to Java Object
// Returns the Java Object
public Object toObject(byte[] bytes) throws PcmlException
{
Object newVal = null;
int dataType = getDataType();
// Get a converter from the PcmlDocument node.
// PcmlDocument will either create a converter or return an existing one.
AS400DataType converter = m_owner.getDoc().getConverter(dataType, getLength(), getPrecision(), getCcsid(), getDateFormat(), getDateSeparator(), getTimeFormat(), getTimeSeparator());
if (dataType != PcmlData.CHAR) // @C6A
{
synchronized(converter) // @B1A
{ // @B1A
newVal = converter.toObject(bytes);
} // @B1A
}
else // We need to use the string type for the conversion @C6A
{
synchronized(converter) // @C6A
{
newVal = ((AS400Text)converter).toObject(bytes, 0, m_bidiStringType); // @C6A
}
}
// For Strings, trim blanks and nulls appropriately
if (dataType == PcmlData.CHAR)
{
newVal = trimString((String) newVal, getTrim()); // @B2A @D1C
}
// Set the new value
setValue(newVal);
return newVal;
} // public int toBytes(byte[] bytes, int offset)
// 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.
public int parseBytes(byte[] bytes, int offset, Hashtable offsetStack) throws PcmlException
{
int nbrBytes = 0;
int skipBytes = 0;
// Adjust offset if necessary
// This is driven by the offset= attribute on the tag
int myOffset = getOffset();
if (myOffset != 0)
{
// Handle errors caused by bad offset values
if (myOffset < 0 || myOffset > bytes.length)
{
throw new PcmlException(DAMRI.BAD_OFFSET_VALUE, new Object[] {Integer.valueOf(myOffset), Integer.valueOf(bytes.length), "", getNameForException()} );
}
// Determine from where the offset is based
Integer myOffsetbase = null;
String myOffsetfrom = m_owner.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 (myOffsetfrom != null)
{
myOffsetbase = (Integer) offsetStack.get(myOffsetfrom);
if (myOffsetbase == null)
{
throw new PcmlException(DAMRI.OFFSETFROM_NOT_FOUND, new Object[] {myOffsetfrom, getNameForException()} );
}
}
else
{
// If offsetfrom= was specified with an integer literal, use it.
if (m_owner.getOffsetfrom() >= 0) // @A1A
{ // @A1A
myOffsetbase = Integer.valueOf(m_owner.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
myOffsetfrom = ((PcmlDocNode) m_owner.getParent()).getQualifiedName();
myOffsetbase = (Integer) offsetStack.get( myOffsetfrom );
} // @A1A
}
if (myOffsetbase != null)
{
myOffset = myOffset + myOffsetbase.intValue();
// Handle errors caused by bad offset values
if (myOffset < 0 || myOffset > bytes.length)
{
throw new PcmlException(DAMRI.BAD_TOTAL_OFFSET, new Object[] {Integer.valueOf(myOffset), Integer.valueOf(bytes.length), myOffsetbase, myOffsetfrom, "", getNameForException()} );
}
}
// If offset for this element is beyond current offset
// calculate number of bytes to skip
if (myOffset > offset)
{
skipBytes = myOffset - offset;
}
}
// Get number of bytes to parse for this value
nbrBytes = byteLength();
// Make sure length makes sense
if (nbrBytes < 0 || nbrBytes > PcmlData.MAX_STRING_LENGTH)
{
throw new PcmlException(DAMRI.BAD_DATA_LENGTH, new Object[] {Integer.valueOf(nbrBytes), Integer.valueOf(PcmlData.MAX_STRING_LENGTH), "", getNameForException()} ); // @C4C
}
// Make sure we are not trying to access more bytes than available.
if (offset + skipBytes + nbrBytes > bytes.length)
{
throw new PcmlException(DAMRI.INSUFFICIENT_INPUT_DATA, new Object[] {Integer.toString(offset + skipBytes + nbrBytes), Integer.toString(bytes.length), "", getNameForException()} );
}
// Finally, make a new byte array, copy the bytes, and save them
byte [] newBytes = new byte[nbrBytes];
for (int b = 0; b < nbrBytes; b++)
{
newBytes[b] = bytes[offset+ skipBytes + b];
}
setBytes(newBytes);
// Detail tracing of data parsing
if (Trace.isTracePCMLOn()) // @D3C
{
String parseMsg;
if (m_indices.size() > 0)
{
parseMsg = SystemResourceFinder.format(DAMRI.READ_DATA_W_INDICES, new Object[] {Integer.toHexString(offset+ skipBytes), Integer.toString(nbrBytes), getNameForException(), m_indices.toString(), PcmlMessageLog.toHexString(newBytes)} );
}
else
{
parseMsg = SystemResourceFinder.format(DAMRI.READ_DATA, new Object[] {Integer.toHexString(offset+ skipBytes), Integer.toString(nbrBytes), getNameForException(), PcmlMessageLog.toHexString(newBytes)} );
}
parseMsg = parseMsg + "\t " + Thread.currentThread();
Trace.log(Trace.PCML, parseMsg);
}
return skipBytes + nbrBytes;
} // End parseBytes()
// Resolve an integer value from either a named element or a literal
private int resolveIntegerValue(int intLiteral, String intId) throws PcmlException
{
PcmlData intNode;
Object nodeValue;
if (intId != null)
{
intNode = (PcmlData) ((PcmlDocRoot)m_owner.getRootNode()).getElement(intId);
nodeValue = intNode.getValue(m_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[] {intNode.getNameForException()} );
}
else
{
throw new PcmlException(DAMRI.STRING_OR_NUMBER, new Object[] {nodeValue.getClass().getName(), intNode.getNameForException()} );
}
}
return intLiteral;
}
// Converts an object to the correct type (class) for
// the defined data type.
// The setValue method allows most data types to be set using
// either the Java class associated with the data type or using
// a String. This method converts the value to the Java class
// defined for the data type. Exceptions such as
// NumberFormatException may result.
//
// This is implemented as a static method so it can be used
// to verify the init= attribute after parsing the pcml document tags.
public static Object convertValue(Object newVal, int dataType, int dataLength, int dataPrecision, String nodeNameForException, TimeZone serverTimeZone) throws PcmlException
{
Object convertedVal = null;
if (newVal == null)
throw new PcmlException(DAMRI.NULL_VALUE, new Object[] {nodeNameForException} );
switch (dataType)
{
case PcmlData.CHAR:
if (newVal instanceof String)
{
convertedVal = newVal;
}
else
{
convertedVal = newVal.toString();
}
break;
case PcmlData.INT:
if (dataLength == 2)
{
if (dataPrecision == 16)
{
if (newVal instanceof String)
{
convertedVal = Integer.valueOf((String) newVal);
}
else
{
if (newVal instanceof Integer)
{
convertedVal = newVal;
}
else if (newVal instanceof Number)
{
convertedVal = Integer.valueOf( ((Number) newVal).intValue() );
}
else
{
throw new PcmlException(DAMRI.STRING_OR_NUMBER, new Object[] {newVal.getClass().getName(), nodeNameForException} );
}
}
}
else
{ // dataPrecision == 15 or defaulted
if (newVal instanceof String)
{
convertedVal = Short.valueOf( ((String) newVal) );
}
else
{
if (newVal instanceof Short)
{
convertedVal = newVal;
}
else if (newVal instanceof Number)
{
convertedVal = Short.valueOf( ((Number) newVal).shortValue() );
}
else
{
throw new PcmlException(DAMRI.STRING_OR_NUMBER, new Object[] {newVal.getClass().getName(), nodeNameForException} );
}
}
}
}
else if (dataLength == 4) // @C3A
{
if (dataPrecision == 32)
{
if (newVal instanceof String)
{
convertedVal = Long.valueOf((String) newVal);
}
else
{
if (newVal instanceof Long)
{
convertedVal = newVal;
}
else if (newVal instanceof Number)
{
convertedVal = Long.valueOf( ((Number) newVal).longValue() );
}
else
{
throw new PcmlException(DAMRI.STRING_OR_NUMBER, new Object[] {newVal.getClass().getName(), nodeNameForException} );
}
}
}
else
{ // dataPrecision == 31 or defaulted
if (newVal instanceof String)
{
convertedVal = Integer.valueOf((String) newVal);
}
else
{
if (newVal instanceof Integer)
{
convertedVal = newVal;
}
else if (newVal instanceof Number)
{
convertedVal = Integer.valueOf( ((Number) newVal).intValue() );
}
else
{
throw new PcmlException(DAMRI.STRING_OR_NUMBER, new Object[] {newVal.getClass().getName(), nodeNameForException} );
}
}
}
}
else // @C3A
{ // dataLength == 8 // @C3A
if (dataPrecision == 64)
{
if (newVal instanceof String)
{
convertedVal = new BigInteger((String) newVal);
}
else
{
if (newVal instanceof BigInteger)
{
convertedVal = newVal;
}
else if (newVal instanceof Number)
{
long longVal = ((Number) newVal).longValue();
convertedVal = new BigInteger(Long.toString(longVal));
}
else
{
throw new PcmlException(DAMRI.STRING_OR_NUMBER, new Object[] {newVal.getClass().getName(), nodeNameForException} );
}
}
}
else
{ // dataPrecision == 63 or defaulted
if (newVal instanceof String) // @C3A
{ // @C3A
convertedVal = Long.valueOf((String) newVal); // @C3A
} // @C3A
else // @C3A
{ // @C3A
if (newVal instanceof Long)
{
convertedVal = newVal;
}
else if (newVal instanceof Number) // @C3A
{ // @C3A
convertedVal = Long.valueOf( ((Number) newVal).longValue() ); // @C3A
} // @C3A
else // @C3A
{ // @C3A
throw new PcmlException(DAMRI.STRING_OR_NUMBER, new Object[] {newVal.getClass().getName(), nodeNameForException} ); // @C3A
} // @C3A
} // @C3A
}
} // @C3A
break;
// Allows input value to be one of: BigDecimal, String or a subclass of Number
case PcmlData.PACKED:
case PcmlData.ZONED:
if (newVal instanceof BigDecimal)
{
convertedVal = ((BigDecimal)newVal).setScale(dataPrecision, BigDecimal.ROUND_HALF_EVEN); // @D0C
}
else
{
if (newVal instanceof String)
{
convertedVal = (new BigDecimal((String) newVal));
if (((BigDecimal)convertedVal).scale() != dataPrecision) {
convertedVal = ((BigDecimal)convertedVal).setScale(dataPrecision, BigDecimal.ROUND_HALF_EVEN); // @D0A
}
}
else
{
if (newVal instanceof Number)
{
convertedVal = (new BigDecimal(((Number) newVal).doubleValue())).setScale(dataPrecision, BigDecimal.ROUND_HALF_EVEN); // @D0C
}
else
{
throw new PcmlException(DAMRI.STRING_OR_NUMBER, new Object[] {newVal.getClass().getName(), nodeNameForException} );
}
}
}
break;
case PcmlData.FLOAT:
if (dataLength == 4)
{
if (newVal instanceof String)
{
convertedVal = Float.valueOf((String) newVal);
}
else
{
if (newVal instanceof Float)
{
convertedVal = newVal;
}
else if (newVal instanceof Number)
{
convertedVal = Float.valueOf( ((Number) newVal).floatValue() );
}
else
{
throw new PcmlException(DAMRI.STRING_OR_NUMBER, new Object[] {newVal.getClass().getName(), nodeNameForException} );
}
}
}
else
{ // Must be length=8
if (newVal instanceof String)
{
convertedVal = Double.valueOf((String) newVal);
}
else
{
if (newVal instanceof Double)
{
convertedVal = newVal;
}
else if (newVal instanceof Number)
{
convertedVal = Double.valueOf( ((Number) newVal).doubleValue() );
}
else
{
throw new PcmlException(DAMRI.STRING_OR_NUMBER, new Object[] {newVal.getClass().getName(), nodeNameForException} );
}
}
}
break;
case PcmlData.BYTE:
if (newVal instanceof String)
{
StringTokenizer st = new StringTokenizer((String) newVal, " ,");
byte byteVal = 0;
byte[] byteArray = new byte[dataLength];
for (int i=0; i < dataLength; i++)
{
if (st.hasMoreTokens())
{
String token = st.nextToken();
try {
byteVal = Byte.decode(token).byteValue();
}
catch (NumberFormatException nfe)
{
// If leftmost bit is on (as in, for example, 0x80), and token isn't prefixed by a minus sign, Byte.decode() throws a NumberFormatException.
// For such cases we must use a more accommodating conversion utility.
try {
byte[] bytes = BinaryConverter.stringToBytes(token);
byteVal = bytes[0];
}
catch (NumberFormatException e) {
// Rethrow original exception; it's more informative.
throw nfe;
}
}
}
else {
// Pad with final token in string
}
byteArray[i] = byteVal;
}
convertedVal = byteArray;
}
else
if (newVal instanceof Number)
{
byte byteVal = ((Number) newVal).byteValue();
byte[] byteArray = new byte[dataLength];
for (int i=0; i < dataLength; i++)
{
byteArray[i] = byteVal;
}
convertedVal = byteArray;
}
else
{
throw new PcmlException(DAMRI.STRING_OR_NUMBER, new Object[] {newVal.getClass().getName(), nodeNameForException} );
}
break;
case PcmlData.DATE:
if (newVal instanceof String)
{
// Parse XML Schema-style date value: yyyy-mm-dd
convertedVal = AS400Date.parseXsdString((String)newVal, serverTimeZone);
}
else
{
if (newVal instanceof java.sql.Date)
{
convertedVal = (java.sql.Date)newVal;
}
else
{
throw new PcmlException(DAMRI.STRING_OR_NUMBER, new Object[] {newVal.getClass().getName(), nodeNameForException} );
}
}
break;
case PcmlData.TIME:
if (newVal instanceof String)
{
// Parse XML Schema-style time value: hh:mm:ss
convertedVal = AS400Time.parseXsdString((String)newVal, serverTimeZone);
}
else
{
if (newVal instanceof java.sql.Time)
{
convertedVal = (java.sql.Time)newVal;
}
else
{
throw new PcmlException(DAMRI.STRING_OR_NUMBER, new Object[] {newVal.getClass().getName(), nodeNameForException} );
}
}
break;
case PcmlData.TIMESTAMP:
if (newVal instanceof String)
{
// Parse XML Schema-style timestamp value: yyyy-MM-ddTHH:mm:ss.SSSSSSSSS
convertedVal = AS400Timestamp.parseXsdString((String)newVal, serverTimeZone);
}
else
{
if (newVal instanceof java.sql.Timestamp)
{
convertedVal = (java.sql.Timestamp)newVal;
}
else
{
throw new PcmlException(DAMRI.STRING_OR_NUMBER, new Object[] {newVal.getClass().getName(), nodeNameForException} );
}
}
break;
default:
throw new PcmlException(DAMRI.BAD_DATA_TYPE, new Object[] {Integer.valueOf(dataType) , nodeNameForException} );
} // END: switch (getDataType())
return convertedVal;
}
// Trims blanks and nulls from the ends of a string
// Returns the trimmed string // @D1C
static String trimString(String str, String trimEnd)
{
if (trimEnd != null && trimEnd.equals("none"))
{
return str;
}
char[] charBuff = str.toCharArray();
int startOffset = 0; // Used when constructing return string
int lengthReturned = charBuff.length; // Used when constructing return string
if (trimEnd == null || trimEnd.equals("right") || trimEnd.equals("both") )
{
// Trim blanks and nulls
trimRight: while (lengthReturned > 0)
{
switch (charBuff[lengthReturned-1])
{
case ' ':
case '\0':
lengthReturned--;
break;
default:
break trimRight;
}
}
}
if (trimEnd != null && (trimEnd.equals("left") || trimEnd.equals("both")) )
{
// Trim blanks and nulls
trimLeft: while (startOffset < lengthReturned)
{
switch (charBuff[startOffset])
{
case ' ':
case '\0':
startOffset++;
lengthReturned--;
break;
default:
break trimLeft;
}
}
}
return new String(charBuff, startOffset, lengthReturned);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy