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

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

The 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.text.Collator;

import com.adobe.xfa.ut.StringUtils;


/**
 * This class defines static methods to implement
 * the FormCalc logical calculations.
 *
 *  L O G I C A L   F U N C T I O N S
 *      choose, if, oneof, throw, within.
 *
 * @author Mike P. Tardif
 *
 * @exclude from published api.
 */
final class BuiltinLogical {

	/*
	 *  Disallow instances of this class.
	 */
	private BuiltinLogical() {
	}

	/*
	 *  Choose
	 *      This function returns a choosen a string from a given set of values.
	 */
	static void Choose(CalcParser oParser, CalcSymbol[] oArgSym) {
		final int nArgs = oArgSym.length;
		CalcSymbol oRetSym = null;
		try {
			//
			// check the number of args vs the number required.
			//
			Builtins.minArgs(nArgs, 2);
			//
			// check for error-valued, return-valued and null-valued args.
			//
			Builtins.limitExceptionArgs(oArgSym);
			Builtins.limitNullArgs(oParser, 1, oArgSym);
			//
			// evaluate the given args.
			//
			int nVal = (int) oParser.getNumeric(oArgSym[0]);
			//
			// choose the requested string.
			//
			for (int i = 1; i < nArgs; ) {
				if (oArgSym[i].getType() == CalcSymbol.TypeAccessor) {
					CalcSymbol[] oSym = oParser.moScriptHost.getItemValue(
							oArgSym[i].getName(), oArgSym[i].getObjValues());
					int nSyms = oSym.length;
					for (int j = 0; j < nSyms; j++) {
						if (i + j == nVal) {
							oRetSym = new CalcSymbol(oSym[j]);
							break;
						}
					}
					for (int j = nSyms - 1; j >=0; j--)
						CalcSymbol.delete(oSym[j], oParser);
					i += nSyms;
				}
				else {
					if (i == nVal) {
						oRetSym = new CalcSymbol(oArgSym[i]);
					}
					i += 1;
				}
				if (oRetSym != null) {
					break;
				}
			}
			//
			// if index not found the null value.
			//
			if (oRetSym == null) {
				oRetSym = new CalcSymbol("");
			}
		} catch (CalcException e) {
			oRetSym = e.getSymbol();
			if (oRetSym.getType() != CalcSymbol.TypeNull)
				oParser.mbInThrow = true;
		}
		//
		// push the result on the stack.
		//
		oParser.mStack.push(oRetSym);
	}


	/*
	 *  If
	 *      This function returns values conditionally based on the value of
	 *      a given number.
	 */
	static void If(CalcParser oParser, CalcSymbol[] oArgSym) {
		final int nArgs = oArgSym.length;
		CalcSymbol oRetSym = null;
		try {
			//
			// check the number of args vs the number required.
			//
			Builtins.minArgs(nArgs, 2);
			Builtins.maxArgs(nArgs, 3);
			//
			// check for error-valued, return-valued and null-valued args.
			//
			Builtins.limitExceptionArgs(oArgSym);
			Builtins.limitNullArgs(oParser, 1, oArgSym);
			//
			// evaluate the given args.
			//
			double nVal = oParser.getNumeric(oArgSym[0]);
			CalcSymbol oSym1 = new CalcSymbol(oArgSym[1]);
			oParser.getNumeric(oSym1);
			CalcSymbol oSym2 = null;
			if (nArgs > 2) {
				oSym2 = new CalcSymbol(oArgSym[2]);
				oParser.getNumeric(oSym2);
			}
			else {
				oSym2 = new CalcSymbol("");
			}
			if (nVal != 0.) {
				oRetSym = oSym1;
				CalcSymbol.delete(oSym2, oParser);
			}
			else {
				oRetSym = oSym2;
				CalcSymbol.delete(oSym1, oParser);
			}
		} catch (CalcException e) {
			oRetSym = e.getSymbol();
			if (oRetSym.getType() != CalcSymbol.TypeNull)
				oParser.mbInThrow = true;
		}
		//
		// push the result on the stack.
		//
		oParser.mStack.push(oRetSym);
	}


	/*
	 *  Oneof
	 *      This function returns true, a.k.a., 1, if the first given value
	 *      matches any of the remaining given set of values.
	 */
	static void Oneof(CalcParser oParser, CalcSymbol[] oArgSym) {
		final int nArgs = oArgSym.length;
		CalcSymbol oRetSym = null;
		try {
			//
			// check the number of args vs the number required.
			//
			Builtins.minArgs(nArgs, 2);
			//
			// check for error-valued and return-valued args.
			//
			Builtins.limitExceptionArgs(oArgSym);
			//
			// determine if one of the given set.
			//
			oRetSym = computeOneof(oParser, oArgSym);
		} catch (CalcException e) {
			oRetSym = e.getSymbol();
			if (oRetSym.getType() != CalcSymbol.TypeNull)
				oParser.mbInThrow = true;
		}
		//
		// push the result on the stack.
		//
		oParser.mStack.push(oRetSym);
	}


	/*
	 *  Throw
	 *      This function throws the given value and the empty string if no
	 *      value is given.
	 */
	static void Throw(CalcParser oParser, CalcSymbol[] oArgSym) {
		final int nArgs = oArgSym.length;
		CalcSymbol oRetSym = null;
		try {
			//
			// check the number of args vs the number required.
			//
			Builtins.maxArgs(nArgs, 1);
			//
			// check for error-valued and return-valued args.
			//
			Builtins.limitExceptionArgs(oArgSym);
			//
			// convert the given arg to string and return it.
			//
			String sVal = (nArgs > 0) ? oParser.getString(oArgSym[0])
														: "";
			oRetSym = new CalcSymbol(sVal);
			oRetSym.setType(CalcSymbol.TypeReturn);
		} catch (CalcException e) {
			oRetSym = e.getSymbol();
		}
		//
		// push the result on the stack.
		//
		oParser.mbInThrow = true;
		oParser.mStack.push(oRetSym);
	}


	/*
	 *  Within
	 *      This function returns true, a.k.a., 1, if the first given value
	 *      is within the given bound values.
	 */
	static void Within(CalcParser oParser, CalcSymbol[] oArgSym) {
		final int nArgs = oArgSym.length;
		CalcSymbol oRetSym = null;
		try {
			//
			// check the number of args vs the number required.
			//
			Builtins.minArgs(nArgs, 3);
			Builtins.maxArgs(nArgs, 3);
			//
			// check for error-valued, return-valued and null-valued args.
			//
			Builtins.limitExceptionArgs(oArgSym);
			Builtins.limitNullArgs(oParser, 1, oArgSym);
			//
			// determine if within the given bounds.
			//
			oRetSym = computeWithin(oParser, oArgSym);
		} catch (CalcException e) {
			oRetSym = e.getSymbol();
			if (oRetSym.getType() != CalcSymbol.TypeNull)
				oParser.mbInThrow = true;
		}
		//
		// push the result on the stack.
		//
		oParser.mStack.push(oRetSym);
	}


	static CalcSymbol computeOneof(CalcParser oParser, CalcSymbol[] oArgSym) {
		final int nArgs = oArgSym.length;
		CalcSymbol oRetSym = null;
		try {
			boolean bOneof = false;
			int fType = oArgSym[0].getType();
			//
			// determine if the first given argument matches any of the
			// given set of values.
			//
			if (fType == CalcSymbol.TypeAccessor) {
				CalcSymbol[] oSym
					= oParser.moScriptHost.getItemValue(oArgSym[0].getName(),
													oArgSym[0].getObjValues());
				CalcSymbol oTmpSym = oArgSym[0];
				oArgSym[0] = oSym[0];
				CalcSymbol oOneof = computeOneof(oParser, oArgSym);
				if (oParser.getNumeric(oOneof) == 1.) {
					bOneof = true;
				}
				CalcSymbol.delete(oOneof, oParser);
				oArgSym[0] = oTmpSym;
				for (int j = oSym.length - 1; j >=0; j--)
					CalcSymbol.delete(oSym[j], oParser);
			}
			else if (fType == CalcSymbol.TypeDouble) {
				double nVal = oParser.getNumeric(oArgSym[0]);
				for (int i = 1; i < nArgs; i++) {
					if (oArgSym[i].getType() == CalcSymbol.TypeAccessor) {
						CalcSymbol[] oSym = oParser.moScriptHost.getItemValue(
							oArgSym[i].getName(), oArgSym[i].getObjValues());
						int nSyms = oSym.length;
						for (int j = 0; j < nSyms; j++) {
							if (nVal == oParser.getNumeric(oSym[j])) {
								bOneof = true;
								break;
							}
						}
						for (int j = oSym.length - 1; j >=0; j--)
							CalcSymbol.delete(oSym[j], oParser);
					}
					else {
						if (nVal == oParser.getNumeric(oArgSym[i])) {
							bOneof = true;
						}
					}
					if (bOneof) {
						break;
					}
				}
			}
			else if (fType == CalcSymbol.TypeString
										|| fType == CalcSymbol.TypeVariable) {
				String sVal = oParser.getString(oArgSym[0]);
				for (int i = 1; i < nArgs; i++) {
					if (oArgSym[i].getType() == CalcSymbol.TypeAccessor) {
						CalcSymbol[] oSym = oParser.moScriptHost.getItemValue(
							oArgSym[i].getName(), oArgSym[i].getObjValues());
						int nSyms = oSym.length;
						for (int j = 0; j < nSyms; j++) {
							if (sVal.equals(oParser.getString(oSym[j]))) {
								bOneof = true;
								break;
							}
						}
						for (int j = oSym.length - 1; j >=0; j--)
							CalcSymbol.delete(oSym[j], oParser);
					}
					else {
						if (sVal.equals(oParser.getString(oArgSym[i]))) {
							bOneof = true;
						}
					}
					if (bOneof) {
						break;
					}
				}
			}
			else if (fType == CalcSymbol.TypeNull) {
				for (int i = 1; i < nArgs; i++) {
					if (oArgSym[i].getType() == CalcSymbol.TypeAccessor) {
						CalcSymbol[] oSym = oParser.moScriptHost.getItemValue(
							oArgSym[i].getName(), oArgSym[i].getObjValues());
						int nSyms = oSym.length;
						for (int j = 0; j < nSyms; j++) {
							if (fType == oSym[j].getType()) {
								bOneof = true;
								break;
							}
						}
						for (int j = nSyms - 1; j >=0; j--)
							CalcSymbol.delete(oSym[j], oParser);
					}
					else {
						if (fType == oArgSym[i].getType()) {
							bOneof = true;
						}
					}
					if (bOneof) {
						break;
					}
				}
			}
			else /* if (fType == CalcSymbol.TypeReturn
										|| fType == CalcSymbol.TypeError) */ {
				throw new CalcException(oArgSym[0]);
			}
			oRetSym = new CalcSymbol(bOneof ? 1. : 0.);
		} catch (CalcException e) {
			oRetSym = e.getSymbol();
			if (oRetSym.getType() != CalcSymbol.TypeNull)
				oParser.mbInThrow = true;
		}
		return oRetSym;
	}


	static CalcSymbol computeWithin(CalcParser oParser, CalcSymbol[] oArgSym) {
		CalcSymbol oRetSym = null;
		try {
			boolean bWithin = false;
			int fType = oArgSym[0].getType();
			//
			// determine if the first given argument matches any of the
			// given set of values.
			//
			if (fType == CalcSymbol.TypeAccessor) {
				CalcSymbol[] oSym = oParser.moScriptHost.getItemValue(
							oArgSym[0].getName(), oArgSym[0].getObjValues());
				CalcSymbol oTmpSym = oArgSym[0];
				oArgSym[0] = oSym[0];
				CalcSymbol oWithin = computeWithin(oParser, oArgSym);
				if (oParser.getNumeric(oWithin) == 1.)  {
					bWithin = true;
				}
				CalcSymbol.delete(oWithin, oParser);
				oArgSym[0] = oTmpSym;
				for (int j = oSym.length - 1; j >=0; j--)
					CalcSymbol.delete(oSym[j], oParser);
			}
			else if (oArgSym[0].isNumeric()) {
				double nVal = oParser.getNumeric(oArgSym[0]);
				double nValLo = oParser.getNumeric(oArgSym[1]);
				double nValHi = oParser.getNumeric(oArgSym[2]);
				if (nValLo <= nVal && nVal <= nValHi) {
					bWithin = true;
				}
			}
			else if (fType == CalcSymbol.TypeString
										|| fType == CalcSymbol.TypeVariable) {
				String sVal = oParser.getString(oArgSym[0]);
				String sValLo = oParser.getString(oArgSym[1]);
				String sValHi = oParser.getString(oArgSym[2]);
				Collator oCol = Collator.getInstance();
				if (oCol.compare(sVal, sValLo) >= 0
										&& oCol.compare(sVal, sValHi) <= 0) {
					bWithin = true;
				}
			}
			oRetSym = new CalcSymbol(bWithin ? 1. : 0.);
		} catch (CalcException e) {
			oRetSym = e.getSymbol();
			if (oRetSym.getType() != CalcSymbol.TypeNull)
				oParser.mbInThrow = true;
		}
		return oRetSym;
	}


	/*
	 *  Exists
	 *      This function returns true, a.k.a., 1, if the given argument
	 *      is an accessor reference to an existing object.
	 */
	static void Exists(CalcParser oParser, CalcSymbol[] oArgSym) {
		final int nArgs = oArgSym.length;
		CalcSymbol oRetSym = null;
		try {
			//
			// check the number of args vs the number required.
			//
			Builtins.minArgs(nArgs, 1);
			Builtins.maxArgs(nArgs, 1);
			//
			// determine if within the given arg is null.
			//
			CalcSymbol oSymIn = new CalcSymbol(oArgSym[0]);
			int nRetVal = 1;
			switch (oSymIn.getType())  {
			case CalcSymbol.TypeAccessor:
				if (oSymIn.getName().indexOf('*') >= 0) { // more precisely, "[*]"
					CalcSymbol.delete(oSymIn, oParser);
					throw new CalcException();
				}
				if (! isObject(oParser, oSymIn))
					nRetVal = 0;
				break;
			case CalcSymbol.TypeReference:
				if (oSymIn.getObjValue() == null)
					nRetVal = 0;
				break;
			case CalcSymbol.TypeNull:
			case CalcSymbol.TypeDouble:
			case CalcSymbol.TypeString:
			case CalcSymbol.TypeVariable:
				nRetVal = 0;
				break;
			case CalcSymbol.TypeError:
			case CalcSymbol.TypeReturn:
			default:
				CalcException e = new CalcException(oSymIn);
				CalcSymbol.delete(oSymIn, oParser);
				throw e;
			}
			CalcSymbol.delete(oSymIn, oParser);
			oRetSym = new CalcSymbol(nRetVal);
		} catch (CalcException e) {
			oRetSym = e.getSymbol();
			if (oRetSym.getType() != CalcSymbol.TypeNull)
				oParser.mbInThrow = true;
		}
		//
		// push the result on the stack.
		//
		oParser.mStack.push(oRetSym);
	}


	/*
	 *  HasValue
	 *      This function returns true, a.k.a., 1, if the given value
	 *      is not null, and not empty.
	 */
	static void HasValue(CalcParser oParser, CalcSymbol[] oArgSym) {
		final int nArgs = oArgSym.length;
		CalcSymbol oRetSym = null;
		try {
			//
			// check the number of args vs the number required.
			//
			Builtins.minArgs(nArgs, 1);
			Builtins.maxArgs(nArgs, 1);
			//
			// check for error-valued and return-valued args.
			//
			Builtins.limitExceptionArgs(oArgSym);
			//
			// determine if given string is empty.
			//
			String s = oParser.getString(oArgSym[0]).trim();
			oRetSym = new CalcSymbol(StringUtils.isEmpty(s) ? 0. : 1.);
		} catch (CalcException e) {
			oRetSym = e.getSymbol();
			if (oRetSym.getType() != CalcSymbol.TypeNull)
				oParser.mbInThrow = true;
		}
		//
		// push the result on the stack.
		//
		oParser.mStack.push(oRetSym);
	}


	static boolean isObject(CalcParser oParser, CalcSymbol oArgSym) {
		try {
			CalcSymbol[] oSym = oParser.moScriptHost.getItemValue(
									oArgSym.getName(), oArgSym.getObjValues());
			for (int j = oSym.length - 1; j >=0; j--)
				CalcSymbol.delete(oSym[j], oParser);
			return true;
		} catch (CalcException e) {
			try {
				oParser.moScriptHost.getItem(oArgSym.getName(),
													oArgSym.getObjValues());
				return true;
			} catch (CalcException f) {
			}
		}
		return false;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy