Beispiel #1
0
  protected ExpQuery(
      Type resultType, VarDeclList elemVarDecls, Expression rangeExp, Expression queryExp)
      throws ExpInvalidException {
    super(resultType, rangeExp, queryExp);
    fElemVarDecls = elemVarDecls;
    fRangeExp = rangeExp;
    fQueryExp = queryExp;

    // type of rangeExp must be a subtype of Collection, i.e. Set,
    // Sequence or Bag
    if (!fRangeExp.type().isCollection(false))
      throw new ExpInvalidException(
          "Range expression must be of type " + "`Collection', found `" + fRangeExp.type() + "'.");

    // assert that declard element variables are equal or
    // supertypes of range element type
    Type rangeElemType = ((CollectionType) fRangeExp.type()).elemType();

    for (int i = 0; i < fElemVarDecls.size(); i++) {
      VarDecl vd = fElemVarDecls.varDecl(i);
      if (!rangeElemType.isSubtypeOf(vd.type()))
        throw new ExpInvalidException(
            "Type `"
                + vd.type()
                + "' of range variable `"
                + vd.name()
                + "' does not match type `"
                + rangeElemType
                + "' of collection elements.");
    }
  }
Beispiel #2
0
  /** Evaluate isUnique expression. */
  protected final Value evalIsUnique(EvalContext ctx) {
    // evaluate range
    Value v = fRangeExp.eval(ctx);
    if (v.isUndefined()) return UndefinedValue.instance;
    CollectionValue rangeVal = (CollectionValue) v;

    // collect values for finding duplicates
    Set<Value> values = new HashSet<Value>();

    // loop over range elements
    for (Value elemVal : rangeVal) {

      // bind element variable to range element, if variable was
      // declared
      if (!fElemVarDecls.isEmpty()) ctx.pushVarBinding(fElemVarDecls.varDecl(0).name(), elemVal);

      // evaluate collect expression
      Value val = fQueryExp.eval(ctx);

      if (!fElemVarDecls.isEmpty()) ctx.popVarBinding();

      // stop if duplicate element is found
      if (values.contains(val)) return BooleanValue.FALSE;
      else values.add(val);
    }

    // result is true if no duplicates where found
    return BooleanValue.TRUE;
  }
Beispiel #3
0
  /** Evaluate collect expressions. */
  protected final Value evalCollectNested(EvalContext ctx) {
    // evaluate range
    Value v = fRangeExp.eval(ctx);
    if (v.isUndefined()) return UndefinedValue.instance;
    CollectionValue rangeVal = (CollectionValue) v;

    // prepare result value
    ArrayList<Value> resValues = new ArrayList<Value>();

    // loop over range elements
    for (Value elemVal : rangeVal) {

      // bind element variable to range element, if variable was
      // declared
      if (!fElemVarDecls.isEmpty()) ctx.pushVarBinding(fElemVarDecls.varDecl(0).name(), elemVal);

      // evaluate collect expression
      Value val = fQueryExp.eval(ctx);

      // add element to result
      resValues.add(val);

      if (!fElemVarDecls.isEmpty()) ctx.popVarBinding();
    }

    // result is collection with mapped values
    if (fRangeExp.type().isSequence() || fRangeExp.type().isOrderedSet())
      return new SequenceValue(fQueryExp.type(), resValues);
    else return new BagValue(fQueryExp.type(), resValues);
  }
Beispiel #4
0
  @Override
  public StringBuilder toString(StringBuilder sb) {
    fRangeExp.toString(sb);
    sb.append("->").append(this.name()).append("(");

    if (!fElemVarDecls.isEmpty()) {
      fElemVarDecls.toString(sb);
      sb.append(" | ");
    }

    fQueryExp.toString(sb);
    return sb.append(")");
  }
Beispiel #5
0
  /** Evaluate sortedBy expressions. */
  protected final Value evalSortedBy(EvalContext ctx) {
    // evaluate range
    Value v = fRangeExp.eval(ctx);
    if (v.isUndefined()) return UndefinedValue.instance;
    CollectionValue rangeVal = (CollectionValue) v;

    ArrayList<KeyValPair> keyValList = new ArrayList<KeyValPair>();

    // loop over range elements
    for (Value elemVal : rangeVal) {

      // bind element variable to range element, if variable was
      // declared
      if (!fElemVarDecls.isEmpty()) ctx.pushVarBinding(fElemVarDecls.varDecl(0).name(), elemVal);

      // evaluate sortedBy expression and store the result as a
      // key together with elemVal
      Value key = fQueryExp.eval(ctx);
      keyValList.add(new KeyValPair(key, elemVal));

      if (!fElemVarDecls.isEmpty()) ctx.popVarBinding();
    }

    // sort elements by key
    Collections.sort(
        keyValList,
        new Comparator<KeyValPair>() {
          public int compare(KeyValPair o1, KeyValPair o2) {
            return o1.fKey.compareTo(o2.fKey);
          }
        });

    // drop the keys from the list
    ListIterator<KeyValPair> listIter = keyValList.listIterator();
    Collection<Value> result = new ArrayList<Value>(keyValList.size());

    while (listIter.hasNext()) {
      KeyValPair kvp = listIter.next();
      result.add(kvp.fElem);
    }

    Type rangeElemType = ((CollectionType) fRangeExp.type()).elemType();
    return new SequenceValue(rangeElemType, result);
  }
Beispiel #6
0
  /** Evaluate select and reject expressions. */
  protected final Value evalSelectOrReject(EvalContext ctx, boolean doSelect) {
    // evaluate range
    Value v = fRangeExp.eval(ctx);
    if (v.isUndefined()) return UndefinedValue.instance;
    CollectionValue rangeVal = (CollectionValue) v;

    // prepare result value
    ArrayList<Value> resValues = new ArrayList<Value>();
    Type elemType = rangeVal.elemType();
    if (!rangeVal.type().isInstantiableCollection())
      throw new RuntimeException("rangeVal is not of collection type: " + rangeVal.type());

    // loop over range elements
    for (Value elemVal : rangeVal) {

      // bind element variable to range element, if variable was
      // declared
      if (!fElemVarDecls.isEmpty()) ctx.pushVarBinding(fElemVarDecls.varDecl(0).name(), elemVal);

      // evaluate select expression
      Value queryVal = fQueryExp.eval(ctx);

      // undefined query values default to false
      if (queryVal.isUndefined()) queryVal = BooleanValue.FALSE;

      if (((BooleanValue) queryVal).value() == doSelect) resValues.add(elemVal);

      if (!fElemVarDecls.isEmpty()) ctx.popVarBinding();
    }

    CollectionValue res;
    if (rangeVal.type().isSet()) res = new SetValue(elemType, resValues);
    else if (rangeVal.type().isSequence()) res = new SequenceValue(elemType, resValues);
    else if (rangeVal.type().isBag()) res = new BagValue(elemType, resValues);
    else if (rangeVal.type().isOrderedSet()) res = new OrderedSetValue(elemType, resValues);
    else {
      // should not happen
      throw new RuntimeException("rangeVal is not of collection type: " + rangeVal.type());
    }
    // result is collection with selected/rejected values
    return res;
  }
Beispiel #7
0
  private final boolean evalExistsOrForAll0(
      int nesting, CollectionValue rangeVal, EvalContext ctx, boolean doExists) {
    // loop over range elements
    boolean res = !doExists;

    for (Value elemVal : rangeVal) {

      // bind element variable to range element, if variable was
      // declared
      if (!fElemVarDecls.isEmpty())
        ctx.pushVarBinding(fElemVarDecls.varDecl(nesting).name(), elemVal);

      if (!fElemVarDecls.isEmpty() && nesting < fElemVarDecls.size() - 1) {
        // call recursively to iterate over range while
        // assigning each value to each element variable
        // eventually
        if (res != doExists) res = evalExistsOrForAll0(nesting + 1, rangeVal, ctx, doExists);
        else
          // don't change the result value when expression is true
          // (exists) or
          // false (forAll) and continue iteration
          evalExistsOrForAll0(nesting + 1, rangeVal, ctx, doExists);
      } else {
        // evaluate predicate expression
        Value queryVal = fQueryExp.eval(ctx);

        // undefined query values default to false
        if (queryVal.isUndefined()) queryVal = BooleanValue.FALSE;

        // don't change the result value when expression is true
        // (exists) or
        // false (forAll) and continue iteration
        if (res != doExists && ((BooleanValue) queryVal).value() == doExists) res = doExists;
      }

      if (!fElemVarDecls.isEmpty()) ctx.popVarBinding();
    }

    return res;
  }