Re: Type-safe qualifiers

From: Andrey Razumovsky (razumovsky.andre..mail.com)
Date: Thu Dec 31 2009 - 04:24:53 EST

  • Next message: Andrus Adamchik: "Re: Type-safe qualifiers"

    Type-safing for expressions is cool, but I have few questions about its
    profitness.
    Just a couple examples.

    1. Instead of:
    Expression clause2 = ExpressionFactory.matchExp(Artist.PAINTINGS_PROPERTY +
    "." + Painting.NAME_PROPERTY, "Y");
    I prefer using just
    Expression clause2 = ExpressionFactory.matchExp("paintings.paintingName",
    "Y");
    Yes, I don't like using constants, to me bottom example seems more readable,
    short and quicker to write (especially if there are a lot of items in the
    path). As far as I understood, this will not be allowed in new API (?)

    2. I wrote a library which automatically builds Cayenne expressions from
    values user specified in grid filter of Web (GWT) client - path is coming
    from client. With new API, shall I have something like
    CayenneDataObject.getKey(String) method to obtain any key in uniform way?
    (even with that, I will have more work to do to convert path to new API,
    maybe we need some method like Key Cayenne.getNestedKey(Class clazz, String
    path)?

    3. I have examples of intentionally not following type-safing for
    expressions (these are real examples)

      a. EF.matchExp("artist", "200") - quick comparison of relation object's id
      b. EF.lessExp("date", "2010-01-01 10:00:00.000") - replacement of date (or
    int, double, whatever) with just string

    Will those be allowed somehow in new API?

    Happy New Year!!!

    2009/12/30 Andrus Adamchik <andru..bjectstyle.org>

    > 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);
    >
    > public static final String NAME_PROPERTY = "name";
    > public static final Key<String> NAME = new
    > Key<String>(NAME_PROPERTY);
    >
    > public static final String PAINTINGS_PROPERTY = "paintings";
    > public static final Key<Painting> PAINTINGS = new Key<Painting>(
    > PAINTINGS_PROPERTY);
    > ...
    >
    > Key class is a builder of type-safe key-value expressions (see the link
    > above for the type of methods that it has). I wrote a quick API-only
    > prototype that is a replacement of ExpressionFactory. Here is an example of
    > building the following Expression the old way and the new way:
    >
    > Expression: name='X' and (painting.name='Y' or painting.name='Z' or
    > painting.name='A')
    >
    > 1. Current API:
    >
    > Expression clause1 = ExpressionFactory.matchExp(Artist.NAME_PROPERTY, "X");
    > Expression clause2 = ExpressionFactory.matchExp(Artist.PAINTINGS_PROPERTY +
    > "." + Painting.NAME_PROPERTY, "Y");
    > Expression clause3 = ExpressionFactory.matchExp(Artist.PAINTINGS_PROPERTY +
    > "." + Painting.NAME_PROPERTY, "Z");
    > Expression clause4 = ExpressionFactory.matchExp(Artist.PAINTINGS_PROPERTY +
    > "." + Painting.NAME_PROPERTY, "A");
    >
    > Expression clause23 = clause2.orExp(clause3);
    > Expression clause234 = clause23.orExp(clause4);
    > Expression qualifier = clause1.andExp(clause234);
    >
    > 2. New API:
    >
    > Expression clause1 = Artist.NAME.eq("X");
    > Expression clause2 = Artist.PAINTINGS.dot(Painting.NAME).eq("Y");
    > 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). 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.
    >
    > I'd like to see if a similar approach can be extended to query building.
    > Although that'll be a entirely different level of effort. For one thing it
    > may force us to reconcile EJQBL and SelectQuery into a single query
    > (SelectQuery is functionally a subset of EJBQLQuery. But SelectQuery
    > "compilation" into SQL is fairly optimized, while EJBQLQuery-to-SQL
    > conversion involves a much longer and slower pipeline). Plus of course there
    > are other obstacles that we discussed before (such as a variety of possible
    > result types).
    >
    > Andrus
    >
    >
    >
    >
    >
    >

    -- 
    Andrey
    



    This archive was generated by hypermail 2.0.0 : Thu Dec 31 2009 - 04:25:54 EST