Пример #1
0
  /**
   * 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));
      }
    }
  }
Пример #2
0
  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);
    }
  }
Пример #3
0
  /**
   * 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;
  }