com.adobe.xfa.formcalc.CalcSymbol 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 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