Extending EOGenerator templates

The default EOGenerator templates (JavaSourceEOF52.eotemplate and JavaSubclassSourceEOF5.eotemplate) only implement the basic logic in the generated _EO.java and EO.java classes.

I’m assuming you know what eogenerator does, and you understand how the _EO.java and EO.java classes relate to one another. If you don’t, ask, and I’ll try to explain.

For instance, for an entity named Person with the attributes firstName and lastName and a to many relationship to PhoneNumbers named phoneNumbers you’d end up with this:

  • Getter and setter accessor methods for firstName
  • Getter and setter accessor methods for lastName
  • Getter and setter methods for phoneNumbers
  • addTo and removeFrom methods for phoneNumbers

This is about the same amount of java that you’d get from EOModeler if it generated your java for you. Acceptable, but we can do much better.

My Template

My templates (which you can download here) are derived from the advanced sample template that ships with eogenerator (EOGJavaSource.eotemplate) and create the following additional methods in your _EO.java class:

For each to-many relationships

  • addToRelationshipNameRelationship(Object obj) – calls addObjectToBothSidesOfRelationshipWithKey on the relationship with obj
  • removeFromRelationshipNameRelationship(Object obj) – calls removeObjectFromBothSidesOfRelationshipWithKey on the relationship with obj
  • createRelationshipNameRelationship() – creates a new object matching the destination type of the relationship, inserts it into this EO’s EOEditingContexts and adds it to the relationship.
  • deleteRelationshipNameRelationship(Object obj) – removes obj from the relationship and then calls editingContext().deleteObject(obj)
  • deleteAllRelationshipNameRelationships – iterates through all of the objects in the relationship, calling deleteRelationshipNameRelationship.

For each model defined fetch specifications

  • objectsForFetchSpecificationName(EOEditingContext ec, AObject aObjectBinding, BObject bObjectBinding, …) – a static method that returns any objects matching the fetch spec FetchSpecificationName. It takes typed objects for any bindings defined in the fetchSpec.

Using the templates

Using my templates is straight forward, simply specify them when you call EOGenerator (see this post for more details). Before you use my templates however, you will need to specify the name of the class that your EO’s should inherit from (EOGenericRecord is the default). Replace the reference to CBEOBaseClass in the constructor section of CBJavaSourceEOF5.eotemplate (it should be around line 29).

Extending the templates

EOGenerator uses a tool called MiscMerge to create the java class from the EOModel. There is a MiscMerge.rtf included in the eogenerator distribution, but you can figure out what is going on pretty easily just by looking at the templates (the template that does most of the work is CBJavaSourceEOF5.eotemplate).

One of the downsides to using Key Value Coding is that you lose compile time checking on valueForKey methods. For instance, calling:

valueForKey("anAtribute")

will compile fine, but fail at runtime if the attribute is actually called anAttribute.

So, one extension you may wish to make to my templates is to have static strings created to that map to each of your attributes. This means that you can call:

valueForKey(MyEO.AN_ATTRIBUTE)

and the compiler will catch your typos.

The EOGJavaSource.eotemplate included with eogenerator includes an example of how to do this. The template code between line 34 and 39 will create a static string variable for each of your attributes and relationships. Simply copy these lines of code (in between the <$comment … $> and <$comment) and paste them below the constructor in CBJavaSourceEOF5.eotemplate.

EOGenerator is a very powerful tool, it will get you a lot of machine generated (and more importantly machine maintained) code that will make your applications simpler and easier to build. I highly recommend exploring its capabilities a little.

6 thoughts on “Extending EOGenerator templates

  1. David … absolutely excellent article. ….. this provided more meaty opportunities for the next time I upgrade my EO generator templates. Thanks, Kieran

  2. I’ve just finished figuring out a Boolean issue with EOF which I used EOGenerator to fix I thought it might make a good addition.
    In EOModeler Booleans are defined as an NSNumber with the type set to ‘c’. This doesn’t work very well for some databases (PostgreSQL). EOGenerator doesn’t take the value Type into account so I added this…
    ——-

    < $foreach Attribute classAttributes.@sortedNameArray do$>
    < $if Attribute.javaValueClassName eq 'Number' and Attribute.valueType eq 'c'$>
        public Boolean < $Attribute.name$>() {
            return (Boolean)storedValueForKey("< $Attribute.name$>");
        }
    
        public void set< $Attribute.name.initialCapitalString$>(Boolean aValue) {
            takeStoredValueForKey(aValue, "< $Attribute.name$>");
        }
    < $else$>
        public < $Attribute.javaValueClassName$> < $Attribute.name$>() {
            return (< $Attribute.javaValueClassName$>)storedValueForKey("< $Attribute.name$>");
        }
    
        public void set< $Attribute.name.initialCapitalString$>(< $Attribute.javaValueClassName$> aValue) {
            takeStoredValueForKey(aValue, "< $Attribute.name$>");
        }
    < $endif$>< $endforeach do
    $>

    ——

    Just thought it might be useful to someone.

  3. Thanks for your great introduction to eogenerator and eotemplates.
    Hopefully you have a moment to help me. I am having a problem with fetchspecificaiton qaulifier variables. In your example the eotemplate expression to build the binding dictionary <$if FetchSpec.bindings.count > 0$> fails to produce the expected java code even though the eotemplate expression to build the method declaration <$foreach Binding FetchSpec.bindings do2$> correctly includes the bindings in the produced method declaration. Is there an additional EOModeler step required to include qualifier $varibles bindings so that FetchSpec.bindings.count evaluates correctly?

    Thanks again!

  4. Hmm,

    Try changing this line:

    <$if FetchSpec.bindings.count > 0$>

    To this:

    <$if FetchSpec.bindings.@count > 0$>

Comments are closed.