com.adobe.xfa.content.DecimalValue Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aem-sdk-api Show documentation
Show all versions of aem-sdk-api Show documentation
The Adobe Experience Manager SDK
/*
* ADOBE CONFIDENTIAL
*
* Copyright 2005 Adobe Systems Incorporated All Rights Reserved.
*
* NOTICE: All information contained herein is, and remains the property of
* Adobe Systems Incorporated and its suppliers, if any. The intellectual and
* technical concepts contained herein are proprietary to Adobe Systems
* Incorporated and its suppliers and may be covered by U.S. and Foreign
* Patents, patents in process, and are protected by trade secret or copyright
* law. Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained from
* Adobe Systems Incorporated.
*/
package com.adobe.xfa.content;
import com.adobe.xfa.AppModel;
import com.adobe.xfa.Element;
import com.adobe.xfa.Int;
import com.adobe.xfa.LogMessage;
import com.adobe.xfa.Node;
import com.adobe.xfa.ScriptTable;
import com.adobe.xfa.XFA;
import com.adobe.xfa.ut.ExFull;
import com.adobe.xfa.ut.MsgFormatPos;
import com.adobe.xfa.ut.Numeric;
import com.adobe.xfa.ut.ResId;
import com.adobe.xfa.ut.StringUtils;
/**
* An element that creates a unit of data content representing a number with a
* fixed number of digits after the decimal.
*
* decimal-data is PCDATA that obeys the following rules:
* 1. no limit on the number of digits
* 2. optional leading sign
* 3. fractional digits beyond limit specified in "Digits" are rounded off
*
* @exclude from published api -- Mike Tardif, May 2006.
*/
public final class DecimalValue extends Content {
int mnInputFracDigits; // used when fracDigits == -1
public DecimalValue(Element parent, Node prevSibling) {
super(parent, prevSibling, null, XFA.DECIMAL, XFA.DECIMAL, null,
XFA.DECIMALTAG, XFA.DECIMAL);
//mnInputFracDigits = 0;
}
public boolean equals(Object object) {
if (this == object)
return true;
return super.equals(object) &&
getValue() == ((DecimalValue) object).getValue();
}
public int hashCode() {
long bits = Double.doubleToLongBits(getValue());
return super.hashCode() ^ (int)(bits ^ (bits >>> 32));
}
/**
* Get the formatted content of this element as a string, with the fracDigits
* attribute applied
* @return the string value
*/
public String getFormattedValue() {
//
//Return string value that respects the fractional digit
//attribute. Note that the getValue() always returns a double and
//therefore never really respects fractional zero digits
//
String value = getStrValue();
if (StringUtils.isEmpty(value))
return "";
int nFracDigits;
{
Int oInt = (Int) getAttribute(XFA.FRACDIGITSTAG);
nFracDigits = oInt.getValue();
// if (nFracDigits < 0 || nFracDigits > 8)
// nFracDigits = 8;
}
int nLeadDigits;
{
Int oInt = (Int) getAttribute(XFA.LEADDIGITSTAG);
nLeadDigits = oInt.getValue();
}
// how many fractional digits do we really want?
int nNeedFracDigits;
if (nFracDigits == -1)
nNeedFracDigits = mnInputFracDigits;
else if (nFracDigits >= 0)
nNeedFracDigits = nFracDigits;
else
return ""; // bad value
StringBuilder sFormattedValue = new StringBuilder(value);
// Watson 1701543. We were not omitting the minus sign from our
// count of the leading digits
boolean bNegativeNumber = (value.indexOf('-') == 0);
if (bNegativeNumber)
sFormattedValue.deleteCharAt(0);
int nFoundAt = sFormattedValue.toString().indexOf('.');
if (nFoundAt != -1) {
// check lead digits
if (nLeadDigits >= 0 && nFoundAt > nLeadDigits)
return ""; // bad
// fix up fracDigits
nFoundAt++;
int nHaveFracDigits = sFormattedValue.length() - nFoundAt;
if (nHaveFracDigits > nNeedFracDigits) {
// Watson 1281788 - rounding is required, so directly editing the value string does not work
// Watson 1462167 - we no longer round, but truncate to be consistent with earlier versions
sFormattedValue.setLength(sFormattedValue.length() - (nHaveFracDigits - nNeedFracDigits));
} else {
if (nFracDigits == -1) {
while (nHaveFracDigits < nNeedFracDigits) {
sFormattedValue.append('0');
nHaveFracDigits++;
}
}
}
} else {
// check lead digits
if (nLeadDigits >= 0 && sFormattedValue.length() > nLeadDigits)
return ""; // bad
// fix up fracDigits
if (nFracDigits == -1 && nNeedFracDigits > 0) {
sFormattedValue.append('.');
while (nNeedFracDigits > 0) {
sFormattedValue.append('0');
nNeedFracDigits--;
}
}
}
if (bNegativeNumber)
sFormattedValue.insert(0, '-');
return sFormattedValue.toString();
}
public ScriptTable getScriptTable() {
return DecimalScript.getScriptTable();
}
/**
* Get the content of this element as a double, with the fracDigits
* attribute applied.
* @return a double precision value
*/
public double getValue() {
//Retrieve the string representation of the double precision
//value, convert this to double and return that. We do this
//as floor can return incorrect values
//(i.e. (floor(10.0*10.0*1245.56))" -> 124555.000, which is wrong)
//The string representation returned will respect the fractional
//digit attribute.
String sValue = getFormattedValue();
double dVal = Numeric.stringToDouble(sValue, false);
return dVal;
}
public void setStrValue(String sText, boolean bNotify /* = true */, boolean bDefault /* = false */) {
trackInputFracDigits(sText);
super.setStrValue(sText, bNotify, bDefault);
}
/**
* Set the content of this element
* @param dValue the new value expressed as a double
*/
public void setValue(double dValue,
boolean bFromData /* = false */, boolean bNotify /* = true */, boolean bDefault /* = false */ /*CL#710206*/) {
// leadDigits="-1" means unlimited
// fracDigits value range: -1 means retain input number of fractional digits,
// otherwise fixed between 0 and 8 inclusively
Int oFracInt = (Int) getAttribute(XFA.FRACDIGITSTAG);
Int oLeadInt = (Int) getAttribute(XFA.LEADDIGITSTAG);
int nFracDigits = oFracInt.getValue();
int nLeadDigits = oLeadInt.getValue();
if (nFracDigits == -1)
nFracDigits = mnInputFracDigits;
String sValue = Numeric.doubleToString(dValue, nFracDigits, false);
if (nLeadDigits < 0) { // unlimited
/*CL#710206*/
setStrValue(sValue, bNotify, bDefault);
return;
}
// Watson 1701543. We were not omitting the minus sign from our
// count of the leading digits
boolean bNegativeNumber = (sValue.indexOf('-') == 0);
boolean bTooManyLeadDigits = false;
int nFoundAt = sValue.indexOf('.');
if (nFoundAt != -1) {
if (bNegativeNumber)
nFoundAt--;
if (nFoundAt > nLeadDigits)
bTooManyLeadDigits = true;
}
else if (sValue.length() > nLeadDigits)
bTooManyLeadDigits = true;
if (!bFromData && bTooManyLeadDigits) { // if bFromData dont have to raise error //CL#710206
// Acrobat displays these to the user, which our customers don't seem to like.
// Need to come up with a system to show them only to authors. Watson 2257768
if (! getAppModel().getLegacySetting(AppModel.XFA_LEGACY_V30_SCRIPTING)) {
MsgFormatPos message = new MsgFormatPos(ResId.TypeMismatch);
message.format(getSOMExpression());
message.format(sValue);
getModel().addErrorList(new ExFull(message), LogMessage.MSG_WARNING, this);
}
return;
}
setStrValue(sValue, bNotify, bDefault);
}
/**
* Set the content of this element
* @param sValue new value as string. Use this method to set the value to null.
* @param bFromData
*/
public void setValue(String sValue, boolean bFromData /* = false */,
boolean bNotify /* = true */, boolean bDefault /* = false */ /*CL#710206*/) {
if (StringUtils.isEmpty(sValue))
super.setStrValue(null, true, false);
else {
double dVal = Numeric.stringToDouble(sValue, true);
// We used to check separately for isnan() and !finite(), but NaN and finite are
// mutually exclusive, so everything bad actually falls into the !finite() case.
// Bug#3047665: Not true for Java. We need to explicitly test for NaNs
boolean bTypeMismatch = Double.isInfinite(dVal) || Double.isNaN(dVal);
if (bTypeMismatch) {
if (!getAppModel().getLegacySetting(AppModel.XFA_LEGACY_V30_SCRIPTING)) {
MsgFormatPos message = new MsgFormatPos(ResId.TypeMismatch);
message.format(getSOMExpression());
message.format(sValue);
getModel().addErrorList(new ExFull(message), LogMessage.MSG_WARNING, this);
}
// SAP requires error in case of any mismatch and it is protected using patch-W-2447677 flag and hence
// not setting to zero in case the patch flag is set.
if (getAppModel().getLegacySetting(AppModel.XFA_LEGACY_V29_SCRIPTING) &&
!getAppModel().getLegacySetting(AppModel.XFA_PATCH_W_2447677))
setStrValue(null, true, false); // legacy behavior for infinite is set to empty
else {
if (bFromData) // data is king, even if it's a type mismatch
setStrValue(sValue, bNotify, bDefault);//CL#710206
// else
// ; // otherwise leave existing value unchanged
}
return;
}
try {
//
// Fixed Watson 116840. Store decimals values as strings whenever
// the field has a fracDigits=-1. This way, we preserve the input
// exactly, which is critical when formatting with decimal picture '8'.
//
Int oFracInt = (Int)getAttribute(XFA.FRACDIGITSTAG);
int nFracDigits = oFracInt.getValue();
if (bFromData || nFracDigits == -1)//CL#734794
setStrValue(sValue, bNotify, bDefault);//CL#710206
else {
trackInputFracDigits(sValue);
setValue(dVal, bFromData, bNotify, bDefault);//CL#710206
}
}
catch(NumberFormatException e) {
super.setStrValue(null, true, false);
}
}
}
public String toString() {
return getFormattedValue();
}
private void trackInputFracDigits(String sValue) {
mnInputFracDigits = 0;
Int oFracInt = (Int) getAttribute(XFA.FRACDIGITSTAG);
if (oFracInt.getValue() == -1 && sValue != null) {
int nFoundAt = sValue.indexOf('.');
if (nFoundAt != -1) {
for (int i = nFoundAt + 1; i < sValue.length(); i++) {
char c = sValue.charAt(i);
if (!('0' <= c && c <= '9')) {
mnInputFracDigits = -1;
break;
}
mnInputFracDigits++;
}
}
}
}
/**
* Returns true
if the current value does not legally parse
* into a decimal with the appropriate number of leading digits.
* @exclude from published api.
*/
public boolean valueHasTypeMismatch() {
String sValue = getFormattedValue();
double dVal = Numeric.stringToDouble(sValue, true);
if (Double.isNaN(dVal) || Double.isInfinite(dVal))
return true;
//
// check for lead/frac digits out-of-bounds errors
//
Int oFracInt = (Int) getAttribute(XFA.FRACDIGITSTAG);
int nFracDigits = oFracInt.getValue();
if (nFracDigits == -1)
nFracDigits = Integer.MAX_VALUE;
Int oLeadInt = (Int) getAttribute(XFA.LEADDIGITSTAG);
int nLeadDigits = oLeadInt.getValue();
if (nLeadDigits == -1)
nLeadDigits = Integer.MAX_VALUE;
String sVal = getStrValue();
boolean bBeforeDecimal = true;
int length = sVal.length();
for (int i = 0; i < length; ) {
int c = sVal.codePointAt(i);
i += (c <= 0xFFFF) ? 1 : 2;
if ('0' <= c && c <= '9') {
if (bBeforeDecimal)
nLeadDigits--;
else
nFracDigits--;
if (nLeadDigits < 0)
return true;
if (nFracDigits < 0)
return true;
}
else if (c == '.') {
bBeforeDecimal = false;
}
}
return false;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy