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

com.adobe.xfa.content.DecimalValue Maven / Gradle / Ivy

There is a newer version: 2024.11.18751.20241128T090041Z-241100
Show newest version
/*
 * 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