/** * Set the local variable to the given value. If the value is null, then the corresponding * variable will be removed. If there is a global variable of the same name, then an * EvaluationException will be thrown. * * @param name name of the local variable * @param terms terms used to dereference the variable, or null if the variable is to be used * directly * @param value value to use or null to remove the variable * @throws EvaluationException if there is a global variable with the same name as the local * variable */ public void setLocalVariable(String name, Term[] terms, Element value) throws EvaluationException { assert (name != null); if (terms == null || terms.length == 0) { // Revert back to the simple case that does not require // dereferencing. setLocalVariable(name, value); } else { // The more complicated case where we need to dereference the // variable. (And also possibly create the parents.) // Retrieve the value of the local variable. Element var = getLocalVariable(name); // If the value is a protected resource, then make a shallow copy // and replace the value of the local variable. if (var != null && var.isProtected()) { var = var.writableCopy(); setLocalVariable(name, var); } // If the value does not exist, create a resource of the correct // type and insert into variable table. if (var == null || var instanceof Undef) { Term term = terms[0]; if (term.isKey()) { var = new HashResource(); } else { var = new ListResource(); } setLocalVariable(name, var); } // Recursively descend to set the value. assert (var != null); try { var.rput(terms, 0, value); } catch (InvalidTermException ite) { throw new EvaluationException(ite.formatVariableMessage(name, terms)); } } }
public boolean executeDmlValidationBlock(Operation dml, Element self) throws ValidationException { Element result = null; // Store the old local variables and iterators. Needed because structure // templates need to keep the state across template.execute() calls. LocalVariableMap oldVariables = createLocalVariableMap(null); IteratorMap oldIterators = createIteratorMap(); // Initialize the SELF reference to the local self value. SelfHolder selfHolder = new ReadOnlySelfHolder(self); initializeSelfHolder(selfHolder); try { result = dml.execute(this); } catch (ReturnValueException rve) { result = rve.getElement(); } catch (EvaluationException ee) { File objectFile = (objectTemplate != null) ? objectTemplate.source : null; ValidationException ve = ValidationException.create(MSG_VALIDATION_FAILED_BECAUSE_OF_EXCEPTION); ve.setObjectTemplate(objectFile); ve.initCause(ee); throw ve; } finally { clearSelf(); restoreLocalVariableMap(oldVariables); restoreIteratorMap(oldIterators); } try { BooleanProperty bresult = (BooleanProperty) result; return bresult.getValue().booleanValue(); } catch (ClassCastException cce) { File objectFile = (objectTemplate != null) ? objectTemplate.source : null; ValidationException ve = ValidationException.create( MSG_INVALID_VALIDATION_FUNCTION_RETURN_TYPE, result.getTypeAsString()); throw ve.setObjectTemplate(objectFile); } }
/** * Return the Element which corresponds to the given variable name. It will first check local * variables and then the parent context. This method will return null if the variable doesn't * exist or the argument is null. Note that this will clone the final value, if it originated from * a global variable. * * @param name name of the variable to lookup * @param lookupOnly flag indicating if only a lookup should be done * @param terms values for dereferencing the given variable * @return Element value of the associated dereferenced variable */ public Element dereferenceVariable(String name, boolean lookupOnly, Term[] terms) throws InvalidTermException { boolean duplicate = false; Element result = localVariables.get(name); // If the result is null, then try to look up a global variable. if (result == null) { duplicate = true; result = getGlobalVariable(name); } // Now actually dereference the given variable. The caller must deal // with any invalid term exceptions or evaluation exceptions. We just // pass those on. if (result != null) { if (!(result instanceof Undef)) { // FIXME: Determine if the result needs to be protected. result = result.rget(terms, 0, false, lookupOnly); } else { // Trying to dereference an undefined value. Therefore, the // value does not exist; return null to caller. result = null; } } // FIXME: This is inefficient and should be avoided. However, one must // ensure that global variables are protected against changes. // To ensure that global variables are not inadvertently modified via // copies in local variables, duplicate the result. Do this only AFTER // the dereference to limit the amount of potentially unnecessary // cloning. if (duplicate && result != null) { result = result.duplicate(); } return result; }