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 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 #3
0
 protected void assertBooleanQuery() throws ExpInvalidException {
   // queryExp must be a boolean expression
   if (!fQueryExp.type().isBoolean())
     throw new ExpInvalidException(
         "Argument expression of `"
             + name()
             + "' must have boolean type, found `"
             + fQueryExp.type()
             + "'.");
 }
Beispiel #4
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);
  }