protected static Constraint parseWhereConstraint(StreamKeywordTokenizer tokens, Filter filter)
      throws IOException {
    Constraint result = null;

    tokens.nextToken();
    if (tokens.ttype == '(') {
      result = parseWhereOr(tokens, filter);
      tokens.nextToken();
      if (tokens.ttype != ')') {
        throw FilterParserException.create(App.messages.getString("res.614"), tokens);
      }
    } else {
      tokens.pushBack();
      Object c1 = parseWhereValue(tokens, filter);
      String op = parseWhereOperator(tokens, filter);
      Object c2 = parseWhereValue(tokens, filter);

      result = new Constraint();
      result.setOperator(op);
      result.setLeftOperand(c1);
      result.setRightOperand(c2);
    }

    return result;
  }
  protected static Object parseWhereValue(StreamKeywordTokenizer tokens, Filter filter)
      throws IOException {
    tokens.nextToken();
    if (tokens.ttype == tokens.TT_VARIABLE || tokens.ttype == tokens.TT_WORD) {
      return filter.get(tokens.sval);
    } else if (tokens.ttype == tokens.TT_NUMBER) {
      return new Double(tokens.nval);
    } else if (tokens.ttype == '?') {
      return new QMark();
    } else if (tokens.ttype == '\'') {
      return tokens.sval;
    } else if (tokens.ttype == tokens.TT_KEYWORD && TRUE.equals(tokens.sval)) {
      return Boolean.TRUE;
    } else if (tokens.ttype == tokens.TT_KEYWORD && FALSE.equals(tokens.sval)) {
      return Boolean.FALSE;
    } /*else if (tokens.ttype == tokens.TT_KEYWORD
      		&& NULL.equals(tokens.sval)) {
      	return null;
      } */ else if (tokens.ttype == '(') { // for in operator ex: toto in
      // (1,2,3)
      tokens.nextToken();

      tokens.pushBack();
      HashSet list = new HashSet();
      do {
        Object o = parseWhereValue(tokens, filter);
        list.add(o);
        tokens.nextToken();
      } while (tokens.ttype == ',');
      if (tokens.ttype != ')') {
        throw FilterParserException.create(App.messages.getString("res.616"), tokens);
      }
      return list;
    }
    // TODO peut etre avoir un keyword DATE pour les dates: Date(31/12/2004)

    throw FilterParserException.create(App.messages.getString("res.617"), tokens);
  }
  protected static String parseWhereOperator(StreamKeywordTokenizer tokens, Filter filter)
      throws IOException {
    String result = "";

    tokens.nextToken();
    if (tokens.ttype == '=') {
      return result = "=";
    } else if (tokens.ttype == '<') {
      result = "<";
      if (tokens.nextToken() == '=') {
        result += "=";
      } else {
        tokens.pushBack();
      }
      return result;
    } else if (tokens.ttype == '>') {
      result = ">";
      if (tokens.nextToken() == '=') {
        result += "=";
      } else {
        tokens.pushBack();
      }
      return result;
    } else if (tokens.ttype == '!') {
      if (tokens.nextToken() == '=') {
        return result = "!=";
      }
    } else if (tokens.ttype == tokens.TT_KEYWORD) {
      //			if (NOT.equals(tokens.sval)) {
      //				result = "not ";
      //				tokens.nextToken();
      //			}
      //			if (tokens.ttype == tokens.TT_KEYWORD) {
      //				if (LIKE.equals(tokens.sval)) {
      //					return result += "like";
      //				} else if (IN.equals(tokens.sval)) {
      //					return result += "in";
      //				}
      //			}
    }

    throw FilterParserException.create(App.messages.getString("res.615"), tokens);
  }