Example #1
0
  /**
   * Returns a minimum or maximum item.
   *
   * @param cmp comparator
   * @param qc query context
   * @return resulting item
   * @throws QueryException query exception
   */
  Item minmax(final OpV cmp, final QueryContext qc) throws QueryException {
    final Collation coll = toCollation(1, qc);

    final Iter iter = exprs[0].atomIter(qc, info);
    Item curr = iter.next();
    if (curr == null) return null;

    // check if first item is comparable
    cmp.eval(curr, curr, coll, sc, info);

    // strings
    if (curr instanceof AStr) {
      for (Item it; (it = iter.next()) != null; ) {
        if (!(it instanceof AStr)) throw EXPTYPE_X_X_X.get(info, curr.type, it.type, it);
        final Type rt = curr.type, ri = it.type;
        if (cmp.eval(curr, it, coll, sc, info)) curr = it;
        if (rt != ri && curr.type == URI) curr = STR.cast(curr, qc, sc, info);
      }
      return curr;
    }
    // dates, durations, booleans, binary values
    if (curr instanceof ADate || curr instanceof Dur || curr instanceof Bin || curr.type == BLN) {
      for (Item it; (it = iter.next()) != null; ) {
        if (curr.type != it.type) throw EXPTYPE_X_X_X.get(info, curr.type, it.type, it);
        if (cmp.eval(curr, it, coll, sc, info)) curr = it;
      }
      return curr;
    }
    // numbers
    if (curr.type.isUntyped()) curr = DBL.cast(curr, qc, sc, info);
    for (Item it; (it = iter.next()) != null; ) {
      final Type type = numType(curr, it);
      if (cmp.eval(curr, it, coll, sc, info) || Double.isNaN(it.dbl(info))) curr = it;
      if (type != null) curr = (Item) type.cast(curr, qc, sc, info);
    }
    return curr;
  }