| /* |
| * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0, |
| * or the Eclipse Distribution License v. 1.0 which is available at |
| * http://www.eclipse.org/org/documents/edl-v10.php. |
| * |
| * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause |
| */ |
| |
| // Contributors: |
| // Oracle - initial API and implementation from Oracle TopLink |
| package org.eclipse.persistence.internal.eis.cobol; |
| |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Vector; |
| |
| import org.eclipse.persistence.internal.eis.cobol.helper.ByteConverter; |
| import org.eclipse.persistence.internal.eis.cobol.helper.Helper; |
| import org.eclipse.persistence.internal.helper.DatabaseField; |
| |
| /** |
| * <b>Purpose</b>: This class defines the <code>FieldMetaData</code> interface it defines |
| * various behavior associated with a field and stores meta-information about the field. |
| * <code>ElementaryFieldMetaData</code> represents a field that contains a direct value and |
| * no subordinate fields, a root in the hierarchy. |
| */ |
| public class ElementaryFieldMetaData implements FieldMetaData { |
| |
| /** This is the record that contains this field */ |
| protected RecordMetaData myRecord; |
| |
| /** This is the name of the field */ |
| protected String myName; |
| |
| /** This is the size of the field */ |
| protected int mySize; |
| |
| /** This is the offset of the field within the record byte array */ |
| protected int myOffset; |
| |
| /** This is the type of data the field contains */ |
| protected int myType; |
| |
| /** This is true if this field is redefined */ |
| protected boolean isRedefine; |
| |
| /** This is the offset of the decimal position within the digits of a numeric field */ |
| protected int decimalPosition; |
| |
| /** This is the field that this field redefines */ |
| protected FieldMetaData myFieldRedefined; |
| |
| /** This is the number of elements in the array if this field is an array type */ |
| protected int myArraySize; |
| |
| /** This is populated if the arraySize is dependent on another field */ |
| protected String myDependentFieldName; |
| |
| /** This is true if the field is a numeric field that is signed */ |
| protected boolean isSigned; |
| |
| public ElementaryFieldMetaData() { |
| initialize(); |
| } |
| |
| public ElementaryFieldMetaData(String fieldName, String recordName) { |
| initialize(fieldName, recordName); |
| } |
| |
| public ElementaryFieldMetaData(String fieldName, RecordMetaData record) { |
| initialize(fieldName, record); |
| } |
| |
| protected void initialize() { |
| myRecord = new RecordMetaData(); |
| isRedefine = false; |
| decimalPosition = -1; |
| myArraySize = -1; |
| isSigned = false; |
| myDependentFieldName = ""; |
| } |
| |
| protected void initialize(String fieldName, String recordName) { |
| myName = fieldName; |
| myRecord = new RecordMetaData(recordName); |
| isRedefine = false; |
| decimalPosition = -1; |
| myArraySize = -1; |
| isSigned = false; |
| myDependentFieldName = ""; |
| } |
| |
| protected void initialize(String fieldName, RecordMetaData record) { |
| myName = fieldName; |
| myRecord = record; |
| isRedefine = false; |
| decimalPosition = -1; |
| myArraySize = -1; |
| isSigned = false; |
| myDependentFieldName = ""; |
| } |
| |
| /** |
| * performs a deep copy of all the attributes of the field |
| */ |
| @Override |
| public FieldMetaData deepCopy() { |
| FieldMetaData fieldCopy = new ElementaryFieldMetaData(myName, myRecord.getName()); |
| fieldCopy.setIsFieldRedefine(isRedefine); |
| fieldCopy.setDecimalPosition(decimalPosition); |
| fieldCopy.setArraySize(myArraySize); |
| fieldCopy.setSize(mySize); |
| fieldCopy.setOffset(myOffset); |
| fieldCopy.setType(myType); |
| if (isFieldRedefine()) { |
| fieldCopy.setFieldRedefined(myFieldRedefined.deepCopy()); |
| } |
| fieldCopy.setDependentFieldName(myDependentFieldName); |
| fieldCopy.setIsSigned(isSigned); |
| return fieldCopy; |
| } |
| |
| /** |
| * returns true if field is a signed numeric field |
| */ |
| @Override |
| public boolean isSigned() { |
| return isSigned; |
| } |
| |
| /** |
| * setter for isSigned |
| */ |
| @Override |
| public void setIsSigned(boolean signed) { |
| isSigned = signed; |
| } |
| |
| /** |
| * returns true if the field is a numeric field with a decimal marker |
| */ |
| @Override |
| public boolean hasDecimal() { |
| if (decimalPosition == -1) { |
| return false; |
| } else { |
| return true; |
| } |
| } |
| |
| /** |
| * getter for decimalPosition |
| */ |
| @Override |
| public int getDecimalPosition() { |
| return decimalPosition; |
| } |
| |
| /** |
| * setter for decimalPosition |
| */ |
| @Override |
| public void setDecimalPosition(int newPosition) { |
| decimalPosition = newPosition; |
| } |
| |
| /** |
| * getter for myName |
| */ |
| @Override |
| public String getName() { |
| return myName; |
| } |
| |
| /** |
| * setter for myName |
| */ |
| @Override |
| public void setName(String newName) { |
| myName = newName; |
| } |
| |
| /** |
| * getter for myRecord |
| */ |
| @Override |
| public RecordMetaData getRecord() { |
| return myRecord; |
| } |
| |
| /** |
| * setter for myRecord |
| */ |
| @Override |
| public void setRecord(RecordMetaData newRecord) { |
| myRecord = newRecord; |
| } |
| |
| /** |
| * getter for mySize, multiplies field size my array size if field is an array to get |
| * total size |
| */ |
| @Override |
| public int getSize() { |
| |
| /*if(this.isArray()) |
| return mySize * myArraySize; |
| else*/ |
| return mySize; |
| } |
| |
| /** |
| * setter for mySize |
| */ |
| @Override |
| public void setSize(int size) { |
| mySize = size; |
| } |
| |
| /** |
| * returns true if field is composite, since this is elementary, it always returns false |
| */ |
| @Override |
| public boolean isComposite() { |
| return false; |
| } |
| |
| /** |
| * returns an empty vector since an elementary field should have no subordinate fields |
| */ |
| public Vector getCompositeFields() { |
| return new Vector(); |
| } |
| |
| /** |
| * getter for myOffset |
| */ |
| @Override |
| public int getOffset() { |
| return myOffset; |
| } |
| |
| /** |
| * setter for myOffset |
| */ |
| @Override |
| public void setOffset(int offset) { |
| myOffset = offset; |
| } |
| |
| /** |
| * getter for myType |
| */ |
| @Override |
| public int getType() { |
| return myType; |
| } |
| |
| /** |
| * setter for myType |
| */ |
| @Override |
| public void setType(int type) { |
| myType = type; |
| } |
| |
| /** |
| * returns true if field is a redefine |
| */ |
| @Override |
| public boolean isFieldRedefine() { |
| return isRedefine; |
| } |
| |
| /** |
| * setter for isRedefine |
| */ |
| @Override |
| public void setIsFieldRedefine(boolean status) { |
| isRedefine = status; |
| } |
| |
| /** |
| * setter for myFieldRedefined |
| */ |
| @Override |
| public void setFieldRedefined(FieldMetaData field) { |
| myFieldRedefined = field; |
| if (field != null) { |
| isRedefine = true; |
| } else { |
| isRedefine = false; |
| } |
| } |
| |
| /** |
| * getter for myFieldRedefined |
| */ |
| @Override |
| public FieldMetaData getFieldRedefined() { |
| return myFieldRedefined; |
| } |
| |
| /** |
| * returns true if field is an array |
| */ |
| @Override |
| public boolean isArray() { |
| return (myArraySize > 0); |
| } |
| |
| /** |
| * getter for array size |
| */ |
| @Override |
| public int getArraySize() { |
| return myArraySize; |
| } |
| |
| /** |
| * setter for myArraySize |
| */ |
| @Override |
| public void setArraySize(int newSize) { |
| myArraySize = newSize; |
| } |
| |
| /** |
| * returns true if this field has a dependent field |
| */ |
| @Override |
| public boolean dependsOn() { |
| return (!myDependentFieldName.isEmpty()); |
| } |
| |
| /** |
| * getter for myDependentFieldName |
| */ |
| @Override |
| public String getDependentFieldName() { |
| return myDependentFieldName; |
| } |
| |
| /** |
| * setter for myDependentFieldName |
| */ |
| @Override |
| public void setDependentFieldName(String fieldName) { |
| myDependentFieldName = fieldName; |
| } |
| |
| /** |
| * this method extracts and returns the value for the field, if the field is an |
| * array, the value is an <code>Vector</code> |
| */ |
| @Override |
| public Object extractValueFromArray(byte[] recordData) { |
| Object value; |
| if (this.isArray()) { |
| int offset = this.getOffset(); |
| ArrayList fieldValue = new ArrayList(this.getArraySize()); |
| for (int i = this.getArraySize(); i > 0; i--) { |
| FieldMetaData fieldCopy = this.deepCopy(); |
| fieldCopy.setOffset(offset); |
| ByteConverter converter = new ByteConverter(fieldCopy, recordData); |
| fieldValue.add(converter.getStringValue()); |
| offset += mySize; |
| } |
| value = fieldValue; |
| } else { |
| ByteConverter converter = new ByteConverter(this, recordData); |
| value = converter.getStringValue(); |
| } |
| return value; |
| } |
| |
| /** |
| * this method adjusts the array size to the value in its dependent field |
| */ |
| protected void adjustArraySize(CobolRow row) { |
| Integer intValue = Helper.integerFromString(row.get(this.getDependentFieldName()).toString()); |
| if (intValue != null) { |
| this.setArraySize(intValue); |
| } |
| } |
| |
| /** |
| * this method will write its value to the row provided |
| */ |
| @Override |
| public void writeOnRow(CobolRow row, byte[] recordData) { |
| DatabaseField field = new DatabaseField(this.getName(), this.getRecord().getName()); |
| Object value; |
| |
| //check for array first adjust size if necessary |
| if (this.isArray() && this.dependsOn()) { |
| adjustArraySize(row); |
| } |
| if (!this.isFieldRedefine()) { |
| value = extractValueFromArray(recordData); |
| } |
| //redefined field handle accordingly |
| else { |
| value = new CobolRedefinedFieldValue(this, recordData); |
| } |
| row.add(field, value); |
| |
| } |
| |
| /** |
| * this method will write its value from the row to the record data byte array |
| */ |
| @Override |
| public void writeOnArray(CobolRow row, byte[] recordData) { |
| Object value = row.get(this.getName()); |
| ByteConverter converter; |
| if (this.isArray()) { |
| //check for array first adjust size if necessary |
| if (this.dependsOn()) { |
| adjustArraySize(row); |
| } |
| int offset = this.getOffset(); |
| Iterator elements = ((List)value).iterator(); |
| for (int i = this.getArraySize(); i > 0; i--) { |
| FieldMetaData fieldCopy = this.deepCopy(); |
| fieldCopy.setOffset(offset); |
| converter = new ByteConverter(fieldCopy, recordData); |
| String elementValue = (String)elements.next(); |
| converter.setBytesToValue(elementValue); |
| offset += mySize; |
| } |
| } else { |
| converter = new ByteConverter(this, recordData); |
| converter.setBytesToValue((String)value); |
| } |
| } |
| } |