/*
Copyright (c) 2003-2008 ITerative Consulting Pty Ltd. All Rights Reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted
provided that the following conditions are met:
o Redistributions of source code must retain the above copyright notice, this list of conditions and
the following disclaimer.
o Redistributions in binary form must reproduce the above copyright notice, this list of conditions
and the following disclaimer in the documentation and/or other materials provided with the distribution.
o This jcTOOL Helper Class software, whether in binary or source form may not be used within,
or to derive, any other product without the specific prior written permission of the copyright holder
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package Framework;
import java.beans.PropertyChangeEvent;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Locale;
import org.apache.log4j.Logger;
/**
* The DecimalData class represents floating point data, scaled to a specified decimal precision up to 28 decimal places.
* DecimalData arithmetic functions are precise to the specified scale. DecimalData data is most often used to represent monetary values in greater precision than is possible with the double or DoubleData data types.
*/
public class DecimalData extends NumericData implements Serializable
{
/**
* Resolves ambiguous constructor arguments
*/
public static class qq_Resolver {
public static final int cDOUBLEVALUE = 1;
public static final int cINTEGERVALUE = 2;
public static final int cISNULL = 3;
public static final int cSCALE = 4;
public static final int cTEXTVALUE = 5;
public static final int cVALUE = 6;
public static final int cDOUBLEVALUE_ISNULL = 7;
public static final int cDOUBLEVALUE_SCALE = 8;
public static final int cINTEGERVALUE_ISNULL = 9;
public static final int cINTEGERVALUE_SCALE = 10;
public static final int cISNULL_TEXTVALUE = 11;
public static final int cISNULL_SCALE = 12;
public static final int cISNULL_VALUE = 13;
public static final int cTEXTVALUE_SCALE = 14;
public static final int cSCALE_TEXTVALUE = 20;
public static final int cSCALE_VALUE = 15;
public static final int cDOUBLEVALUE_ISNULL_SCALE = 16;
public static final int cINTEGERVALUE_ISNULL_SCALE = 17;
public static final int cISNULL_TEXTVALUE_SCALE = 18;
public static final int cISNULL_SCALE_VALUE = 19;
}
//ISSUE 507 - Created default scale constant
private static final int DEFAULT_SCALE = 2;
/**
* We need to get the decimal format symbols for the ENGLIGH locale as the TextValue in Forte
* returned the value with a decimal point as the separator, not a comma (Ie 2000.0 and not 2000,0
* if we're in a European locale)
*/
private static final DecimalFormatSymbols englishLocaleSymbols = new DecimalFormatSymbols(Locale.ENGLISH);
public DecimalData(DecimalData value) {
super();
this.theValue = value.theValue;
}
public DecimalData(double pValue, int pResolver) {
super();
this.setValue(pValue);
}
public DecimalData(int pValue, int pResolver) {
super();
if (pResolver == DecimalData.qq_Resolver.cINTEGERVALUE)
this.setValue(pValue);
else if (pResolver == DecimalData.qq_Resolver.cSCALE)
this.setScale(pValue);
}
public DecimalData(boolean pValue, int pResolver) {
super();
if (pValue == true) {
DatatypeException dte = new DatatypeException();
dte.setReasonCode(Constants.SP_ER_NULLASSIGNMENT);
throw dte;
}
//this.setIsNull(pValue);
}
public DecimalData(TextData pValue, int pResolver) {
super();
this.setValue(pValue);
}
public DecimalData(TextData pValue) {
super();
this.setValue(pValue);
}
public DecimalData(String pValue, int pResolver) {
super();
this.setValue(pValue);
}
public DecimalData(double pValue, boolean pValue2, int pResolver) {
super();
if (pValue2 == true) {
DatatypeException dte = new DatatypeException();
dte.setReasonCode(Constants.SP_ER_NULLASSIGNMENT);
throw dte;
}
this.setValue(pValue);
// this.setIsNull(pValue2);
}
public DecimalData(double pValue, int pValue2, int pResolver) {
super();
this.setScale(pValue2);
this.setValue(pValue);
}
public DecimalData(int pScale, String pTextValue, int pResolver) {
super();
this.setValue(pTextValue);
this.setScale(pScale);
}
public DecimalData(int pScale, TextData pTextValue, int pResolver) {
super();
this.setValue(pTextValue);
this.setScale(pScale);
}
public DecimalData(int pValue, boolean pValue2, int pResolver) {
super();
if (pValue2 == true) {
DatatypeException dte = new DatatypeException();
dte.setReasonCode(Constants.SP_ER_NULLASSIGNMENT);
throw dte;
}
this.setValue(pValue);
// this.setIsNull(pValue2);
}
public DecimalData(int pValue, int pValue2, int pResolver) {
super();
this.setValue(pValue);
this.setScale(pValue2);
}
public DecimalData(boolean pValue, TextData pValue2, int pResolver) {
super();
if (pValue == true) {
DatatypeException dte = new DatatypeException();
dte.setReasonCode(Constants.SP_ER_NULLASSIGNMENT);
throw dte;
}
this.setValue(pValue2);
// this.setIsNull(pValue);
}
public DecimalData(boolean pValue, String pValue2, int pResolver) {
super();
if (pValue == true) {
DatatypeException dte = new DatatypeException();
dte.setReasonCode(Constants.SP_ER_NULLASSIGNMENT);
throw dte;
}
this.setValue(pValue2);
// this.setIsNull(pValue);
}
public DecimalData(boolean pValue, int pValue2, int pResolver) {
super();
if (pValue == true) {
DatatypeException dte = new DatatypeException();
dte.setReasonCode(Constants.SP_ER_NULLASSIGNMENT);
throw dte;
}
this.setScale(pValue2);
// this.setIsNull(pValue);
}
public DecimalData(boolean pValue, double pValue2, int pResolver) {
super();
if (pValue == true) {
DatatypeException dte = new DatatypeException();
dte.setReasonCode(Constants.SP_ER_NULLASSIGNMENT);
throw dte;
}
this.setValue(pValue2);
// this.setIsNull(pValue);
}
public DecimalData(TextData pValue, int pValue2, int pResolver) {
super();
this.setValue(pValue);
this.setScale(pValue2);
}
public DecimalData(String pValue, int pValue2, int pResolver) {
super();
this.setValue(pValue);
this.setScale(pValue2);
}
public DecimalData(int pValue, double pValue2, int pResolver) {
super();
this.setScale(pValue);
this.setValue(pValue2);
}
public DecimalData(double pValue, boolean pValue2, int pValue3, int pResolver) {
super();
if (pValue2 == true) {
DatatypeException dte = new DatatypeException();
dte.setReasonCode(Constants.SP_ER_NULLASSIGNMENT);
throw dte;
}
this.setValue(pValue);
//this.setIsNull(pValue2);
this.setScale(pValue3);
}
public DecimalData(int pValue, boolean pValue2, int pValue3, int pResolver) {
super();
if (pValue2 == true) {
DatatypeException dte = new DatatypeException();
dte.setReasonCode(Constants.SP_ER_NULLASSIGNMENT);
throw dte;
}
this.setValue(pValue);
//this.setIsNull(pValue2);
this.setScale(pValue3);
}
public DecimalData(boolean pValue2, TextData pValue, int pValue3, int pResolver) {
super();
if (pValue2 == true) {
DatatypeException dte = new DatatypeException();
dte.setReasonCode(Constants.SP_ER_NULLASSIGNMENT);
throw dte;
}
this.setValue(pValue);
//this.setIsNull(pValue2);
this.setScale(pValue3);
}
public DecimalData(boolean pValue2, String pValue, int pValue3, int pResolver) {
super();
if (pValue2 == true) {
DatatypeException dte = new DatatypeException();
dte.setReasonCode(Constants.SP_ER_NULLASSIGNMENT);
throw dte;
}
this.setValue(pValue);
//this.setIsNull(pValue2);
this.setScale(pValue3);
}
public DecimalData(boolean pValue2, int pValue, double pValue3, int pResolver) {
super();
if (pValue2 == true) {
DatatypeException dte = new DatatypeException();
dte.setReasonCode(Constants.SP_ER_NULLASSIGNMENT);
throw dte;
}
this.setScale(pValue);
//this.setIsNull(pValue2);
this.setValue(pValue3);
}
/**
* theValue is where this object stores its value (and scale)
*/
protected BigDecimal theValue;
/**
* default constructor - initializes DecimalData
* initializes an empty DecimalData object to have value 0 and the default scale.
*/
public DecimalData() {
//ISSUE 507 - Updated to use constant
// TF:Mar 18, 2010:Changed to use the fixed BigInteger value
this.theValue = new BigDecimal(BigInteger.ZERO, DEFAULT_SCALE);
}
/**
* Create a new decimal data using the default scale and the passed value
* @param value
*/
public DecimalData(double value) {
BigDecimal tmp = new BigDecimal(value);
theValue = tmp.setScale(DEFAULT_SCALE, RoundingMode.HALF_UP);
}
/**
* Create a new decimal data using the passed value
* @param value
*/
public DecimalData(BigDecimal value) {
theValue = value;
}
/**
* Create a new decimal data using the passed value and the default scale
* @param value
*/
public DecimalData(Number value) {
setValue(value);
}
/**
* Create a new DecimalData with the default scale and the value specified
* @param value
*/
public DecimalData(String value) {
BigDecimal tmp = new BigDecimal(value);
//ISSUE 507 - Updated to use constant
theValue = tmp.setScale(DEFAULT_SCALE, RoundingMode.HALF_UP);
}
/**
* Get the value of this DecimalData as a string, formatting it to the scale of this DecimalData
*/
public String toString() {
// ISSUE 19 - need to use a private method to prevent infinite recursion on a
// domain class that calls toString.
if (checkNullValue())
data_RaiseInvalidMethodExcpt();
TextData tmp = new TextData();
this._fillString(tmp);
return(tmp.getValue());
}
/**
* Determine if this DecimalData object is the same as another object. This method
* will return true only if the passed object is a DecimalData whose value is the same
* as this value.
*/
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof DecimalData)) {
return false;
}
DecimalData dd = (DecimalData)obj;
// TF:03/06/2008:Added in null check
// TF:27/04/2009:Changed this to use the compareTo method, as the scale was irrelevant in Forte's comparison
return this.isNull() == dd.isNull() && (theValue.compareTo(dd.theValue) == 0);
}
@Override
public int hashCode() {
if (this.isNull()) {
// TF:27/04/2009:Pick a valid but unlikely value
return Integer.MAX_VALUE - 41;
}
return this.theValue.hashCode();
}
/**
* Get the value of this DecimalData as an integer. This will discard any fractional part
* and return the lowest 32-bits of the value as an integer
*/
public int intValue() {
if (checkNullValue())
data_RaiseInvalidMethodExcpt();
return theValue.intValue();
}
/**
* Get the value of this DecimalData as a long. This will discard any fractional part
* and return the lowest 64-bits of the value as a long.
*/
public long longValue() {
if (checkNullValue())
data_RaiseInvalidMethodExcpt();
return theValue.longValue();
}
public float floatValue()
{
if (checkNullValue())
data_RaiseInvalidMethodExcpt();
return theValue.floatValue();
}
public double doubleValue()
{
if (checkNullValue())
data_RaiseInvalidMethodExcpt();
return theValue.doubleValue();
}
public double getValue()
{
if (checkNullValue())
data_RaiseInvalidMethodExcpt();
return theValue.doubleValue();
}
/**
* @return the underlying BigDecimal value
*/
public BigDecimal getBigDecimal()
{
if (checkNullValue())
data_RaiseInvalidMethodExcpt();
return theValue;
}
public void add(NumericData source1, NumericData source2)
{
BigDecimal answer;
BigDecimal tmpBigDecimal;
if (source1 == null || source2 == null)
data_RaiseNilOperandExcpt();
if(source1.checkNullValue() || source2.checkNullValue())
{
setNull();
return;
}
if (source1 instanceof DecimalData)
answer = ((DecimalData) source1).theValue;
else
answer = new BigDecimal(source1.asScalarReal());
if (source2 instanceof DecimalData)
tmpBigDecimal = ((DecimalData) source2).theValue;
else
tmpBigDecimal = new BigDecimal(source2.asScalarReal());
setValue(answer.add(tmpBigDecimal));
}
public void add(double source1, NumericData source2)
{
BigDecimal answer;
BigDecimal tmpBigDecimal;
if (source2 == null)
data_RaiseNilOperandExcpt();
if(source2.checkNullValue())
{
setNull();
return;
}
answer = new BigDecimal(source1);
if (source2 instanceof DecimalData)
tmpBigDecimal = ((DecimalData) source2).theValue;
else
tmpBigDecimal = new BigDecimal(source2.asScalarReal());
setValue(answer.add(tmpBigDecimal));
}
public void add(NumericData source1, double source2)
{
BigDecimal answer;
BigDecimal tmpBigDecimal;
if (source1 == null)
data_RaiseNilOperandExcpt();
if(source1.checkNullValue())
{
setNull();
return;
}
answer = new BigDecimal(source2);
if (source1 instanceof DecimalData)
tmpBigDecimal = ((DecimalData) source1).theValue;
else
tmpBigDecimal = new BigDecimal(source1.asScalarReal());
setValue(answer.add(tmpBigDecimal));
}
public void add(double source1, double source2) {
BigDecimal answer;
BigDecimal tmpBigDecimal;
answer = new BigDecimal(source2);
tmpBigDecimal = new BigDecimal(source1);
setValue(answer.add(tmpBigDecimal));
}
public double asScalarReal() {
if (checkNullValue())
data_RaiseInvalidMethodExcpt();
return theValue.doubleValue();
}
public Double asDouble() {
if (theValue != null)
return new Double(theValue.doubleValue());
else
return new Double(0.0);
}
public int asScalarInteger()
{
if (checkNullValue())
data_RaiseInvalidMethodExcpt();
return theValue.intValue();
}
public void divide(NumericData source1, NumericData source2)
{
BigDecimal answer;
BigDecimal tmpBigDecimal;
if (source1 == null || source2 == null)
data_RaiseNilOperandExcpt();
if(source1.checkNullValue() || source2.checkNullValue())
{
setNull();
return;
}
if (source1 instanceof DecimalData)
answer = ((DecimalData) source1).theValue;
else
answer = new BigDecimal(source1.asScalarReal());
if (source2 instanceof DecimalData)
tmpBigDecimal = ((DecimalData) source2).theValue;
else
tmpBigDecimal = new BigDecimal(source2.asScalarReal());
setValue(answer.divide(tmpBigDecimal, getScale(), RoundingMode.HALF_UP));
//AD:25/11/2008: Uncomment the below line if Forte truncation bug is necessary and comment the above line
//setValue(divide(answer,tmpBigDecimal,getScale()));
}
public void divide(NumericData source1,
double source2)
{
BigDecimal answer;
BigDecimal tmpBigDecimal;
if (source1 == null)
data_RaiseNilOperandExcpt();
if(source1.checkNullValue())
{
setNull();
return;
}
tmpBigDecimal = new BigDecimal(source2);
if (source1 instanceof DecimalData)
answer = ((DecimalData) source1).theValue;
else
answer = new BigDecimal(source1.asScalarReal());
setValue(answer.divide(tmpBigDecimal, getScale(), RoundingMode.HALF_UP ));
//AD:25/11/2008: Uncomment the below line if Forte truncation bug is necessary and comment the above line
//setValue(divide(answer,tmpBigDecimal,getScale()));
}
public void divide(double source1, NumericData source2)
{
BigDecimal answer;
BigDecimal tmpBigDecimal;
if (source2 == null)
data_RaiseNilOperandExcpt();
if(source2.checkNullValue())
{
setNull();
return;
}
answer = new BigDecimal(source1);
if (source2 instanceof DecimalData)
tmpBigDecimal = ((DecimalData) source2).theValue;
else
tmpBigDecimal = new BigDecimal(source2.asScalarReal());
setValue(answer.divide(tmpBigDecimal, getScale(),RoundingMode.HALF_UP));
//AD:25/11/2008: Uncomment the below line if Forte truncation bug is necessary and comment the above line
//setValue(divide(answer,tmpBigDecimal,getScale()));
}
public void divide(double source1, double source2)
{
BigDecimal answer;
BigDecimal tmpBigDecimal;
answer = new BigDecimal(source1);
tmpBigDecimal = new BigDecimal(source2);
setValue(answer.divide(tmpBigDecimal, getScale(), RoundingMode.HALF_UP));
//AD:25/11/2008: Uncomment the below line if Forte truncation bug is necessary and comment the above line
//setValue(divide(answer,tmpBigDecimal,getScale()));
}
// AD:25/11/2008: Method used to keep Forte's truncation bug. Not currently used unless lines above uncommented
//Created this method to truncate the divided result based on the scale.
@SuppressWarnings("unused")
private BigDecimal divide(BigDecimal source1, BigDecimal source2, int scale){
String str = null;
// TF:Mar 18, 2010:Changed these to use the constant
BigDecimal result = BigDecimal.ZERO;
if (source1.compareTo(BigDecimal.ZERO) > 0 ) {
result = source1.divide(source2, scale+2, RoundingMode.HALF_UP);
str = result.toPlainString();
int dotindex = str.indexOf('.') + 1;
String resultString = str.substring(0,(dotindex+scale));
result = new BigDecimal(resultString);
}else{
result = source1;
}
result.setScale(scale,RoundingMode.HALF_UP);
return result;
}
// ISSUE 19 - need to use a private method to prevent infinite recursion on a
// domain class that calls toString.
private void _fillString(TextData target)
{
if (target == null) {
data_RaiseNilOperandExcpt();
}
if (getIsNull()) {
target.concat(NL_FMSG_NULLVALUE);
}
else
{
// TF:20/3/08:Changed the default format to "0.0" to match what forte did
// TF:2 oct. 2008:Changed this to use the english locale symbols to ensure that the output
// uses a period separator instead of a comma or other locale-specific symbol (as this
// matches what Forte did)
NumberFormat df = new DecimalFormat("0.0", englishLocaleSymbols);
df.setMaximumFractionDigits(this.getScale());
target.concat(df.format(theValue));
}
}
public void fillString(TextData target) {
this._fillString(target);
}
public int getScale()
{
if (theValue != null)
return theValue.scale();
else
return 0;
}
public BooleanNullable isEqual(NumericData source)
{
BooleanNullable result;
BigDecimal tmpBigDecimal;
if (source == null)
data_RaiseNilOperandExcpt();
result = new BooleanNullable();
if(checkNullValue() || source.checkNullValue())
{
result.setNull();
}
else
{
if (source instanceof DecimalData)
tmpBigDecimal = ((DecimalData) source).theValue;
else
tmpBigDecimal = new BigDecimal(source.asScalarReal());
if (theValue.compareTo(tmpBigDecimal) == 0)
result.setTrue();
else
result.setFalse();
}
return result;
}
public BooleanNullable isGreaterThan(NumericData source)
{
BooleanNullable result;
BigDecimal tmpBigDecimal;
if (source == null)
data_RaiseNilOperandExcpt();
result = new BooleanNullable();
if(checkNullValue() || source.checkNullValue())
{
result.setNull();
}
else
{
if (source instanceof DecimalData)
{
tmpBigDecimal = ((DecimalData) source).theValue;
}
else
{
tmpBigDecimal = new BigDecimal(source.asScalarReal());
}
if (theValue.compareTo(tmpBigDecimal) > 0)
result.setTrue();
else
result.setFalse();
}
return result;
}
public BooleanNullable isGreaterThanOrEqual(NumericData source)
{
BooleanNullable result;
BigDecimal tmpBigDecimal;
if (source == null)
data_RaiseNilOperandExcpt();
result = new BooleanNullable();
if(checkNullValue() || source.checkNullValue())
{
result.setNull();
}
else
{
if (source instanceof DecimalData)
{
tmpBigDecimal = ((DecimalData) source).theValue;
}
else
{
tmpBigDecimal = new BigDecimal(source.asScalarReal());
}
if (theValue.compareTo(tmpBigDecimal) >= 0)
result.setTrue();
else
result.setFalse();
}
return result;
}
public BooleanNullable isLessThan(NumericData source)
{
BooleanNullable result;
BigDecimal tmpBigDecimal;
if (source == null)
data_RaiseNilOperandExcpt();
result = new BooleanNullable();
if(checkNullValue() || source.checkNullValue())
{
result.setNull();
}
else
{
if (source instanceof DecimalData)
{
tmpBigDecimal = ((DecimalData) source).theValue;
}
else
{
tmpBigDecimal = new BigDecimal(source.asScalarReal());
}
if (theValue.compareTo(tmpBigDecimal) < 0)
result.setTrue();
else
result.setFalse();
}
return result;
}
public BooleanNullable isLessThanOrEqual(NumericData source)
{
BooleanNullable result;
BigDecimal tmpBigDecimal;
if (source == null)
data_RaiseNilOperandExcpt();
result = new BooleanNullable();
if(checkNullValue() || source.checkNullValue())
{
result.setNull();
}
else
{
if (source instanceof DecimalData)
{
tmpBigDecimal = ((DecimalData) source).theValue;
}
else
{
tmpBigDecimal = new BigDecimal(source.asScalarReal());
}
if (theValue.compareTo(tmpBigDecimal) <= 0)
result.setTrue();
else
result.setFalse();
}
return result;
}
public BooleanNullable isNotEqual(NumericData source)
{
BooleanNullable result;
BigDecimal tmpBigDecimal;
if (source == null)
data_RaiseNilOperandExcpt();
result = new BooleanNullable();
if(checkNullValue() || source.checkNullValue())
{
result.setNull();
}
else
{
if (source instanceof DecimalData)
{
tmpBigDecimal = ((DecimalData) source).theValue;
}
else
{
tmpBigDecimal = new BigDecimal(source.asScalarReal());
}
if (theValue.compareTo(tmpBigDecimal) != 0)
result.setTrue();
else
result.setFalse();
}
return result;
}
public void multiply(NumericData source1, NumericData source2) {
BigDecimal answer;
BigDecimal tmpBigDecimal;
if (source1 == null || source2 == null)
data_RaiseNilOperandExcpt();
if(source1.checkNullValue() || source2.checkNullValue())
{
setNull();
return;
}
if (source1 instanceof DecimalData)
answer = ((DecimalData) source1).theValue;
else
answer = new BigDecimal(source1.asScalarReal());
if (source2 instanceof DecimalData)
tmpBigDecimal = ((DecimalData) source2).theValue;
else
tmpBigDecimal = new BigDecimal(source2.asScalarReal());
setValue(answer.multiply(tmpBigDecimal));
}
public void multiply(double source1,
NumericData source2)
{
BigDecimal answer;
BigDecimal tmpBigDecimal;
if (source2 == null)
data_RaiseNilOperandExcpt();
if(source2.checkNullValue())
{
setNull();
return;
}
answer = new BigDecimal(source1);
if (source2 instanceof DecimalData)
tmpBigDecimal = ((DecimalData) source2).theValue;
else
tmpBigDecimal = new BigDecimal(source2.asScalarReal());
setValue(answer.multiply(tmpBigDecimal));
}
public void multiply(NumericData source1,
double source2)
{
BigDecimal answer;
BigDecimal tmpBigDecimal;
if (source1 == null)
data_RaiseNilOperandExcpt();
if(source1.checkNullValue())
{
setNull();
return;
}
answer = new BigDecimal(source2);
if (source1 instanceof DecimalData)
tmpBigDecimal = ((DecimalData) source1).theValue;
else
tmpBigDecimal = new BigDecimal(source1.asScalarReal());
setValue(answer.multiply(tmpBigDecimal));
}
public void multiply(double source1,
double source2)
{
BigDecimal answer;
BigDecimal tmpBigDecimal;
answer = new BigDecimal(source2);
tmpBigDecimal = new BigDecimal(source1);
setValue(answer.multiply(tmpBigDecimal));
}
public void setScale(int value)
{
if (value < 0)
{
UsageException ex = new UsageException();
ex.reasonCode = UsageException.PARAMETERERROR;
throw ex;
}
if (theValue == null) {
// TF:03/06/2008:Changed to used the scale constant
// TF:Mar 18, 2010:Changed this to use the constant
theValue = BigDecimal.ZERO;
}
theValue = theValue.setScale(value, RoundingMode.HALF_UP);
reportChange();
}
/*
* CraigM:14/01/2009 - Mostly copied from TextData.
*
* @see Framework.DataValue#setIsNull(boolean)
*/
public void setIsNull(boolean isNull) {
if (hasNullValue != isNull) {
if (isNull) {
if (isNullable()) {
this.setNull();
}
else {
data_RaiseNullAssignExcpt();
}
} else {
this.clearNull();
}
reportChange();
}
}
public void setValue(BigDecimal source)
{
if (source == null) {
data_RaiseNilOperandExcpt();
}
else {
this.theValue = source.setScale(getScale(), RoundingMode.HALF_UP);
this.clearNull();
reportChange();
}
}
public void setValue(int value) {
setValue( (long) value);
}
public void setValue(double value)
{
BigDecimal oldValue = this.theValue;
try {
if (this.theValue != null) {
int scale = this.theValue.scale();
BigDecimal bigD = new BigDecimal(value);
this.theValue = bigD.setScale(scale, RoundingMode.HALF_UP);
}
else {
// TF:03/06/2008:LIB-18:Mapped the return value to the value
BigDecimal bigD = new BigDecimal(value);
this.theValue = bigD.setScale(DEFAULT_SCALE, RoundingMode.HALF_UP);
}
}
catch (RuntimeException e) {
Logger.getLogger("task.part.logmgr").error("Unhandled exception", e);
}
reportChange();
this.getPropertyListeners().firePropertyChange("value", oldValue, this.theValue);
}
public void setValue(Double value) {
setValue(value.doubleValue());
}
public void setValue(Number value) {
setValue(value.doubleValue());
}
public void setValue(Float value) {
setValue(value.floatValue());
}
public void setValue(long source) {
if (this.theValue != null) {
int scale = this.theValue.scale();
BigDecimal bigD = new BigDecimal(source);
this.theValue = bigD.setScale(scale, RoundingMode.HALF_UP);
}
else {
BigDecimal bigD = new BigDecimal(source);
this.theValue = bigD.setScale(DEFAULT_SCALE, RoundingMode.HALF_UP);
}
reportChange();
}
public void setValue(NumericData source)
{
if (source == null) {
data_RaiseNilOperandExcpt();
}
else if (source.checkNullValue()) {
setNull();
}
else {
setValue(source.asScalarReal());
}
}
public void setValue(DecimalData source) {
// AD:Aug 15, 2008 - make sure if source is nullable set Null value
if (source.checkNullValue()) {
setNull();
}
else {
setValue(source.toBigDecimal());
}
}
public void setValue(String source)
{
if (source == null) {
data_RaiseNilOperandExcpt();
}
else {
//PM:25 sept. 2008:if the string is empty set it to zero
if (source.length() == 0) {
// CraigM:08/10/2008 - DecimalDatas will throw an exception on an empty string
if (DecimalData.class.getName().equals(this.getClass().getName())) {
DatatypeException dte = new DatatypeException();
dte.setReasonCode(Constants.SP_ER_TYPECONVERSION);
throw dte;
}
source = "0";
}
try {
// CraigM:07/10/2008 - DecimalNullables seem to be unforgiving with other characters in Forte
if (this instanceof DecimalNullable) {
// Unless we are only whitespace, then we null ourselves
// Or if our value is N/A, then we were null, and we want to stay null. CraigM:20/01/2009.
if (source.trim().length() == 0 || "N/A".equals(source)) {
this.setNull();
return;
}
// Look for any invalid character
if (this.hasInvalidChars(source)) {
DatatypeException dte = new DatatypeException();
dte.setReasonCode(Constants.SP_ER_TYPECONVERSION);
throw dte;
}
}
// CraigM:07/10/2008 - Pure DecimalData seemed to be unforgiving with invalid characters in Forte
else if (DecimalData.class.getName().equals(this.getClass().getName())) {
if (this.hasInvalidChars(source)) {
DatatypeException dte = new DatatypeException();
dte.setReasonCode(Constants.SP_ER_TYPECONVERSION);
throw dte;
}
}
this.setValue(DecimalFormat.getInstance().parse(source.trim()));
} catch (ParseException e) {
// CraigM:07/10/2008 - Forte wouldn't throw an exception if the first character was a space (it would zero out the value). JIRA: JCT-606.
if (source.charAt(0) == ' ') {
setValue(0);
}
else {
DatatypeException dte = new DatatypeException(e);
dte.setReasonCode(Constants.SP_ER_TYPECONVERSION);
throw dte;
}
}
}
}
public void setValue(StringBuffer source) {
if (source == null)
data_RaiseNilOperandExcpt();
else
setValue(source.toString());
}
public void setValue(StringBuilder source) {
if (source == null)
data_RaiseNilOperandExcpt();
else
setValue(source.toString());
}
public void setValue(TextData source)
{
if (source == null) {
data_RaiseNilOperandExcpt();
}
else if (source.checkNullValue()) {
// CraigM:07/10/2008 - Added check to make sure we can be set to null
if (this.isNullable()) {
this.setNull();
}
else {
data_RaiseNullAssignExcpt();
}
}
else {
setValue(source.toString());
}
}
public void subtract(NumericData source1,
NumericData source2)
{
BigDecimal answer;
BigDecimal tmpBigDecimal;
if (source1 == null || source2 == null)
data_RaiseNilOperandExcpt();
if(source1.checkNullValue() || source2.checkNullValue())
{
setNull();
return;
}
if (source1 instanceof DecimalData)
answer = ((DecimalData) source1).theValue;
else
answer = new BigDecimal(source1.asScalarReal());
if (source2 instanceof DecimalData)
tmpBigDecimal = ((DecimalData) source2).theValue;
else
tmpBigDecimal = new BigDecimal(source2.asScalarReal());
setValue(answer.subtract(tmpBigDecimal));
}
public void subtract(double source1,
NumericData source2)
{
BigDecimal answer;
BigDecimal tmpBigDecimal;
if (source2 == null)
data_RaiseNilOperandExcpt();
if(source2.checkNullValue())
{
setNull();
return;
}
answer = new BigDecimal(source1);
if (source2 instanceof DecimalData)
tmpBigDecimal = ((DecimalData) source2).theValue;
else
tmpBigDecimal = new BigDecimal(source2.asScalarReal());
setValue(answer.subtract(tmpBigDecimal));
}
public void subtract(NumericData source1,
double source2)
{
BigDecimal answer;
BigDecimal tmpBigDecimal;
if (source1 == null)
data_RaiseNilOperandExcpt();
if(source1.checkNullValue())
{
setNull();
return;
}
tmpBigDecimal = new BigDecimal(source2);
if (source1 instanceof DecimalData)
answer = ((DecimalData) source1).theValue;
else
answer = new BigDecimal(source1.asScalarReal());
setValue(answer.subtract(tmpBigDecimal));
}
public void subtract(double source1,
double source2)
{
BigDecimal answer;
BigDecimal tmpBigDecimal;
answer = new BigDecimal(source1);
tmpBigDecimal = new BigDecimal(source2);
setValue(answer.subtract(tmpBigDecimal));
}
public BigDecimal toBigDecimal()
{
if (checkNullValue())
data_RaiseInvalidMethodExcpt();
return theValue;
}
@Override
public Number toNumber() {
return toBigDecimal();
}
protected static final int ubcdPrecision = 30;
protected static final int ubcdByteLength = 15;
protected static final int sbcdByteLength = 16;
/* Removed as it is not used - removes unnecessary warnings
* private byte[] stringToSbcd(String istring)
{
char[] string;
int i = 0;
int j;
int scale = 0;
int point = 0;
byte[] result = new byte[sbcdByteLength];
String tmpString = istring.trim();
if (tmpString.length() < (ubcdPrecision + 1))
{
StringBuffer sb = new StringBuffer(tmpString);
if (tmpString.indexOf('.') == -1)
{
sb.append(".0");
}
while (sb.length() < (ubcdPrecision + 1))
{
sb.append('0');
}
string = sb.toString().toCharArray();
}
else
{
string = tmpString.toCharArray();
}
result[0]=0;
if (string[0] == '-')
{
result[0]=1;
i++;
}
point = -1;
for(;
i < ubcdPrecision && (java.lang.Character.isDigit(string[i]));
i++)
;
if(string[i] == '.')
{
point=i++;
for(;
i < ubcdPrecision && (java.lang.Character.isDigit(string[i+1]));
i++)
;
}
if (point == i)
{
scale = 0;
}
else if (point == -1)
{
scale = 0;
point = i++;
}
else
{
int dscale;
scale = i - point;
dscale = scale;
if ((dscale % 2) == 1)
{
dscale++;
}
if ((dscale+point)> ubcdPrecision)
{
dscale -= 2;
scale = dscale;
}
result[0] += dscale << 1;
}
i = scale+point;
j = ubcdByteLength;
if ((scale % 2) == 1)
{
result[j--] = (byte) ((string[i--] - '0') << 4);
}
while ( i > point )
{
result[j] = (byte) (string[i--] - '0');
result[j--] += (byte) ((string[i--] - '0') << 4);
}
if(point != 0)
i--;
while ( i >=1 )
{
result[j] = (byte) (string[i--] - '0');
result[j--] += (byte) ((string[i--] - '0') << 4);
}
if ((i == 0) && (point != 0))
result[j--] = (byte) (string[i] - '0');
while(j >=1)
{
result[j--] = 0;
}
return result;
}
private String sbcdToString(byte oper[])
{
int i;
int j;
int scaleindex;
int offsetToDecimalPoint;
int quot;
int rem;
int truncate;
boolean bHasDecimal = false;
char[] result = new char[ubcdPrecision + 1];
scaleindex = ubcdPrecision - (oper[0] >> 1);
j = 0;
if ((oper[0] & 1) != 0)
{
result[0] = '-';
j++;
}
offsetToDecimalPoint = (scaleindex >> 1) + 1;
for (i=1; (i < oper.length) && (oper[i] == 0) && (i < offsetToDecimalPoint) ; i++)
;
if (i < offsetToDecimalPoint)
{
quot = (oper[i] >>> 4) & 0xf ;
rem = oper[i] & 0xf;
i++;
if (quot != 0)
{
result[j++] = (char) (quot + '0');
}
result[j++] = (char) (rem + '0');
}
for(; i<ubcdByteLength; i++)
{
quot = (oper[i] >>> 4) & 0xf ;
rem = oper[i] & 0xf;
if (i == offsetToDecimalPoint)
{
if (j==0)
{
result[j++] = '0';
}
result[j++] = '.';
bHasDecimal = true;
}
result[j++] = (char) (quot + '0');
result[j++] = (char) (rem + '0');
}
if (j==0)
{
result[j++] = '0';
}
truncate = j;
if (bHasDecimal)
{
for (j--; j>0; j--)
{
if (result[j] == '0')
{
if (result[j-1] == '.')
break;
truncate = j;
}
else
{
break;
}
}
}
String tmpString = new String(result);
return tmpString.substring(0, truncate);
}
*/
public DecimalData getCopyData() {
DecimalData lvReturn = new DecimalData(this.doubleValue());
lvReturn.setScale(this.getScale());
return lvReturn;
}
// public Object clone() {
// return this.clone(false);
// }
//
// public Object clone(boolean pDeep) {
// DecimalData result = new DecimalData();
// this.duplicateIntoTarget(result, pDeep);
// return result;
// }
public void duplicateIntoTarget(DecimalData pData, boolean pDeep) {
super.duplicateIntoTarget(pData, pDeep);
// BigDecimals are immutable, so can use the same one.
pData.theValue = this.theValue;
}
public void propertyChange(PropertyChangeEvent arg0) {
// -----------------------------------------------------------------------
// TF:29/01/2010:JCT-640:Changed this to invoke a method on the superclass
// -----------------------------------------------------------------------
this.firePropertyChange("value", null, this.theValue);
}
/**
* Compares the value attribute of the object specified in the source parameter with the value
* of this object and returns an integer indicating their relative magnitude
* (equals, less than, and so on). If the convert parameter is TRUE, the method
* converts source to a DataValue object if necessary and then does the comparison.
*/
public int compareValue(DataValue source, boolean convert, boolean ignoreCase) {
if (source == null) {
return Constants.DV_CMP_NIL;
}
else if (this.isNull() || source.isNull()) {
return Constants.DV_CMP_NULL;
}
else if (source instanceof DecimalData) {
double thisValue = this.getValue();
double otherValue = ((DecimalData)source).getValue();
if (thisValue < otherValue)
return Constants.DV_CMP_LT;
else if (thisValue == otherValue)
return Constants.DV_CMP_EQ;
else
return Constants.DV_CMP_GT;
}
else if (convert) {
try {
double thisValue = this.getValue();
double otherValue = source.getTextValue().getDoubleValue();
if (thisValue < otherValue)
return Constants.DV_CMP_LT;
else if (thisValue == otherValue)
return Constants.DV_CMP_EQ;
else
return Constants.DV_CMP_GT;
}
catch (Exception e) {
return Constants.DV_CMP_UNCONVERTIBLE;
}
}
return Constants.DV_CMP_UNCONVERTIBLE;
}
/**
* The DecodeValue method converts the source text into a DecimalData value according to a DataFormat.
* If the source is a string or TextData, it must conform to the template specified for the format parameter. If the string value is not a valid decimal format, it generates a DataTypeException
* @param source TextData
* @param format DataFormat
*/
public void decodeValue(TextData source, DataFormat format){
decodeValue(source.toString(), format);
}
/**
* The DecodeValue method converts the source text into a DecimalData value according to a DataFormat.
* If the source is a string or TextData, it must conform to the template specified for the format parameter. If the string value is not a valid decimal format, it generates a DataTypeException
* @param source String
* @param format DataFormat
*/
public void decodeValue(String source, DataFormat format){
try{
setValue(((NumericFormat)format).decodeDouble(source));
} catch (Throwable e){
DatatypeException ex = new DatatypeException("String or TextData not a valid format", e);
ex.setReasonCode(Constants.SP_ER_TYPECONVERSION);
throw ex;
}
}
public int dataType() {
return Constants.DV_DT_DECIMAL;
}
public String getRawNoDecString() {
return new Long(this.longValue()).toString();
}
public void setIntegerValue(int value){
this.setValue(value);
}
@Override
public void setDoubleValue(double value) {
this.setValue(value);
}
@Override
// AD:Aug 15, 2008 - Override DataValue for more efficient setting if of the same type
public void setValue(DataValue source) {
if (source instanceof DecimalData) {
setValue((DecimalData) source);
} else {
super.setValue(source);
}
}
/**
* setValue<p>
* <p>
* @param source Type: DataValue
* @param sourceScale Type: boolean
*
* @author AD:Nov 10, 2008 - Keep the scale
*/
public void setValue(DataValue source, boolean sourceScale) {
if(sourceScale){
if(source instanceof DecimalNullable){
this.setScale(((DecimalNullable) source).getScale());
}
}
this.setValue(source);
}
}