@SuppressWarnings("unchecked")
  public <A extends Number & Comparable<A>> Collection<Predicate> numeric(
      NumberExpression<A> expr, NumberExpression<A> other, A knownValue) {
    List<Predicate> rv = new ArrayList<Predicate>();
    for (NumberExpression<?> num : projections.numeric(expr, other, knownValue, true)) {
      rv.add(num.lt(expr));
    }
    rv.add(expr.ne(other));
    rv.add(expr.ne(knownValue));
    rv.add(expr.goe(other));
    rv.add(expr.goe(knownValue));
    rv.add(expr.gt(other));
    rv.add(expr.gt(knownValue));
    rv.add(expr.loe(other));
    rv.add(expr.loe(knownValue));
    rv.add(expr.lt(other));
    rv.add(expr.lt(knownValue));

    rv.add(expr.in(1, 2, 3));
    rv.add(expr.in(1l, 2l, 3l));

    if (expr.getType().equals(Integer.class)) {
      NumberExpression<Integer> eint = (NumberExpression) expr;
      rv.add(eint.between(1, 2));
      rv.add(eint.notBetween(1, 2));
      rv.add(eint.mod(5).eq(0));
    } else if (expr.getType().equals(Double.class)) {
      NumberExpression<Double> edouble = (NumberExpression) expr;
      rv.add(edouble.between(1.0, 2.0));
      rv.add(edouble.notBetween(1.0, 2.0));
    } else if (expr.getType().equals(Long.class)) {
      NumberExpression<Long> elong = (NumberExpression) expr;
      rv.add(elong.mod(5l).eq(0l));
    }

    //        rv.add(expr.in(IntervalImpl.create(0, 100)));

    return ImmutableList.copyOf(rv);
  }
  @SuppressWarnings("unchecked")
  public Collection<Predicate> string(
      StringExpression expr, StringExpression other, String knownValue) {
    List<Predicate> rv = new ArrayList<Predicate>();
    if (expr instanceof Path && other instanceof Path) {
      rv.addAll(pathFilters(expr, other, knownValue));
    }
    rv.addAll(comparable(expr, other, knownValue));
    for (SimpleExpression<String> eq : projections.string(expr, other, knownValue)) {
      rv.add(eq.eq(other));
    }
    rv.add(expr.between("A", "Z"));

    rv.add(expr.charAt(0).eq(knownValue.charAt(0)));

    rv.add(expr.notBetween("A", "Z"));

    rv.add(expr.contains(other));
    rv.add(expr.contains(knownValue.substring(0, 1)));
    rv.add(expr.contains(knownValue.substring(1, 2)));

    rv.add(expr.containsIgnoreCase(other));
    rv.add(expr.containsIgnoreCase(knownValue.substring(0, 1)));
    rv.add(expr.containsIgnoreCase(knownValue.substring(1, 2)));

    rv.add(expr.endsWith(other));
    rv.add(expr.endsWith(knownValue.substring(1)));
    rv.add(expr.endsWith(knownValue.substring(2)));

    rv.add(expr.equalsIgnoreCase(other));
    rv.add(expr.equalsIgnoreCase(knownValue));

    rv.add(expr.in(Arrays.asList(knownValue)));

    rv.add(expr.indexOf(other).gt(0));
    rv.add(expr.indexOf("X", 1).gt(0));
    rv.add(expr.indexOf(knownValue).gt(0));

    rv.add(expr.locate(other).gt(1));
    if (!target.equals(Target.FIREBIRD)) { // FIXME
      rv.add(expr.locate("X", 2).gt(1));
    }
    rv.add(expr.locate(knownValue).gt(1));

    //        if (!module.equals(Module.HQL) && !module.equals(Module.JDOQL) &&
    // !module.equals(Module.SQL)) {
    //            rv.add(expr.lastIndexOf(other).gt(0));
    //            rv.add(expr.lastIndexOf(knownValue).gt(0));
    //        }

    rv.add(expr.in("A", "B", "C"));

    rv.add(expr.isEmpty());
    rv.add(expr.isNotEmpty());

    rv.add(expr.length().gt(0));

    rv.add(expr.like(knownValue.substring(0, 1) + "%"));
    rv.add(expr.like("%" + knownValue.substring(1)));
    rv.add(expr.like("%" + knownValue.substring(1, 2) + "%"));

    rv.add(expr.like(knownValue.substring(0, 1) + "%", '!'));
    rv.add(expr.like("%" + knownValue.substring(1), '!'));
    rv.add(expr.like("%" + knownValue.substring(1, 2) + "%", '!'));

    rv.add(expr.notLike(knownValue.substring(0, 1) + "%"));
    rv.add(expr.notLike("%" + knownValue.substring(1)));
    rv.add(expr.notLike("%" + knownValue.substring(1, 2) + "%"));

    if (!target.equals(Target.DERBY)
        && !target.equals(Target.FIREBIRD)
        && !target.equals(Target.HSQLDB)
        && !target.equals(Target.H2)
        && !target.equals(Target.SQLITE)
        && !target.equals(Target.SQLSERVER)) {
      rv.add(expr.matches(knownValue.substring(0, 1) + ".*"));
      rv.add(expr.matches(".*" + knownValue.substring(1)));
      rv.add(expr.matches(".*" + knownValue.substring(1, 2) + ".*"));
    }

    rv.add(expr.notIn("A", "B", "C"));

    rv.add(expr.notBetween("A", "Z"));
    rv.add(expr.notBetween(other, other));

    if (!target.equals(Target.DERBY) && !module.equals(Module.JDO)) {
      // https://issues.apache.org/jira/browse/DERBY-4389
      rv.add(new Coalesce<String>(String.class, expr, other).getValue().eq("xxx"));
    }

    //        rv.add(expr.in(IntervalImpl.create("A", "Z")));

    return ImmutableList.copyOf(rv);
  }