سؤال

I have some troubles to implement what I need.

Code better than words : Here is where I set up my predicate, it is add a FilterRow in a DBManager. What I'd like is to get all my member entries who have an ID equal to 64 and 61. My problem is that I just get the id with the ID = 61.

PredicateManager    pred = new PredicateManager();      
String[]            nameColumn = new String[]{"id", "id"};      
String[]            criteria = new String[]{"eq", "eq"};        
Comparable<?>[]     min = new Comparable[]{61, 64};     
Comparable<?>[]     max = new Comparable[]{0, 0};       
Predicate           test = new PredicateORImpl(min, max, null, nameColumn, criteria);

pred.addFilter("Filtre 1", test);
members = facade.read("resources/XML/member.xml", pred);
for (int i = 0 ; i < members.size(); i++) {
    AbstractMember maValeur = members.get(i);
    System.out.println(maValeur.toString());
}

Here is my Predicate manager, in case of I need severals Predicates :

private Map<String,Predicate>               filters;

@Override
public boolean                              evaluate(RowSet rs) {
    boolean isOk = true;
    for (Predicate predicate : filters.values()){
        isOk = predicate.evaluate(rs);
    }
    return isOk;
}

And this my Predicate Implementation :

@Override
public boolean                              evaluate(RowSet rs) {
    try {
        boolean isOk = true;
        int rowNb = (row != null) ? row.length : rowName.length;
        for (int i = 0; i < rowNb && isOk; i++) {
            switch (criteria[i]) {
            case "eq":
                isOk &= equal(rs.getObject(rowName[i]), rowName[i]);
                break;
            case "gt":
                isOk &= greaterThan(rs.getObject(rowName[i]), rowName[i]);
                break;
            case "lt":
                isOk &= lessThan(rs.getObject(rowName[i]), rowName[i]);
                break;
            case "ge":
                isOk &= greaterOrEqualThan(rs.getObject(rowName[i]), rowName[i]);
                break;
            case "le":
                isOk &= lessOrEqualThan(rs.getObject(rowName[i]), rowName[i]);
                break;
            case "between":
                isOk &= between(rs.getObject(rowName[i]), rowName[i]);
                break;
            default: break;
            }
        }
        return isOk;
    }
    catch(SQLException sqle) { return false; }
}

private boolean                             equal(Object value, String columnName) {
    int column = Arrays.asList(rowName).indexOf(columnName);
    Comparable min = this.min[column];
    return (min.compareTo(value) == 0);
}

Thanks a lot for your help.

هل كانت مفيدة؟

المحلول

all my member entries who have an ID equal to 64 and 61

I suspect the problem is that you want records where your ID is 64 OR 61. An ID cannot be both 64 AND 61 at the same time.

By trying to place two conflicting criteria on the same field you are replacing the first with the second.

I suggest you have a predicate for each element of the expression like a tree. e.g.

interface Predicate<T> {
    boolean test(T t);
}

class EqualsColumnPredicate implement Predicate<ResultSet> {
    final String columnName;
    final Object value;
    // create a constructor to set these

    public boolean test(ResultSet rs) {
         return rs.getObject(columnName).equals(value); // TODO check for nulls
    }
}

class OrPredicate<T> implements Predicate<T> {
    final Prediate<T>[] preciates;
    // create a constructor for this field
    public boolean test(T t) {
         for(Predicate<T> p : predicates)
             if(p.test(t)) return true;
        return false;
    }
}

Predicate<T> where = new OrPredicate<ResultSet>(
   new EqualsColumnPredicate("column", 64),
   new EqualsColumnPredicate("column", 61));

while(rs.next())
   if (where.test(rs))
       // found !!
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top