All Downloads are FREE. Search and download functionalities are using the official Maven repository.

src.com.ibm.as400.access.Record Maven / Gradle / Ivy

There is a newer version: 11.1
Show newest version
///////////////////////////////////////////////////////////////////////////////
//
// JTOpen (IBM Toolbox for Java - OSS version)
//
// Filename: Record.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-2004 International Business Machines Corporation and
// others. All rights reserved.
//
///////////////////////////////////////////////////////////////////////////////
// @A2 11/21/2007 - Change to setField() method to calculation of the value for
//                  variableFieldLength.  Shift-in/shift-out characters need to
//                  be included for some CCSIDs.
//                  Similar change in getField for VARGRAPHIC fields.  The 2-byte
//                  length field (which preceeds the field data) indicates the 
//                  number of "graphic characters" (NOT the number of "bytes").
//                  Each graphic character is 2-bytes each.  Therefore, the code
//                  must multiply the length by 2 to read the correct number of
//                  bytes.
//                  This is opposite from a VARCHAR field... where the 2-byte
//                  length field (which preceeds the field data) indicates the 
//                  number of "bytes" of character data (NOT the number of 
//                  characters).  This is because some characters may be represented
//                  by a single byte or more than a single byte.
//                  Fix for CPS DB Item: 795LZ6 - DBCS issue with VARCHAR on JTOpen Record Level Access
///////////////////////////////////////////////////////////////////////////////

package com.ibm.as400.access;

import java.io.InputStream;
import java.io.OutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.CharConversionException;
import java.io.UnsupportedEncodingException;
import java.io.Serializable;
import java.beans.PropertyChangeSupport;
import java.beans.VetoableChangeSupport;
import java.beans.PropertyChangeListener;
import java.beans.VetoableChangeListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyVetoException;
import java.util.Vector;

/**
 *The Record class represents the data described by a RecordFormat object.
 *It can represent:
 *
    *
  • An entry in a data queue. *
  • The parameter data provided to or returned by a program call. *
  • A record to be written to or read from a file on the system. *
  • Any data returned from the system that needs to be converted *between IBM i format and Java format. *
*Record objects generate the following events: *
    *
  • {@link com.ibm.as400.access.RecordDescriptionEvent RecordDescriptionEvent} *
    The events fired are: *
      *
    • fieldModified() *
    *
  • PropertyChangeEvent *
  • VetoableChangeEvent *
*Examples * **/ public class Record implements Serializable { static final long serialVersionUID = 4L; // The server data for this record. private byte[] as400Data_; // Array of the field descriptions that describe the fields in this record. // We initialize from RecordFormat.getFieldDescriptions() during construction // or setRecordFormat(). private FieldDescription[] fieldDescriptions_; // Array of the fields that make up this record. private Object[] fields_; // Array containing the offset in as400Data_ for each field. // These values are only guaranteed to be valid if the record // does not contain dependent fields. private int[] fieldOffsets_; // Indicates if the record has dependent fields private boolean hasDependentFields_; // Indicates which fields have been converted to Java objects private boolean[] isConvertedToJava_; // Indicates which fields have been converted to server data in the as400Data_ array private boolean[] isConvertedToAS400_; // Name of the record private String name_ = ""; // Array indicating if a field is null private boolean[] nullFieldMap_; // Use default property change support private transient PropertyChangeSupport changes_; //@B5C // The record format object with which this record is associated private RecordFormat recordFormat_ = null; // The length of the record, in bytes int recordLength_; // The record number of this record int recordNumber_; long recordNumberLong_;//@RBA // Array to hold fields returned by getFields. This allows us to not // instantiate a new array every time getFields is done, which allows // us to cut down on garbage collection overhead. Object[] returnFields_; // The list of current veto listeners transient private VetoableChangeSupport vetos_; //@B5A //@B5D transient private Vector currentVetoListeners_ = new Vector(); // The list of current RecordDescriptionEvent listeners //@B5D transient private Vector currentRecordDescriptionListeners_ = new Vector(); // The list of RecordDescriptionEvent listeners transient private Vector recordDescriptionListeners_; //@B5C // The list of veto listeners //@B5D transient private Vector vetoListeners_ = new Vector(); /** *Constructs a Record object. **/ public Record() { initializeTransient(); //@B5A } /** *Constructs a Record object. It uses the RecordFormat specified. *The contents of the record will be initialized to their default values. The default *values are determined as follows: *
    *
  1. Use the value specified for the DFT keyword on the FieldDescription object *contained in the RecordFormat object for a particular field. *
  2. If no value was specified for the DFT keyword, use the default value from the *AS400DataType object specified when constructing the FieldDescription object for *a particular field. *
*@param recordFormat Describes the contents of this record. *@see com.ibm.as400.access.RecordFormat **/ public Record(RecordFormat recordFormat) { initializeTransient(); //@B5A initializeRecord(recordFormat); } /** *Constructs a Record object. It uses the record's name and RecordFormat specified. *The contents of the record will be initialized to their default values. The default *values are determined as follows: *
    *
  1. Use the value specified for the DFT keyword on the FieldDescription object for *a particular field. *
  2. If no value was specified for the DFT keyword, use the default value from the *AS400DataType object specified when constructing the FieldDescription object for *a particular field. *
*@param recordFormat Describes the contents of this record. *@param recordName The name to assign to the record. **/ public Record(RecordFormat recordFormat, String recordName) { this(recordFormat); // Verify parameters if (recordName == null) { throw new NullPointerException("recordName"); } // Set the name of the record name_ = recordName; } /** *Constructs a Record object. It uses the specified RecordFormat and a byte array *with which to initialize the contents of the record. *@param recordFormat Describes the contents of this record. *@param contents The contents to which to initialize the record. *
*Note: When using this object for the record level access classes, if *isVariableLength() *returns true for a field, the first two bytes of the data provided for *that field must contain the length of the valid data. However, the number of bytes *provided for *the data for the field must equal the maximum field length for the field. *@exception UnsupportedEncodingException If an error occurs when converting *the IBM i data to a Java Object. **/ public Record(RecordFormat recordFormat, byte[] contents) throws UnsupportedEncodingException { this(recordFormat, contents, 0); } /** *Constructs a Record object. It uses the specified the RecordFormat, a byte array *from which to initialize the contents of the record and the name of the record. *@param recordFormat Describes the contents of this record. *@param contents The contents to which to initialize the record. *
*Note: When using this object for the record level access classes, if isVariableLength() *returns true for a field, the first two bytes of the data provided for *that field must contain the length of the valid data. However, the number of bytes provided for *the data for the field must equal the maximum field length for the field. *@param recordName The name to assign to the record. *@exception UnsupportedEncodingException If an error occurs when converting *the IBM i data to a Java Object. **/ public Record(RecordFormat recordFormat, byte[] contents, String recordName) throws UnsupportedEncodingException { this(recordFormat, contents, 0, recordName); } /** *Constructs a Record object. It uses the specified RecordFormat and a byte array *from which to initialize the contents of the record. *@param recordFormat Describes the contents of this record. The recordFormat *must contain at least one field description. *@param contents The contents to which to initialize the record. *
*Note: When using this object for the record level access classes, if isVariableLength() *returns true for a field, the first two bytes of the data provided for *that field must contain the length of the valid data. However, the number of bytes provided for *the data for the field must equal the maximum field length for the field. *@param offset The offset in contents at which to start. The offset cannot *be less than zero. *@exception UnsupportedEncodingException If an error occurs when converting *the IBM i data to a Java Object. **/ public Record(RecordFormat recordFormat, byte[] contents, int offset) throws UnsupportedEncodingException { initializeTransient(); //@B5A // Verify parameters if (recordFormat == null) { throw new NullPointerException("recordFormat"); } if (recordFormat.getNumberOfFields() == 0) { throw new ExtendedIllegalArgumentException("recordFormat", ExtendedIllegalArgumentException.PARAMETER_VALUE_NOT_VALID); } if (contents == null) { throw new NullPointerException("contents"); } if (contents.length == 0) { throw new ExtendedIllegalArgumentException("contents", ExtendedIllegalArgumentException.LENGTH_NOT_VALID); } if (offset < 0) { throw new ExtendedIllegalArgumentException("offset", ExtendedIllegalArgumentException.RANGE_NOT_VALID); } // Set the instance data recordFormat_ = recordFormat; fieldDescriptions_ = recordFormat.getFieldDescriptions(); hasDependentFields_ = recordFormat_.getHasDependentFields(); fields_ = new Object[fieldDescriptions_.length]; returnFields_ = new Object[fieldDescriptions_.length]; fieldOffsets_ = new int[fieldDescriptions_.length]; // Initialize the offset values isConvertedToJava_ = new boolean[fieldDescriptions_.length]; isConvertedToAS400_ = new boolean[fieldDescriptions_.length]; nullFieldMap_ = new boolean[fields_.length]; FieldDescription fd = null; int fieldOffset = 0; int length = 0; // Reset the record length recordLength_ = 0; // This loop sets the offsets for the fields and also determines the // record length of the record. for (int i = 0; i < fields_.length; ++i) { fd = fieldDescriptions_[i]; fieldOffsets_[i] = fieldOffset; if (fd instanceof VariableLengthFieldDescription) { if (((VariableLengthFieldDescription)fd).isVariableLength()) { // Add two bytes for the length of the field fieldOffset += 2; recordLength_ += 2; } } length = fd.getDataType().getByteLength(); fieldOffset += length; recordLength_ += length; if (!hasDependentFields_) { isConvertedToAS400_[i] = true; } isConvertedToJava_[i] = false; } // Allocate the space for as400Data_ now that we know the record length as400Data_ = new byte[recordLength_]; if (!hasDependentFields_) { // Go ahead and copy the contents to as400Data_ try { System.arraycopy(contents, offset, as400Data_, 0, as400Data_.length); } catch(ArrayIndexOutOfBoundsException e) { // Need to reset isConverted... state for (int i = 0; i < isConvertedToAS400_.length; ++i) { isConvertedToAS400_[i] = false; } throw e; } } else { // Initialize the contents of the record with the specified byte array setContents(contents, offset); } } /** *Constructs a Record object. It uses the specified RecordFormat, a byte array *from which to initialize the record's contents and the record's name. *@param recordFormat Describes the contents of this record. *@param contents The contents to which to initialize the record. *
*Note: When using this object for the record level access classes, if isVariableLength() *returns true for a field, the first two bytes of the data provided for *that field must contain the length of the valid data. However, the number of bytes provided for *the data for the field must equal the maximum field length for the field. *@param offset The offset in contents at which to start. The offset cannot *be less than zero. *@param recordName The name to assign to the record. *@exception UnsupportedEncodingException If an error occurs when converting *the IBM i data to a Java Object. **/ public Record(RecordFormat recordFormat, byte[] contents, int offset, String recordName) throws UnsupportedEncodingException { this(recordFormat, contents, offset); // Verify parameters if (recordName == null) { throw new NullPointerException("recordName"); } // Set the name name_ = recordName; } /** *Adds a listener to be notified when the value of any bound *property is changed. The propertyChange method will be *be called. *@see #removePropertyChangeListener *@param listener The PropertyChangeListener. **/ public void addPropertyChangeListener(PropertyChangeListener listener) //@B5C { if (listener == null) { throw new NullPointerException("listener"); } if (changes_ == null) changes_ = new PropertyChangeSupport(this); changes_.addPropertyChangeListener(listener); } /** *Adds a listener to be notified when a RecordDescriptionEvent is fired. *@see #removeRecordDescriptionListener *@param listener The RecordDescriptionListener. **/ public void addRecordDescriptionListener(RecordDescriptionListener listener) //@B5C { if (listener == null) { throw new NullPointerException("listener"); } if (recordDescriptionListeners_ == null) recordDescriptionListeners_ = new Vector(); recordDescriptionListeners_.addElement(listener); //@B5D currentRecordDescriptionListeners_ = (Vector)recordDescriptionListeners_.clone(); } /** *Adds a listener to be notified when the value of any constrained *property is changed. *The vetoableChange method will be called. *@see #removeVetoableChangeListener *@param listener The VetoableChangeListener. **/ public void addVetoableChangeListener(VetoableChangeListener listener) //@B5C { if (listener == null) { throw new NullPointerException("listener"); } //@B5D vetoListeners_.addElement(listener); //@B5D currentVetoListeners_ = (Vector)vetoListeners_.clone(); if (vetos_ == null) vetos_ = new VetoableChangeSupport(this); vetos_.addVetoableChangeListener(listener); //@B5A } //@G0A /** * Tests this Record object for equality with the given object. * @param obj The Object to compare. * @return true if obj is a Record object and its record length, record number, * record name, dependent fields, field values, and key field values equal this Record's; * false otherwise. Since there are so many pieces of data that determine whether * or not one Record equals another, the programmer may also want to consider using * Record.toString() and comparing the Strings for equality. **/ public boolean equals(Object obj) { if (obj == null) return false; try { Record cmp = (Record)obj; if (cmp.recordLength_ == recordLength_ && cmp.recordNumber_ == recordNumber_ && cmp.recordNumberLong_ == recordNumberLong_ &&//@RBA cmp.hasDependentFields_ == hasDependentFields_ && (cmp.name_ == null ? (name_ == null) : cmp.name_.equals(name_))) { int n = getNumberOfFields(); int cn = cmp.getNumberOfFields(); if (n == cn) { int nk = getNumberOfKeyFields(); int cnk = getNumberOfKeyFields(); if (nk == cnk) { for (int i=0; i *Note: If a field is a variable-length field, the first two bytes of data for the field *contain the length of the valid data for the field. However, the number of bytes provided for the *field is the maximum length of the field as specified by the FieldDescription object for the *field in the record format for this object.
*The record format for the record must be set prior to invoking this method. *@see Record#Record(com.ibm.as400.access.RecordFormat) *@see Record#setRecordFormat *@return The contents of this record. *@exception CharConversionException If an error occurs when converting *the contents of a field to IBM i data. *@exception UnsupportedEncodingException If an error occurs when converting *the contents of a field to IBM i data. **/ public byte[] getContents() throws CharConversionException, UnsupportedEncodingException { if (recordFormat_ == null) { throw new ExtendedIllegalStateException("recordFormat", ExtendedIllegalStateException.PROPERTY_NOT_SET); } if (hasDependentFields_) { // If the record has dependent fields, we do the conversion now and return the contents. // For each field in fields_, use the recordFormat_ object to get the field // description. Use the data type object associated with the field description to translate // the Object representing the field into bytes to be placed in the byte array. // Repeat this process for each field. // If the field is a variable length field (i.e the VARLEN value is greater than 0), the first // two bytes of the data is the length of the data. // Determine the number of bytes that make of the record AS400DataType dType; int offset = 0; if (Trace.traceOn_) { Trace.log(Trace.INFORMATION, "recordLength_: " + String.valueOf(recordLength_)); } byte[] toBytes = new byte[recordLength_]; FieldDescription f; int variableFieldLength; for (int i = 0; i < fields_.length; ++i) { // Convert each field to server data f = fieldDescriptions_[i]; // Check for possible variable length field if (f instanceof VariableLengthFieldDescription) { if (((VariableLengthFieldDescription)f).isVariableLength()) { // Set the two byte length portion of the contents if (fields_[i] == null) { variableFieldLength = 0; } else { variableFieldLength = (f instanceof HexFieldDescription)? ((byte[])fields_[i]).length : ((String)fields_[i]).length(); } BinaryConverter.unsignedShortToByteArray(variableFieldLength, toBytes, offset); offset += 2; } } // Whether the field is variable length or not we still write out the maximum number // of bytes for the field. This is the required format for variable length data for record // level access. dType = f.getDataType(); if (fields_[i] != null) { // Field has a value; convert it to server data offset += dType.toBytes(fields_[i], toBytes, offset); } else { // Field is null; use the default value for the server data to serve as a place holder for // the field. offset += dType.toBytes(dType.getDefaultValue(), toBytes, offset); } } return toBytes; } // No dependent fields. return as400Data_; } /** *Writes the contents of this record to the specified output stream. *Each field's contents will be written to out *based on the field description for the *field that is provided by the record format specified on construction of this object. *The data type object for the field description will be used to do any necessary conversion *of the contents of the field.
*Note: If a field is a variable-length field, the first two bytes of data for the field *contain the length of the valid data for the field. However, the number of bytes provided for the *field is the maximum length of the field as specified by the FieldDescription object for the *field in the record format for this object. *
*The record format for the record must be set prior to invoking this method. *@see Record#Record(com.ibm.as400.access.RecordFormat) *@see Record#setRecordFormat *@param out The stream to which to write the contents of the record. *@exception IOException If an I/O error occurs while communicating with the system. **/ public void getContents(OutputStream out) throws IOException { if (out == null) { throw new NullPointerException("out"); } out.write(getContents()); } /** *Returns the value of the field by index. *
*The record format for the record must be set prior to invoking this method. *@see Record#Record(com.ibm.as400.access.RecordFormat) *@see Record#setRecordFormat *@param index The ordinal position of the field in the record. This value must * be between 0 and getNumberOfFields() - 1 inclusive. *@return The contents of the requested field. *@exception UnsupportedEncodingException If an error occurs when converting *the IBM i data to a Java Object. **/ public Object getField(int index) throws UnsupportedEncodingException { if (recordFormat_ == null) { throw new ExtendedIllegalStateException("recordFormat", ExtendedIllegalStateException.PROPERTY_NOT_SET); } if (index < 0 || index > fields_.length - 1) { throw new ExtendedIllegalArgumentException("index", ExtendedIllegalArgumentException.RANGE_NOT_VALID); } if (isConvertedToJava_[index]) { // Field already converted; just return it return fields_[index]; } // Field has not yet been converted. We will only get here if // the record has no dependent fields so we can go ahead and count // on the fieldOffsets_ array being valid. FieldDescription f = fieldDescriptions_[index]; AS400DataType dType = f.getDataType(); int variableFieldLength; int offset = fieldOffsets_[index]; // Check for possible variable length field if (f instanceof VariableLengthFieldDescription) { if (((VariableLengthFieldDescription)f).isVariableLength()) { // Get the number of bytes returned for the field variableFieldLength = BinaryConverter.byteArrayToUnsignedShort(as400Data_, offset); if (f instanceof DBCSGraphicFieldDescription) //@A2A { //@A2A // NOTE: The 2-byte length field in a VARGRAPHIC field is the number of "characters" and // is NOT the number of "bytes". Each VARGRAPHIC "character" is represented by // two bytes. So, we need to multiply the variableFieldLength by two for VARGRAPHIC. // Note: The 2-byte length field in a VARCHAR field is the number of "bytes", so the // variableFieldLength is correct and should not be modified. variableFieldLength *= 2; //@A2A } //@A2A offset += 2; // Convert the server data to a Java object if ((f instanceof HexFieldDescription)) { // Field is a hex field, no conversion is done on the data byte[] b = new byte[variableFieldLength]; System.arraycopy(as400Data_, offset, b, 0, variableFieldLength); fields_[index] = b; } else { // Field requires conversion based on ccsid //@B5D Converter c = new Converter(((AS400Text)dType).getCcsid()); //@B5C ConverterImpl c = ((AS400Text)dType).getConverter(); //@B5A @F0C fields_[index] = c.byteArrayToString(as400Data_, offset, variableFieldLength); } } else { // Field is not variable length fields_[index] = dType.toObject(as400Data_, offset); } } else { // Not a VariableLengthFieldDescription fields_[index] = dType.toObject(as400Data_, offset); } if (recordDescriptionListeners_ != null) fireFieldModifiedEvent(); isConvertedToJava_[index] = true; return fields_[index]; } /** *Returns the value of the field by name. *
*The record format for the record must be set prior to invoking this method. *@see Record#Record(com.ibm.as400.access.RecordFormat) *@see Record#setRecordFormat *@param name The name of the field. *@return The contents of the requested field. *@exception UnsupportedEncodingException If an error occurs when converting *the IBM i data to a Java Object. **/ public Object getField(String name) throws UnsupportedEncodingException { if (recordFormat_ == null) { throw new ExtendedIllegalStateException("recordFormat", ExtendedIllegalStateException.PROPERTY_NOT_SET); } return getField(recordFormat_.getIndexOfFieldName(name)); } /** *Returns the value of the field by index, as an unconverted byte array. *
*The record format for the record must be set prior to invoking this method. *@see Record#Record(com.ibm.as400.access.RecordFormat) *@see Record#setRecordFormat *@param index The ordinal position of the field in the record. This value must * be between 0 and getNumberOfFields() - 1 inclusive. *@return The unconverted contents of the requested field. **/ public byte[] getFieldAsBytes(int index) { if (recordFormat_ == null) { throw new ExtendedIllegalStateException("recordFormat", ExtendedIllegalStateException.PROPERTY_NOT_SET); } if (index < 0 || index > fields_.length - 1) { throw new ExtendedIllegalArgumentException("index", ExtendedIllegalArgumentException.RANGE_NOT_VALID); } byte[] fieldAsBytes = null; int fieldOffset = 0; // offset to start of field in as400Data_ int fieldByteLength = 0; // length of field, including length bytes if any if (hasDependentFields_) // The record has dependent fields, so fieldOffsets_ is unreliable. { // For each field description in the recordFormat_ object, until we reach the field of interest, determine the field offset and length. // If a field is a variable length field, we must account for the two bytes worth of length data which precede the actual data for the field. int offsetToNextField = 0; for (int i = 0; i <= index; ++i) { fieldOffset = offsetToNextField; FieldDescription f = fieldDescriptions_[i]; AS400DataType dType = f.getDataType(); fieldByteLength = dType.getByteLength(); int lengthDependField = recordFormat_.getLengthDependency(i); int offsetDependField = recordFormat_.getOffsetDependency(i); // Check for offset dependent field if (offsetDependField != -1) { // Set offset to value specified in the field this field depends on fieldOffset = ((Number)fields_[offsetDependField]).intValue(); } if (lengthDependField != -1) { // The length of this field is contained in the field that this field depends on. // Because the field depended on must exist prior to this field in the byte array, // its value has already been determined. fieldByteLength = ((Number)fields_[lengthDependField]).intValue(); } // Check for possible variable length field if (f instanceof VariableLengthFieldDescription && ((VariableLengthFieldDescription)f).isVariableLength()) { fieldByteLength += 2; // allow for the 2 leading "length bytes" } // Prepare to examine the next field. offsetToNextField = fieldOffset + fieldByteLength; } // for ... } // if ... else // no dependent fields, so fieldOffsets_ is reliable { fieldOffset = fieldOffsets_[index]; FieldDescription f = fieldDescriptions_[index]; AS400DataType dType = f.getDataType(); fieldByteLength = dType.getByteLength(); // Check for possible variable length field. if (f instanceof VariableLengthFieldDescription && ((VariableLengthFieldDescription)f).isVariableLength()) { // Get the number of bytes returned for the field. // Whether the field is variable length or not we still write out the maximum number // of bytes for the field. This is the required format for variable length data for record level access. fieldByteLength += 2; // allow for the 2 leading "length bytes" } } fieldAsBytes = new byte[fieldByteLength]; System.arraycopy(as400Data_, fieldOffset, fieldAsBytes, 0, fieldAsBytes.length); return fieldAsBytes; } /** *Returns the value of the field by name, as an unconverted byte array. *
*The record format for the record must be set prior to invoking this method. *@see Record#Record(com.ibm.as400.access.RecordFormat) *@see Record#setRecordFormat *@param name The name of the field. *@return The unconverted contents of the requested field. **/ public byte[] getFieldAsBytes(String name) { if (recordFormat_ == null) { throw new ExtendedIllegalStateException("recordFormat", ExtendedIllegalStateException.PROPERTY_NOT_SET); } return getFieldAsBytes(recordFormat_.getIndexOfFieldName(name)); } /** *Returns the values of the fields in the record. *@return The values of the fields in the record. An array of size zero is *returned if the record format has not been set. *@exception UnsupportedEncodingException If an error occurs when converting *the IBM i data to a Java Object. **/ public Object[] getFields() throws UnsupportedEncodingException { if (recordFormat_ == null) { return new Object[0]; } // Get each field individually in the event that conversion has not yet been done. for (int i = 0; i < fields_.length; ++i) { returnFields_[i] = getField(i); } return returnFields_; } /** *Returns the values of the key fields in the record. *@return The values of the key fields in the record. *An array of length 0 is returned if the record format has not been set *or if no key fields exist. *@exception UnsupportedEncodingException If an error occurs when converting *the IBM i data to a Java Object. **/ public Object[] getKeyFields() throws UnsupportedEncodingException { if (recordFormat_ == null) { return new Object[0]; } Object[] keyFields = new Object[recordFormat_.getNumberOfKeyFields()]; String[] keyFieldNames = recordFormat_.getKeyFieldNames(); for (int i = 0; i < keyFields.length; ++i) { keyFields[i] = getField(keyFieldNames[i]); } return keyFields; } /** *Returns the values of the key fields in a byte array. *@return The values of the key fields in a byte array. *A byte array of length 0 is returned if the record format has not been set *or if no key fields exist. **/ public byte[] getKeyFieldsAsBytes() { if (recordFormat_ == null) { return new byte[0]; } ByteArrayOutputStream keyAsBytes = new ByteArrayOutputStream(); String[] keyFieldNames = recordFormat_.getKeyFieldNames(); AS400DataType dt = null; FieldDescription fd = null; int length; int index; for (int i = 0; i < keyFieldNames.length; ++i) { index = recordFormat_.getIndexOfFieldName(keyFieldNames[i]); fd = fieldDescriptions_[index]; dt = fd.getDataType(); length = dt.getByteLength(); if (fd instanceof VariableLengthFieldDescription && ((VariableLengthFieldDescription)fd).isVariableLength()) { length += 2; } keyAsBytes.write(as400Data_, fieldOffsets_[index], length); } return keyAsBytes.toByteArray(); } /** *Returns the number of fields in this record. *@return The number of fields in this record. Zero is returned if the record *format has not been set. **/ public int getNumberOfFields() { return (recordFormat_ == null)? 0 : fields_.length; } /** *Returns the number of key fields in this record. *@return The number of key fields in this record. Zero is returned if the record *format has not been set. **/ public int getNumberOfKeyFields() { return (recordFormat_ == null)? 0 : recordFormat_.getNumberOfKeyFields(); } /** *Returns the record format for this record. *@return The record format for this record. If the record format has *not been set, null is returned. **/ public RecordFormat getRecordFormat() { return recordFormat_; } /** *Returns the record length of this record. *@return The record length of this record. Zero is returned if the record format *for this object has not been set. **/ public int getRecordLength() { return recordLength_; } /** *Returns the record name for this record. *@return The name of this record. If the name has not been set, *an empty string is returned. **/ public String getRecordName() { return name_; } /** *Returns the record number of this record. This method only pertains to the *record level access classes. *@return The record number of this record. Zero is returned if no record number has been set. **/ public int getRecordNumber() { return recordNumber_; } //@RBA /** *Returns the record number in long type of this record. This method only pertains to the *record level access classes. *@return The record number of this record. Zero is returned if no record number has been set. **/ public long getRecordNumberLong() { return recordNumberLong_; } //@G0A /** * Returns a hash code value for this Record. This is useful if Record objects * need to be placed into Hashtables. * @return The hash code. **/ public int hashCode() { return recordNumber_ == 0 ? recordLength_ : recordNumber_; } /** *Initializes this record to its default values based on the specified record format. *@param recordFormat The record format for this record. **/ private void initializeRecord(RecordFormat recordFormat) { // Verify parameters if (recordFormat == null) { throw new NullPointerException("recordFormat"); } if (recordFormat.getNumberOfFields() == 0) { throw new ExtendedIllegalArgumentException("recordFormat", ExtendedIllegalArgumentException.PARAMETER_VALUE_NOT_VALID); } // Set the instance data recordFormat_ = recordFormat; fieldDescriptions_ = recordFormat.getFieldDescriptions(); hasDependentFields_ = recordFormat_.getHasDependentFields(); fields_ = new Object[fieldDescriptions_.length]; returnFields_ = new Object[fieldDescriptions_.length]; fieldOffsets_ = new int[fieldDescriptions_.length]; isConvertedToJava_ = new boolean[fieldDescriptions_.length]; isConvertedToAS400_ = new boolean[fieldDescriptions_.length]; nullFieldMap_ = new boolean[fieldDescriptions_.length]; // Initialize the contents of the record to the fieldDescription's default value. // Initialize the nullFieldMap_ to false values. Initialize the fieldOffsets_ array // to the appropriate offset. Object obj; FieldDescription fd = null; AS400DataType dType = null; byte[] lenAsBytes = new byte[2]; int offset = 0; int variableFieldLength; ByteArrayOutputStream b = new ByteArrayOutputStream(); // Reset recordLength_ recordLength_ = 0; for (int i = 0; i < fields_.length; ++i) { // Get the default value for this field fd = fieldDescriptions_[i]; obj = fd.getDFT(); // Set the offset of this field fieldOffsets_[i] = offset; // Set the Java value of the field // @B0C: Check for DFT of current or null if (obj == null) // DFT was not set, or was set to null or current { if (fd.isDFTNull()) // DFT was set to null => write 'null' to the field { fields_[i] = fd.getDataType().getDefaultValue(); if (fieldDescriptions_[i].getALWNULL()) nullFieldMap_[i] = true; else nullFieldMap_[i] = false; } else if (fd.isDFTCurrent()) // DFT was set to current => write the appropriate value { fields_[i] = fd.getDFTCurrentValue(); } else // DFT was not set => write 'null' to the field { fields_[i] = fd.getDataType().getDefaultValue(); if (fieldDescriptions_[i].getALWNULL()) { nullFieldMap_[i] = true; fields_[i] = null; //@B1A Set the field value to null as well. } else nullFieldMap_[i] = false; } } else { fields_[i] = obj; // DFT was set => write the default value } // Check for possible variable length field if (fd instanceof VariableLengthFieldDescription) { if (((VariableLengthFieldDescription)fd).isVariableLength()) { // Set the two byte length portion of the contents if (obj == null) { variableFieldLength = 0; } else { variableFieldLength = (fd instanceof HexFieldDescription)? ((byte[])obj).length : ((String)obj).length(); } BinaryConverter.unsignedShortToByteArray(variableFieldLength, lenAsBytes, 0); b.write(lenAsBytes, 0, 2); offset += 2; recordLength_ += 2; } } // Whether the field is variable length or not we still write out the maximum number // of bytes for the field. This is the required format for variable length data for record // level access. dType = fd.getDataType(); if (fields_[i] != null) //@B1A { // Field has a value; convert it to server data b.write(dType.toBytes(fields_[i]), 0, dType.getByteLength()); } else //@B1A { // Field is null; use the default value for the server data to serve as a place holder for // the field. b.write(dType.toBytes(dType.getDefaultValue()), 0, dType.getByteLength()); //@B1A } // Indicate the field is in a converted state isConvertedToJava_[i] = true; isConvertedToAS400_[i] = true; // Determine the next offset value and increment the record length appropriately offset += fd.getDataType().getByteLength(); recordLength_ += fd.getDataType().getByteLength(); } // Allocate the space for as400Data_ as400Data_ = b.toByteArray(); if (recordDescriptionListeners_ != null) fireFieldModifiedEvent(); } //@D0A void initializeTextObjects(AS400 system) { // First do our record format if (recordFormat_ != null) recordFormat_.initializeTextObjects(system); // Then do all of our internal fields if (fieldDescriptions_ != null) { for (int i=0; i *The record format for the record must be set prior to invoking this method. *@see Record#Record(com.ibm.as400.access.RecordFormat) *@see Record#setRecordFormat *@param index The index of the field. The index must be between *0 and getNumberOfFields() - 1. *@return true if the field is null; false otherwise. **/ public boolean isNullField(int index) { if (recordFormat_ == null) { throw new ExtendedIllegalStateException("recordFormat", ExtendedIllegalStateException.PROPERTY_NOT_SET); } if (index < 0 || index > fields_.length - 1) { throw new ExtendedIllegalArgumentException("index", ExtendedIllegalArgumentException.RANGE_NOT_VALID); } return nullFieldMap_[index]; } /** *Indicates if the field is null. *
*The record format for the record must be set prior to invoking this method. *@see Record#Record(com.ibm.as400.access.RecordFormat) *@see Record#setRecordFormat *@param name The name of the field. *@return true if the field is null; false otherwise. **/ public boolean isNullField(String name) { if (recordFormat_ == null) { throw new ExtendedIllegalStateException("recordFormat", ExtendedIllegalStateException.PROPERTY_NOT_SET); } return nullFieldMap_[recordFormat_.getIndexOfFieldName(name)]; } /** *Reads the number of bytes requested. This method will loop until *either length bytes have been read or until the end of file is reached. *@param in The Inputstream from which to read. *@param buf The buffer from which to read the data. *@param offset The offset within buf array from which to start reading. *@param length The number of bytes to read. *@returns The number of bytes read. *@exception IOException If an I/O error occurs while communicating with the system. **/ private int readFromStream(InputStream in, byte[] buf, int offset, int length) throws IOException { boolean endOfFile = false; int bytesRead = 0; while ((bytesRead < length) && !endOfFile) { int temp = in.read(buf, offset+bytesRead, length - bytesRead); if (temp == -1) { endOfFile = true; } else { bytesRead += temp; } } return bytesRead; } /** *Overrides the ObjectInputStream.readObject() method in order to return any *transient parts of the object to there properly initialized state. * I.e we in effect *call the null constructor. By calling ObjectInputStream.defaultReadObject() *we restore the state of any non-static and non-transient variables. We *then continue on to restore the state (as necessary) of the remaining varaibles. *@param in The input stream from which to deserialize the object. *@exception ClassNotFoundException If the class being deserialized is not found. *@exception IOException If an error occurs while communicating with the system. **/ private void readObject(java.io.ObjectInputStream in) throws ClassNotFoundException, IOException { in.defaultReadObject(); initializeTransient(); //@B5A //@B5D currentVetoListeners_ = new Vector(); //@B5D currentRecordDescriptionListeners_ = new Vector(); //@B5D recordDescriptionListeners_ = new Vector(); //@B5D vetoListeners_ = new Vector(); } /** *Removes a listener from the change list. *If the listener is not on the list, do nothing. *@see #addPropertyChangeListener *@param listener The PropertyChangeListener. **/ public void removePropertyChangeListener(PropertyChangeListener listener) //@B5C { if (listener == null) { throw new NullPointerException("listener"); } if (changes_ != null) changes_.removePropertyChangeListener(listener); } /** *Removes a listener from the record description listeners list. *If the listener is not on the list, do nothing. *@see #addRecordDescriptionListener *@param listener The RecordDescriptionListener. **/ public void removeRecordDescriptionListener(RecordDescriptionListener listener) //@B5C { if (listener == null) { throw new NullPointerException("listener"); } if (recordDescriptionListeners_ != null) recordDescriptionListeners_.removeElement(listener); //@B5D currentRecordDescriptionListeners_ = (Vector)recordDescriptionListeners_.clone(); } /** *Removes a listener from the veto change listeners list. *If the listener is not on the list, do nothing. *@see #addVetoableChangeListener *@param listener The VetoableChangeListener. **/ public void removeVetoableChangeListener(VetoableChangeListener listener) //@B5C { if (listener == null) { throw new NullPointerException("listener"); } //@B5D vetoListeners_.removeElement(listener); //@B5D currentVetoListeners_ = (Vector)vetoListeners_.clone(); if (vetos_ != null) vetos_.removeVetoableChangeListener(listener); //@B5A } /** *Sets the contents of this record from the specified byte array. *The contents of each field will be set from contents *based on the field description for the *field that is provided by the record format specified on construction of this object. *The data type object for the field description will be used to do any necessary conversion *of the data from the byte array.
*Note: When using this object for the record level access classes, if isVariableLength() *returns true for a field, the first two bytes of the data provided for *that field must contain the length of the valid data. However, the number of bytes provided for *the data for the field must equal the maximum field length for the field. *
*The record format for the record must be set prior to invoking this method. *@see Record#Record(com.ibm.as400.access.RecordFormat) *@see Record#setRecordFormat *@param contents The data with which to set the contents of this record. *@exception UnsupportedEncodingException If an error occurs when converting *the IBM i data to a Java Object. **/ public void setContents(byte[] contents) throws UnsupportedEncodingException { setContents(contents, 0); } /** *Sets the contents of this record from the specified byte array. *The contents of each field will be set from contents *based on the field description for the *field that is provided by the record format specified on construction of this object. *The data type object for the field description will be used to do any necessary conversion *of the data from the byte array.
*Note: When using this object for the record level access classes, if isVariableLength() *returns true for a field, the first two bytes of the data provided for *that field must contain the length of the valid data. However, the number of bytes provided for *the data for the field must equal the maximum field length for the field. *
*The record format for the record must be set prior to invoking this method. *@see Record#Record(com.ibm.as400.access.RecordFormat) *@see Record#setRecordFormat *@param contents The data with which to set the contents of this record. *@param offset The offset in contents at which to start. *@exception UnsupportedEncodingException If an error occurs when converting *the IBM i data to a Java Object. **/ public void setContents(byte[] contents, int offset) throws UnsupportedEncodingException { if (recordFormat_ == null) { throw new ExtendedIllegalStateException("recordFormat", ExtendedIllegalStateException.PROPERTY_NOT_SET); } if (contents == null) { throw new NullPointerException("contents"); } if (contents.length == 0) { throw new ExtendedIllegalArgumentException("contents", ExtendedIllegalArgumentException.LENGTH_NOT_VALID); } if (offset < 0 || offset >= contents.length) { throw new ExtendedIllegalArgumentException("offset (" + offset + ")", ExtendedIllegalArgumentException.RANGE_NOT_VALID); } if (hasDependentFields_) { // Record has dependent fields; convert now. // For each field description in the recordFormat_ object, use the field description's // data type object to translate the appropriate number of bytes in contents to an Object. // Repeat this process for each field description in the record format. // If the field is a variable length field, we must account for the two bytes worth of length // data which precede the actual data for the field. AS400DataType dType; int numFields = recordFormat_.getNumberOfFields(); FieldDescription f; int lengthDependField; int offsetDependField; int variableFieldLength; recordLength_ = 0; // Reset the record length for (int i = 0; i < numFields; ++i) { f = fieldDescriptions_[i]; lengthDependField = recordFormat_.getLengthDependency(i); offsetDependField = recordFormat_.getOffsetDependency(i); dType = f.getDataType(); int length = dType.getByteLength(); // Check for offset dependent field if (offsetDependField != -1) { // Set offset to value specified in the field this field depends on offset = ((Number)fields_[offsetDependField]).intValue(); } if (lengthDependField != -1) { AS400DataType newDataType = null; // The length of this field is contained in the field that this field depends on // Because the field depended on must exist prior to this field in the byte array, // its value has already been determined. length = ((Number)fields_[lengthDependField]).intValue(); // @A1A: Check if f is variable length.. If so // we need to bump the offset by two // to get to the actual data and bump the record length by two. boolean varLen = false; if (f instanceof VariableLengthFieldDescription && ((VariableLengthFieldDescription)f).isVariableLength()) { offset += 2; recordLength_ += 2; varLen = true; } // End @A1A // Convert the server data to a Java object if (f instanceof HexFieldDescription) { // Field is a hex field, setDataType to indicate correct length newDataType = new AS400ByteArray(length); } else if (f instanceof ArrayFieldDescription) { newDataType = new AS400Array(((AS400Array)dType).getType(), length); } else { // character field - setDataType to indicate correct length AS400Text dtText = (AS400Text)dType; //@B6A //@B6D newDataType = new AS400Text(length, ((AS400Text)dType).getCcsid()); newDataType = new AS400Text(length, dtText.getCcsid()); //@F0C ((AS400Text)newDataType).setConverter(dtText.getConverter()); //@F0C } if (!varLen) //@A1A: If field is variable length need to preserve { // maximum field length f.setDataType(newDataType); } fields_[i] = newDataType.toObject(contents, offset); recordLength_ += f.getDataType().getByteLength(); } // Check for possible variable length field else if (f instanceof VariableLengthFieldDescription) { if (((VariableLengthFieldDescription)f).isVariableLength()) { // Get the number of bytes returned for the field variableFieldLength = BinaryConverter.byteArrayToUnsignedShort(contents, offset); offset += 2; recordLength_ += 2; // Convert the server data to a Java object if ((f instanceof HexFieldDescription)) { // Field is a hex field, no conversion is done on the data byte[] b = new byte[variableFieldLength]; System.arraycopy(contents, offset, b, 0, variableFieldLength); fields_[i] = b; } else { // Field requires conversion based on ccsid //@B5D Converter c = new Converter(((AS400Text)dType).getCcsid()); //@B5C ConverterImpl c = ((AS400Text)dType).getConverter(); //@B5A @F0C fields_[i] = c.byteArrayToString(contents, offset, variableFieldLength); } recordLength_ += dType.getByteLength(); } else { // Field is not variable length fields_[i] = dType.toObject(contents, offset); recordLength_ += dType.getByteLength(); } } else { // Not a VariableLengthFieldDescription fields_[i] = dType.toObject(contents, offset); recordLength_ += dType.getByteLength(); } // Whether the field is variable length or not, we are always given the maximum // number of bytes for the field in the byte array. offset += length; isConvertedToJava_[i] = true; isConvertedToAS400_[i] = false; } if (recordDescriptionListeners_ != null) fireFieldModifiedEvent(); } else { // No dependent fields; we can convert on the fly as necessary if (contents.length - offset < as400Data_.length) { Trace.log(Trace.ERROR, "Byte array has insufficient length for record. contents length: " + contents.length + ", offset: " + offset + ", record length: " + as400Data_.length); throw new ExtendedIllegalArgumentException("contents.length (" + contents.length + "), offset (" + offset + "), recordLength (" + as400Data_.length + ")", ExtendedIllegalArgumentException.RANGE_NOT_VALID); } System.arraycopy(contents, offset, as400Data_, 0, as400Data_.length); // Indicate that no fields have been converted yet for (int i = 0; i < isConvertedToJava_.length; ++i) { isConvertedToJava_[i] = false; isConvertedToAS400_[i] = true; } } } /** *Sets the contents of this record from the specified input stream. *The contents of each field will be set from in based on the field description for the *field that is provided by the record format specified on construction of this object. *The data type object for the field description will be used to do any necessary conversion *of the data from the input stream.
*Note: When using this object for the record level access classes, if isVariableLength() *returns true for a field, the first two bytes of the data provided for *that field must contain the length of the data. *
*The record format for the record must be set prior to invoking this method. *@see Record#Record(com.ibm.as400.access.RecordFormat) *@see Record#setRecordFormat *@param in The stream from which to read the data. *@exception IOException If an I/O error occurs while communicating with the system. **/ public void setContents(InputStream in) throws IOException { if (recordFormat_ == null) { throw new ExtendedIllegalStateException("recordFormat", ExtendedIllegalStateException.PROPERTY_NOT_SET); } if (in == null) { throw new NullPointerException("in"); } AS400DataType dType; byte[] contents = new byte[recordLength_]; if (readFromStream(in, contents, 0, recordLength_) != recordLength_) { throw new ExtendedIOException("Unable to read " + String.valueOf(recordLength_) + "bytes", ExtendedIOException.UNKNOWN_ERROR); } setContents(contents, 0); } /** *Sets the contents of the field at index to value. *
*The record format for the record must be set prior to invoking this method. *@see Record#Record(com.ibm.as400.access.RecordFormat) *@see Record#setRecordFormat *@param index The position in this record of the field whose contents are to be set. The index must be between 0 and getNumberOfFields() - 1. *@param value The value to which to set the contents of the field. Specify null for *value to indicate that the field is null. **/ public void setField(int index, Object value) { if (recordFormat_ == null) { throw new ExtendedIllegalStateException("recordFormat", ExtendedIllegalStateException.PROPERTY_NOT_SET); } if (index < 0 || index > fields_.length - 1) { throw new ExtendedIllegalArgumentException("index", ExtendedIllegalArgumentException.RANGE_NOT_VALID); } fields_[index] = value; if (recordDescriptionListeners_ != null) fireFieldModifiedEvent(); if (value == null) { nullFieldMap_[index] = true; } //@B0A else { nullFieldMap_[index] = false; } isConvertedToJava_[index] = true; byte[] convertedFieldBytes = null; //@A2A if (!hasDependentFields_) { // Keep the contents of as400Data_ up to date so that // getContents does not need to do any translation int offset = fieldOffsets_[index]; int variableFieldLength=0; //Initialize @A2C FieldDescription f = fieldDescriptions_[index]; // Check for possible variable length field if (f instanceof VariableLengthFieldDescription) { if (((VariableLengthFieldDescription)f).isVariableLength()) { // Set the two byte length portion of the contents if (fields_[index] == null) { // variableFieldLength = 0; Already set to zero, so no-op //@A2D } else { try { //@A2A // For variable length fields there is a two-byte length field that // needs to be calculated. Cannot simply use a String.length() method // on the input parameter "value", because it may need to be converted // to the ccsid of the target sytem which could result in a different // length string (i.e. DBCS which could add shift-in and shift-out // characters). Unicode "characters" may be represented by multiple // "bytes", hence the need to carefully calculate the "number of bytes" // for the variableFieldLength (not the number of characters). // Therefore, extract the ccsid, convert the data, and save the length // of the result in variableFieldLength. AS400DataType tmpDataType = f.getDataType(); //@A2A if (tmpDataType instanceof AS400Text) //@A2A { //@A2A int tmpCcsid = ((AS400Text)tmpDataType).getCcsid(); //@A2A convertedFieldBytes = CharConverter.stringToByteArray(tmpCcsid, (String)fields_[index]); //@A2A variableFieldLength = convertedFieldBytes.length; //@A2A } //@A2A else //@A2A { //@A2A // Prior to the @A2 fix, the following line of code was used to // calculate the string length. It is valid for non-AS400Text // data types. Retain this behavior. variableFieldLength = (f instanceof HexFieldDescription)? ((byte[])fields_[index]).length : ((String)fields_[index]).length(); //@A2C } //@A2A if (f instanceof DBCSGraphicFieldDescription) //@A2A { //@A2A // NOTE: The 2-byte length field in a VARGRAPHIC field is the number of "characters" and // is NOT the number of "bytes". Each VARGRAPHIC "character" is represented by // two bytes. So, we need to divide the variableFieldLength by two for VARGRAPHIC. // Note: The 2-byte length field in a VARCHAR field is the number of "bytes", so the // variableFieldLength is correct and should not be modified. variableFieldLength /= 2; //@A2A } //@A2A } //@A2A catch(UnsupportedEncodingException e) //@A2A { Trace.log(Trace.ERROR, "Record.setField received UnsupportedEncodingException", e); throw new InternalErrorException(InternalErrorException.UNEXPECTED_EXCEPTION);//@A2A } } BinaryConverter.unsignedShortToByteArray(variableFieldLength, as400Data_, offset); offset += 2; } } // Whether the field is variable length or not we still write out the maximum number // of bytes for the field. This is the required format for variable length data for record // level access. AS400DataType dType = f.getDataType(); if (fields_[index] != null) { if (convertedFieldBytes != null) //@A2A { // Use already converted data rather than re-converting the data System.arraycopy(convertedFieldBytes, 0, as400Data_, offset, convertedFieldBytes.length);//@A2A } else { // Field has a value; convert it to server data dType.toBytes(fields_[index], as400Data_, offset); } } else { // Field is null; use the default value for the server data to serve as a place holder for // the field. dType.toBytes(dType.getDefaultValue(), as400Data_, offset); } // Indicate the field is in a converted state isConvertedToAS400_[index] = true; } else { isConvertedToAS400_[index] = false; } } /** *Sets the contents of the field with the specified name to value. *
*The record format for the record must be set prior to invoking this method. *@see Record#Record(com.ibm.as400.access.RecordFormat) *@see Record#setRecordFormat *@param name The name of the field whose contents are to be set. *@param value The value to which to set the contents of the field. Specify null for *value to indicate that the field is null. **/ public void setField(String name, Object value) { if (recordFormat_ == null) { throw new ExtendedIllegalStateException("recordFormat", ExtendedIllegalStateException.PROPERTY_NOT_SET); } setField(recordFormat_.getIndexOfFieldName(name), value); } /** *Sets the record format for this record. *@param recordFormat The record format for this record. *@exception PropertyVetoException If a change is vetoed. **/ public void setRecordFormat(RecordFormat recordFormat) throws PropertyVetoException { if (recordFormat == null) { throw new NullPointerException("recordFormat"); } //@B5C - fire events the "new" way // Notify veto listeners of the change if (vetos_ != null) vetos_.fireVetoableChange("recordFormat", recordFormat_, recordFormat); RecordFormat old = recordFormat_; initializeRecord(recordFormat); if (changes_ != null) changes_.firePropertyChange("recordFormat", old, recordFormat_); } /** *Sets the name for this record. *@param name The name for this record. *@exception PropertyVetoException If a change is vetoed. **/ public void setRecordName(String name) throws PropertyVetoException { if (name == null) { throw new NullPointerException("name"); } //@B5C - fire events the "new" way // Notify veto listeners of the change if (vetos_ != null) vetos_.fireVetoableChange("recordName", name_, name); String old = name_; name_ = name; if (changes_ != null) changes_.firePropertyChange("recordName", old, name_); } /** *Sets the record number of this record. This method only pertains to the record *level access class SequentialFile when a write or update by record number *is being done. *@param recordNumber The record number of this record. The *recordNumber must be greater than 0. *@exception PropertyVetoException If a change is vetoed. **/ public void setRecordNumber(int recordNumber) throws PropertyVetoException { if (recordNumber < 0) { throw new ExtendedIllegalArgumentException("recordNumber", ExtendedIllegalArgumentException.RANGE_NOT_VALID); } //@B5C - fire events the "new" way // Notify veto listeners of the change Integer old = null; Integer newnum = null; if (vetos_ != null || changes_ != null) { old = new Integer(recordNumber_); newnum = new Integer(recordNumber); } if (vetos_ != null) vetos_.fireVetoableChange("recordNumber", old, newnum); recordNumber_ = recordNumber; if (changes_ != null) changes_.firePropertyChange("recordNumber", old, newnum); } //@RBA /** * Sets the record number with long type of this record. * @param recordNumber * @throws PropertyVetoException If the recipient wishes the property change to be rolled back. */ public void setRecordNumberLong(long recordNumber) throws PropertyVetoException { if (recordNumber > 4294967288L ||recordNumber < 0) { throw new ExtendedIllegalArgumentException("recordNumber", ExtendedIllegalArgumentException.RANGE_NOT_VALID); } //@B5C - fire events the "new" way // Notify veto listeners of the change Long old = null; Long newnum = null; if (vetos_ != null || changes_ != null) { old = new Long(recordNumberLong_); newnum = new Long(recordNumber); } if (vetos_ != null) vetos_.fireVetoableChange("recordNumberLong_", old, newnum); recordNumberLong_ = recordNumber; if (changes_ != null) changes_.firePropertyChange("recordNumberLong_", old, newnum); } /** *Returns the contents of this record formatted as a String. If a field is null, *"null" is substituted for the contents of the field in the string representation *of this record. *@return The contents of this record. The empty string is returned if the *record has not contents. **/ public String toString() { if (recordFormat_ == null) { return ""; } StringBuffer theRecord = new StringBuffer(0); Object obj = null; for (int i = 0; i < fields_.length; ++i) { // Append each field as a String to theRecord. Separate each field's // contents with a single space. try { obj = getField(i); } catch(UnsupportedEncodingException e) { // Unable to convert field; set to null. We do this because // we can't throw an exception from toString() obj = null; } catch(Exception e) //@D0A { // Some other exception; probably due to the fact that // this Record object hasn't had its AS400Text objects // filled in. obj = "???"; //@D0A } if (obj == null) { theRecord.append("null"); } else { if (obj instanceof byte[]) { theRecord.append(new String((byte[])obj)); } else { theRecord.append(obj.toString()); } } theRecord.append(" "); } // We return all but the last character which is the last blank we added return theRecord.toString().substring(0, theRecord.length() - 1); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy