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

com.adobe.xfa.formcalc.CalcSymbol Maven / Gradle / Ivy

There is a newer version: 2024.11.18751.20241128T090041Z-241100
Show newest version
/*
 * ADOBE CONFIDENTIAL
 *
 * Copyright 2007 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.formcalc;


import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;

import com.adobe.xfa.Obj;

import com.adobe.xfa.ut.FindBugsSuppress;
import com.adobe.xfa.ut.MsgFormat;
import com.adobe.xfa.ut.ResId;
import com.adobe.xfa.ut.IntegerHolder;

/**
 * Class CalcSymbol defines objects which are the typed-values
 * used by the {@link CalcParser} (FormCalc scripting engine).
 *
 * 

Each CalcSymbol have but two properties: a type, * and depending on the type, a value. and a storage type. * Some types of CalcSymbols have extra values. * *

This is the implementation of the fundamental class of * objects manipulated by FormCalc parser and interpreter. * Objects of this class populate both the data symbol table, * and the builtin symbol table, the runtime stack, and constitute * the operands of some instructions, as well as the final * result of every FormCalc parser/interpreter operation. * *

@author Paul Imerson, Mike P. Tardif * * @exclude from published api. */ public final class CalcSymbol { /** *


	 * 
	 * typedef enum TypeEnum {
	 *       TypeError = 0,
	 *       TypeNull,
	 *       TypeString,
	 *       TypeDouble,
	 *       TypeBuiltin,
	 *       TypeVariable,
	 *       TypeReference,
	 *       TypeParameter,
	 *       TypeFunction,
	 *       TypeAccessor,
	 *       TypeReturn
	 * } int;
* Enumeration of all possible CalcSymbol types. * Most are internal to the FormCalc scripting engine. * Applications would only deal with types: *
    *
  • TypeString, *
  • TypeError, *
  • TypeNull. *
*/ public static final int TypeError = 0; public static final int TypeNull = 1; public static final int TypeString = 2; public static final int TypeDouble = 3; // internal only to FormCalc engine public static final int TypeBuiltin = 4; // internal only to FormCalc engine public static final int TypeVariable = 5; // internal only to FormCalc engine public static final int TypeReference = 6; // internal only to FormCalc engine public static final int TypeParameter = 7; // internal only to FormCalc engine public static final int TypeFunction = 8; // internal only to FormCalc engine public static final int TypeAccessor = 9; // internal only to FormCalc engine public static final int TypeReturn = 10; // internal only to FormCalc engine /* *

	 * 
	 * typedef enum StoreEnum {
	 *       StoreTemp = 0,
     *       StorePerm,
	 *       StoreFroz
	 * } int;
* Enumeration of all possible CalcSymbol storage mode. * Note: this enumeration is internal to the * FormCalc engine -- it is not for public use. */ static final int StoreTemp = 0; static final int StorePerm = 1; static final int StoreFroz = 2; static final int StorePrelim = 0x10; /** * Instantiates a CalcSymbol of type * TypeNull. */ public CalcSymbol() { mNext = null; mName = null; setScope(0); setObjValue(null); mValue = null; mStore = StoreTemp; mType = TypeNull; } /** * Instantiates a CalcSymbol of type * TypeDouble. * * @param nVal the numeric value of the CalcSymbol. */ public CalcSymbol(int nVal) { mNext = null; mName = null; setScope(0); setObjValue(null); setNumericValue((double) nVal); mStore = StoreTemp; mType = TypeDouble; } /** * Instantiates a CalcSymbol of type * TypeDouble * if the value of the given double is finite, and of type * TypeError * if the value of the given double is not finite. * * @param dVal the double value of the CalcSymbol. */ public CalcSymbol(double dVal) { mNext = null; mName = null; setScope(0); setObjValue(null); mStore = StoreTemp; if (isFinite(dVal)) { setNumericValue(dVal); mType = TypeDouble; } else { MsgFormat oErr = new MsgFormat(ResId.FC_ERR_ARITHMETIC); setErrorValue(oErr.toString()); setLineAndError(0); mType = TypeError; } } /** * Instantiates a CalcSymbol of type * TypeString * if the given boolean isError is false, and a CalcSymbol * of type * TypeError * is the given boolean is true. * * @param sVal the string value of the CalcSymbol if * the given boolean isError is false, and the error value of * the CalcSymbol if the given boolean is true. * @param bIsError a boolean indicating if the instantiated * CalcSymbol is to be of type TypeError, or * of type TypeString. The defaults is for the CalcSymbol * to be of type TypeString. * @param nErrorLine if bIsError is true, this contains the associated * line number in the context of syntax errors (not run-time errors). * if the value of the given boolean is false, and an error-valued * CalcSymbol if the value of the given boolean is true. * @param nErrorResId - if bIsError is TRUE, this contains the associated resource ID * of the error. */ public CalcSymbol(String sVal, boolean bIsError /* = false */, int nErrorLine /* = 0 */, int nErrorResId /* = 0 */) { mNext = null; mName = null; setScope(0); setObjValue(null); setStringValue(sVal); mStore = StoreTemp; if (bIsError) { mType = TypeError; setLineAndError(encodeLineAndErrorResId(nErrorLine, nErrorResId)); } else { mType = TypeString; } } /** * Instantiates a CalcSymbol of type * TypeString. * * @param sVal the string value of the CalcSymbol. */ public CalcSymbol(String sVal) { mNext = null; mName = null; setScope(0); setStringValue(sVal); mStore = StoreTemp; mType = TypeString; } /** * Instantiates a CalcSymbol of type * TypeBuiltin. * * @param func the builtin function. */ public CalcSymbol(Method func) { mNext = null; mName = ""; setScope(0); setFuncValue(func); mStore = StorePerm; mType = TypeBuiltin; } /** * Instantiates a CalcSymbol of type * TypeReference. * * @param oObj the object handle. * @param sName optionally, the object name. */ public CalcSymbol(Obj oObj, String sName /* = null */) { mNext = null; mName = null; setScope(0); mValue = null; mStore = StoreTemp; mType = TypeNull; if (oObj != null) { if (sName != null) mName = sName; setObjValue(oObj); mType = TypeReference; } } /** * Instantiates a CalcSymbol as a copy of the given CalcSymbol. * * @param oSym the CalcSymbol to copy. */ public CalcSymbol(CalcSymbol oSym) { mNext = null; mName = null; setScope(0); mValue = null; mStore = StoreTemp; mType = oSym.mType; assign(oSym); } /** * Assigns the given CalcSymbol to this object. * * @param oSym the CalcSymbol being assigned. * @return this object. */ @FindBugsSuppress(code="SF") CalcSymbol assign(CalcSymbol oSym) { mNext = oSym.mNext; mName = oSym.mName; mType = oSym.mType; switch (oSym.mType) { case TypeDouble: mValue = oSym.mValue; break; case TypeVariable: setScope(oSym.getScope()); /*FALLTHRU*/ case TypeReturn: case TypeString: mValue = oSym.mValue; break; case TypeAccessor: if (getObjs() > 0) { setObjValue(null); } setObjValues(oSym.getObjValues()); break; case TypeReference: if (getObjs() > 0) { setObjValue(null); } setObjValue(oSym.getObjValue()); break; case TypeError: mValue = oSym.mValue; setLineAndError(oSym.getLineAndError()); break; case TypeFunction: setCntValue(oSym.getCntValue()); setAddr(oSym.getAddr()); break; case TypeParameter: setIdxValue(oSym.getIdxValue()); break; case TypeBuiltin: setFuncValue(oSym.getFuncValue()); break; default: setNumericValue(0.); break; } mStore = StoreTemp; return this; } /** * Conditionally delete this CalcSymbol. Only delete if this * CalcSymbol is of temporary store or if the parser allows it. * * @param pParser the FormCalc parser. */ static void delete(CalcSymbol oSym, CalcParser oParser) { // Check for corruption assert (oSym.mType == CalcSymbol.TypeError || oSym.mType == CalcSymbol.TypeNull || oSym.mType == CalcSymbol.TypeString || oSym.mType == CalcSymbol.TypeDouble || oSym.mType == CalcSymbol.TypeBuiltin || oSym.mType == CalcSymbol.TypeVariable || oSym.mType == CalcSymbol.TypeReference || oSym.mType == CalcSymbol.TypeParameter || oSym.mType == CalcSymbol.TypeFunction || oSym.mType == CalcSymbol.TypeAccessor || oSym.mType == CalcSymbol.TypeReturn); if (oParser.mbDeleteOk || (oSym.mStore & ~CalcSymbol.StorePrelim) == CalcSymbol.StoreTemp) oSym = null; } /** * Compares the given CalcSymbol for equality. * * @param object the CalcSymbol being compared with. * @return boolean true if equal, and false otherwise. */ public boolean equals(Object object) { if (this == object) return true; // This overrides Object.equals(boolean) directly, so... if (object == null) return false; if (object.getClass() != getClass()) return false; CalcSymbol oCompare = (CalcSymbol) object; if (mType != oCompare.mType) return false; if (mName == null || oCompare.mName == null) return false; if (! mName.equals(oCompare.mName)) return false; if (mStore != oCompare.mStore) return false; switch (mType) { case TypeNull: return true; case TypeDouble: return mValue.equals(oCompare.mValue); case TypeReturn: case TypeString: return mValue.equals(oCompare.mValue); case TypeError: return (mValue.equals(oCompare.mValue) && getLineAndError() == oCompare.getLineAndError()); case TypeVariable: if (getScope() != oCompare.getScope()) return false; if (mValue == null) return (oCompare.mValue == null); else if (oCompare.mValue != null) return (mValue.equals(oCompare.mValue)); else /* if (mValue != null && oCompare.mValue == null) */ return false; case TypeAccessor: case TypeReference: return getObjValue() == oCompare.getObjValue(); // todo case TypeParameter: return getIdxValue() == oCompare.getIdxValue(); case TypeBuiltin: return getFuncValue() == oCompare.getFuncValue(); case TypeFunction: if (getAddr() != oCompare.getAddr()) return false; return getCntValue() == oCompare.getCntValue(); default: assert false; break; } return false; } /** * Returns a hash code value for the object. * @exclude from published api. */ public int hashCode() { int result = mType; result = (result * 31) ^ (mName == null ? 0 : mName.hashCode()); result = (result * 31) ^ mStore; result = (result * 31) ^ mType; switch (mType) { case TypeNull: break; case TypeDouble: case TypeReturn: case TypeString: result = (result * 31) ^ mValue.hashCode(); break; case TypeError: result = (result * 31) ^ mValue.hashCode(); result = (result * 31) ^ getLineAndError(); break; case TypeVariable: result = (result * 31) ^ getScope(); result = (result * 31) ^ (mValue == null ? 0 : mValue.hashCode()); break; case TypeAccessor: case TypeReference: { Obj obj = getObjValue(); result = (result * 31) ^ (obj == null ? 0 : obj.hashCode()); break; } case TypeParameter: result = (result * 31) ^ getIdxValue(); break; case TypeBuiltin: { Method method = getFuncValue(); result = (result * 31) ^ (method == null ? 0 : method.hashCode()); break; } case TypeFunction: result = (result * 31) ^ getAddr(); result = (result * 31) ^ getCntValue(); break; default: assert false; break; } return result; } /** * Gets this object's name. * @return the object's name. */ public String getName() { return mName; } /** * Sets this object's name. * * @param sName the object's new name. */ void setName(String name) { assert(name != null); mName = name; } /** * Gets this object's type. * @return the object's type. * @return the type of this object. Applications will always ever * get one of TypeNull, TypeString, or * TypeError returned. */ public int getType() { return mType; } /** * Sets this object's type. * * @param eType the object's new type. */ void setType(int eType) { mType = eType; } /** * Gets this object's storage. * * @return the object's storage. */ int getStore() { return mStore; } /** * Sets this object's storage. * * @param eStore the object's new storage. */ void setStore(int eStore) { mStore = eStore; } /** * Gets this TypeAccessor's line count and error ResId. * * @return the object's line count and error ResId. */ int getLineAndError() { return mExtra; } /** * Sets this TypeAccessor's line count and error ResId. * * @param nLineAndError the TypeFunction new line count and error ResId. */ void setLineAndError(int nLineAndError) { mExtra = nLineAndError; } /** * Gets this object's scope index. Only CalcSymbols of type * TypeVariable have scope indexes. * * @return the object's scope. */ int getScope() { return mExtra; } /** * Sets this object's scope index. Only CalcSymbols of type * TypeVariable have scope indexes. * * @param nScope the object's new scope. */ void setScope(int nScope) { mExtra = nScope; } /** * Gets this TypeFunction's machine address. * * @return the object's machine address. */ int getAddr() { return mExtra; } /** * Sets this TypeFunction's machine address. * * @param nAddr the TypeFunction new machine address. */ void setAddr(int nAddr) { mExtra = nAddr; } /** * Gets this TypeAccessor's object count. * * @return the object's object count. */ int getObjs() { return mExtra; } /** * Sets this TypeAccessor's object count. * * @param nObjs the TypeFunction new object count. */ void setObjs(int nObjs) { mExtra = nObjs; } /** * Gets the next CalcSymbol in the list. * * @return the next CalcSymbol in the list. */ CalcSymbol getNext() { return mNext; } /** * Sets the next CalcSymbol in the list. * * @param oNext the next CalcSymbol in the list. */ void setNext(CalcSymbol oNext) { mNext = oNext; } /** * Gets this TypeReference's object handle. * * @return the object's object handle. */ public Obj getObjValue() { return (mObjs != null) ? mObjs[0] : null; } /** * Gets this TypeReference's object handles. * * @return the object's object handles. */ Obj[] getObjValues() { return mObjs; } /** * Sets this TypeReference's object handle. * * @param oObj the object's new object handle. */ void setObjValue(Obj oObj) { mObjs = null; setObjs(0); if (oObj != null) { setObjs(1); mObjs = new Obj[getObjs()]; mObjs[0] = oObj; } } /** * Sets this TypeReference's object handles. * * @param oObj the object's new object handles. */ void setObjValues(Obj[] oObj) { mObjs = null; setObjs(0); if (oObj != null) { setObjs(oObj.length); mObjs = new Obj[getObjs()]; for (int i = 0; i < getObjs(); i++) { mObjs[i] = oObj[i]; } } } /** * Gets this TypeBuiltin's function value. */ Method getFuncValue() { return (Method) mValue; } /** * Gets this TypeBuiltin's function value. * * @param oParser the parser context. * @param oCntx the parser context. * @param oArgs the array of CalcSymbols. */ Object getFuncValue(CalcParser oParser, CalcSymbol[] oArgs) { try { Method func = (Method) mValue; Object[] args = new Object[] { oParser, oArgs }; func.invoke(null, args); } catch(IllegalAccessException e) { assert (e != null); } catch(InvocationTargetException e) { assert (e != null); } return mValue; } /** * Sets this TypeBuiltin's function value. * * @param oFunc the method. */ void setFuncValue(Method oFunc) { mValue = oFunc; } /** * Gets this TypeFunction's argument count. * * @return the object's argument count. */ int getCntValue() { return ((Integer) mValue).intValue(); } /** * Sets this TypeFunction's argument count. * * @param nIdx the object's new argument count. */ void setCntValue(int nCnt) { mValue = Integer.valueOf(nCnt); } /** * Gets this TypeParameter's stack index. * * @return the object's stack index. */ public int getIdxValue() { return ((Integer) mValue).intValue(); } /** * Sets this TypeParameter's stack index. * * @param nIdx the object's new stack index. */ void setIdxValue(int nIdx) { mValue = Integer.valueOf(nIdx); } /** * Gets this TypeString's string value. * This method presumes the CalcSymbol if of type * TypeString. * Otherwise, the result is indeterminate. * * @return the object's string value. */ public String getStringValue() { return (mType == TypeNull) ? null : (String) mValue; } /** * Sets this TypeString's string value. * * @param str the object's new string value. */ void setStringValue(String str) { mValue = str; } /** * Gets this TypeDouble's numeric value. * This method presumes the CalcSymbol if of type * TypeDouble. * Otherwise, the result is indeterminate. * * @return the object's numeric value. */ public double getNumericValue() { return ((Double) mValue).doubleValue(); } /** * Sets this TypeDouble's numeric value. * * @return the object's numeric value. */ void setNumericValue(double dbl) { mValue = new Double(dbl); } /** * Gets this TypeError's error value. * This method presumes the CalcSymbol if of type * TypeError. * Otherwise, the result is indeterminate. * @param oErrorLine if non-null, populated with the line * number of the error, in the context of syntax errors * (not run-time errors). * @param oErrorCode - if non-NULL, populated with the error * code of the error, in the context of syntax errors * (not run-time errors). * @return the object's error value. */ public String getErrorValue(IntegerHolder oErrorLine /* = null */, IntegerHolder oErrorCode /* = null */) { if (oErrorLine != null) oErrorLine.value = decodeLine(mExtra); if (oErrorCode != null) oErrorCode.value = decodeErrorResId(mExtra); // Not supported yet. return (String) mValue; } /** * Sets this TypeError's error value. * * @param err the object's new error value. */ void setErrorValue(String err) { mValue = err; } /** * Sets this TypeDouble's to a TypeString, * by converting its numeric value to the string * equivalent. */ void setTypeToString() { if (mType == TypeDouble) { StringBuilder sStr = new StringBuilder( FormCalcUtil.dblToStr(getNumericValue(), 11)); FormCalcUtil.trimZeroes(sStr); FormCalcUtil.trimRadix(sStr); FormCalcUtil.trimSign(sStr); setStringValue(sStr.toString()); mType = TypeString; } else if (mType == TypeVariable) { mType = (mValue != null) ? TypeString : TypeNull; } if (mType == TypeString && isNumeric()) { StringBuilder sStr = new StringBuilder(getStringValue()); FormCalcUtil.trimSign(sStr); setStringValue(sStr.toString()); } } /** * Is this object numeric-valued. * * @return boolean true if this object is of type * TypeDouble, * or is of type * TypeString * and its string value is numeric. */ boolean isNumeric() { boolean bRetVal = false; switch (mType) { case TypeDouble: bRetVal = true; break; case TypeString: case TypeVariable: if (mValue != null && getStringValue().length() > 0) bRetVal = FormCalcUtil.strIsNumeric(getStringValue()); break; default: break; } return bRetVal; } int mType; // symbol type. int mStore; // symbol storage. String mName; // symbol name. Object /* union { // Javaport: collapsed into a single Object. double num; // TypeDouble's numeric value. String str; // TypeString's string value. String err; // TypeError's error message. Obj[] obj; // TypeReference's object handles. int cnt; // TypeFunction's argument count. int idx; // TypeParameter's stack index. Method func; // TypeBuiltin's function pointer. } */ mValue; // symbol value: Obj[] mObjs; // TypeReference's object handles. int /* union { // Javaport: collapsed into a single int. int addr; // TypeFunction's instruction address. int scope; // TypeVariable's scope index. int objs; // TypeAccessor's object count. int lineAndError; // TypeError's optional line number, and error code (combined). } */ mExtra; // extra symbol value: CalcSymbol mNext; // next symbol. private static boolean isFinite(double d) { if (Double.isNaN(d) || Double.isInfinite(d)) return false; return true; } static int encodeLineAndErrorResId(int nLine, int nResId) { assert((nLine & 0xFFFF) == nLine); assert((nResId & 0xFFFF) == nResId); return (nLine << 16) | (nResId & 0xFFFF); } static int decodeLine(int nLineAndErrorResId) { return nLineAndErrorResId >> 16; } static int decodeErrorResId(int nLineAndErrorResId) { return (nLineAndErrorResId & 0xFFFF); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy