Sometimes there is a need to build an expression by combining other existing expressions. Also quiet often it is desirable to use strongly typed API instead of interpreted string expressions. The following sections describe ExpressionFactory and Expression methods that allow to construct expressions step by step via API calls.

### Path/Value Expressions

The most simple expressions are the ones that match an object property path with a value or a list of values. ExpressionFactory provides a set of methods to build such "path/value" expressions:

- public static Expression matchExp(String pathSpec, Object value)
- public static Expression noMatchExp(String pathSpec, Object value)
- public static Expression matchDbExp(String pathSpec, Object value)
- public static Expression lessExp(String pathSpec, Object value)
- public static Expression lessOrEqualExp(String pathSpec, Object value)
- public static Expression greaterExp(String pathSpec, Object value)
- public static Expression greaterOrEqualExp(String pathSpec, Object value)
- public static Expression inExp(String pathSpec, Object[] values)
- public static Expression inExp(String pathSpec, java.util.List values)
- public static Expression betweenExp(String pathSpec, Object value1, Object value2)
- public static Expression likeExp(String pathSpec, Object value)
- public static Expression likeIgnoreCaseExp(String pathSpec, Object value)
- public static Expression notInExp(String pathSpec, Object value)
- public static Expression notBetweenExp(String pathSpec, Object value)
- public static Expression notLikeExp(String pathSpec, Object value)
- public static Expression notLikeIgnoreCaseExp(String pathSpec, Object value)

As was mentioned earlier, the type of a second Object argument depends on the type of property path points to. It is important to mention that paths that end with a relationship name (both to-one and to-many) can be matched against DataObjects, thus removing the need to know PK or FK values when building expressions. This behavior is not specific to ExpressionFactory, it works the same way with Expression.fromString(..) as well.

    import org.apache.cayenne.exp.Expression;
    import org.apache.cayenne.exp.ExpressionFactory;
    import org.apache.cayenne.query.SelectQuery;
    ...

    // find artist paintings (if we don't want to use relationship for whatever reason)

    Artist a = ...;
    Expression qual = ExpressionFactory.matchExp("toArtist", a);
    SelectQuery select = new SelectQuery(Painting.class, qual);

### Chaining Expressions

Expression class itself provides a set of convenience methods to chain expressions as they are built from smaller parts. Note that each of these methods does not modify the original expression, rather it builds and returns a new instance of the expression.

- public Expression joinExp(int type, Expression exp)
  Creates and returns a new expression that joins this object with another expression, using specified join type. This is a shorter equivalent of ExpressionFactory.binaryExpression(type, this, exp).
- public Expression andExp(Expression exp)
  A shorter equivalent for joinExp(Expression.AND, exp).
- public Expression orExp(Expression exp)
  A shorter equivalent for joinExp(Expression.OR, exp).

Example of using chaining:

    import org.apache.cayenne.exp.Expression;
    import org.apache.cayenne.exp.ExpressionFactory;
    import org.apache.cayenne.query.SelectQuery;
    ...

    // find artists whose name starts with "D"
    // with invalid or null date of birth

    Expression qual = ExpressionFactory.greaterOrEqualExp("dateOfBirth", new Date());

    // 1. chain expressions, note the assignment back to "qual",
    // since a new instance is created
    qual = qual.orExp(ExpressionFactory.matchExp("dateOfBirth", null));

    // 2. "AND" applies to a combined earlier criteria
    qual =
       qual.andExp(ExpressionFactory.likeIgnoreCaseExp("artistName", "D%"));

    SelectQuery select = new SelectQuery(Artist.class, qual);

### Creating Complex Expressions

There is a way to create complex expressions either from the Lists of expressions or from the Maps containing values using "path" Strings as keys. This approach significantly simplifies connecting Cayenne queries to the UI, and reduces the number of steps needed to create expressions in other cases. ExpressionFactory provides the following methods:

- public static Expression joinExp(int type, java.util.List expressions)
  Joins all expressions into a single expression. type is used as an expression type for expressions joining each one of the items on the list. type is normally AND or OR.
- public static Expression matchAllExp(java.util.Map map, int type)
  Creates an expression that matches all path/value pairs in map. Path is OBJ_PATH.
- public static Expression matchAllDbExp(java.util.Map map, int type)
  Same as above, but path is interpreted to be DB_PATH.
- public static Expression matchAnyExp(java.util.Map map, int type)
  Creates an expression that matches any of the path/value pairs in map. Path is OBJ_PATH.
- public static Expression matchAnyDbExp(java.util.Map map, int type)
  Same as above, but path is interpreted to be DB_PATH.

Example of creating complex expressions:

    HashMap map = new HashMap();
    map.put("login", "joeuser");
    map.put("password", "secret");

    // the last parameter refers to the operation inside each key/value pair.

    Expression qual = ExpressionFactory.matchAllExp(map, Expression.EQUAL_TO);