On 31/12/09 6:59 AM, Andrus Adamchik wrote:
While there's lots of things we need to figure out to create generified
queries, here is one low-hanging fruit - type-safe qualifiers. The idea
is borrowed from the WebObjects EOF extensions framework called Wonder:

http://webobjects.mdimension.com/hudson/job/Wonder53/javadoc/er/extensions/eof/ERXKey.html


The way it works, is that for each String property in a Persistent
object, we generate an extra parameterized "key". E.g.:

public class _Artist extends CayenneDataObject {

public static final String DATE_OF_BIRTH_PROPERTY = "dateOfBirth";
public static final Key<Date> DATE_OF_BIRTH = new Key<Date>(
DATE_OF_BIRTH_PROPERTY);

What a shame String is final, so Key can't just extend String. Oh well.

In the long term, perhaps the old property will go away, so perhaps this is a 
better first step:

  public static final Key<Date> DATE_OF_BIRTH = new Key<Date>("dateOfBirth");

  @deprecated
  public static final String DATE_OF_BIRTH_PROPERTY = DATE_OF_BIRTH.toString();


How does Key relate to Attribute and Relationship? Is it an interface that both 
implement?


2. New API:

Expression clause1 = Artist.NAME.eq("X");
Expression clause2 = Artist.PAINTINGS.dot(Painting.NAME).eq("Y");

Would this be more in keeping with existing usage:

  Artist.PAINTINGS.join(Painting.NAME).match("Y");

and

  Artist.PAINTINGS.outerJoin(Painting.NAME).match("Y");

to emulate the "|" we have now.


Expression clause3 = Artist.PAINTINGS.dot(Painting.NAME).eq("Z");
Expression clause4 = Artist.PAINTINGS.dot(Painting.NAME).eq("A");

Expression qualifier = Each.get(clause1, Any.get(clause2, clause3,
clause4));

As you see the new API is much tighter, and the first part of it is
completely type-safe (generated "keys" ensure that we are matching
against the right type of value, even in a multi-step path).

At first glance Artist.PAINTINGS looks like it should be <Collection<Painting>>. But 
that breaks the type-safeness. We can tell when a key represents a Relationship (<? extends 
PersistentObject>) rather than an Attribute. But would we ever want to know when it represents 
a to-many relation rather than a to-one?


 The last
line uses 2 new Expression factories, "Each" and "Any", to quickly
organize key-value expressions into a nested expression tree. I think
this is as good as it can get within the constraints of the Java syntax.

Any and Each are a bit obscure. You aren't going to find them by reading the 
Javadoc for Expression. What do they give over the existing orExp/andExp syntax?

  Expression qualifier = Each.get(clause1, Any.get(clause2, clause3, clause4));

  Expression qualifier = clause1.andExp(clause2.orExp(clause3).orExp(clause4));

Intuitively I don't equate "each" as meaning "all" or "and". Or even simpler:

  Expression qualifier = clause1.and(clause2.or(clause3).or(clause4));


Ari


--

-------------------------->
Aristedes Maniatis
GPG fingerprint CBFB 84B4 738D 4E87 5E5C  5EFA EF6A 7D2E 3E49 102A

Reply via email to