README.md
7932fe51
 **Enterprise Object Generator  v1.7**
 
 *eogenerator* is a command-line tool for reading EOModel file(s) and generating
 EO classes from them, using a different method than Apple's EOModeler.  This
 approach allows all business logic to be implemented in the EO classes without
 fear of being overwritten later.  There is also support for having a custom
 superclass for the generated EO classes, and for generating Objective-C \#import
 statements correctly if EOModels related to each other reside in separate
 frameworks.
 
  
 
 Version 1.7 is built as a universal binary for Intel macs, fixes problems with
 Boolean attributes, adds character encoding parameters, and fixes a couple of
 other minor problems.
 
  
 
 To see the fetch specification and addObjectToBothSides... cover methods, look
 in the example EOGJavaSource.eotemplate (EOGObjCSource.eotemplate for
 Objective-C).
 
  
 
 EOModeler's EO generation is straightforward: it generates one class per
 EOEntity.  While this is fine for simple applications, it has a major limitation
 -- the generated code can't be edited, since a future code generation would
 overwrite the changes.  A common approach to this problem is to put all custom
 logic in categories, leaving the base classes free to be overwritten
 repeatedly.  However this also has some downsides: additional transient-type
 instance variables can't be added, the generated accessor methods can not be
 overridden easily, and of course it does not work at all with Java. Another
 approach is to not generate accessor methods at all, instead just using
 -valueForKey: and -takeValue:forKey: everywhere.  This has major downsides in
 that code is harder to read, it's a bit slower, scalar types can't be used, and
 a massive amount of compiler type-checking is lost.
 
  
 
 To get around these problems, *eogenerator* takes a different approach.  For
 each EOEntity, **two** classes are generated.  The first contains all the
 generated accessor methods and instance variables; it has a class name slightly
 different than the entity name and will be regenerated whenever its EOEntity has
 changed.  The second class is the actual EO class.  It is only generated the
 first time through, starting out as an empty subclass of the first. 
 
  
 
 As an example, if you have an *Employee* entity, *eogenerator* produces:
 
 \_Employee.java
 
 public class \_Employee extends EOGenericRecord (or EOCustomObject)
 
 Employee.java  (only if not present -- doesn't overwrite)
 
 public class Employee extends \_Employee
 
 Or, for Objective-C:
 
 \_Employee.h
 
 \@interface \_Employee : EOGenericRecord (or NSObject)
 
 \_Employee.m
 
 \@implementation \_Employee
 
 Employee.h (only if not present -- doesn't overwrite)
 
 \@interface Employee : \_Employee
 
 Employee.m (only if not present -- doesn't overwrite)
 
 \@implementation Employee
 
 This way, custom code can be placed in the "Employee" class without being
 overwritten, since only the "\_Employee" class is regenerated.  The accessor
 methods can be overridden while being able to call the super implementation, and
 instance variables can be added to the Employee class if desired.
 
 While the Employee class will not be overwritten thereafter, it will be
 "touched" (i.e. have its timestamp updated) whenever \_Employee is regenerated. 
 This is done to force a recompilation.  Read-only files will not be overwritten
 at all unless the -force flag is given.  A prefix for the generated class names
 other than the default "\_" can be given with the -prefix argument.
 
 (It has recently been pointed out to us that John Vlissides defined a design
 pattern called "Generation Gap" detailing this type of dual-class approach -- it
 can be found online at http://www.research.ibm.com/designpatterns/pubs/gg.html ,
 and apparently also in *Pattern Hatching: Design Patterns Applied* (chapter 3). 
 Thanks to Matt Shedlick for the pointer.)
 
 **Templates**
 
 The EO classes are produced using template files.  The default locations for
 finding the template files are the current directory, followed by the standard
 Library/Developer locations (which on MacOS X Server is
 \~/Developer/EOGenerator, \~/Library/EOGenerator, /Local/Developer/EOGenerator,
 /Local/Library/EOGenerator, /Network/Developer/EOGenerator, and
 /Network/Library/EOGenerator), followed by the directory containing the
 eogenerator binary.  These directories should contain *.eotemplate* files. 
 There are at least six files that are expected to be available, two each for
 Objective-C header, Objective-C source, and Java source files.  If versions
 exist in multiple search paths, the first one found is used.  The -templatedir
 command-line option allows adding more directories to the front of the search
 path.
 
 By default, the template files are named:
 
 JavaSourceEOF5.eotemplate
 
 JavaSourceEOF4.eotemplate
 
 JavaSourceEOF3.eotemplate
 
 JavaSourceEOF2.eotemplate
 
 JavaSubclassSourceEOF5.eotemplate
 
 JavaSubclassSourceEOF4.eotemplate
 
 JavaSubclassSourceEOF3.eotemplate
 
 JavaSubclassSourceEOF2.eotemplate
 
 JavaClientSourceEOF5.eotemplate
 
 JavaClientSourceEOF4.eotemplate
 
 JavaClientSourceEOF3.eotemplate
 
 JavaClientSubclassSourceEOF5.eotemplate
 
 JavaClientSubclassSourceEOF4.eotemplate
 
 ObjCHeader.eotemplate
 
 ObjCSource.eotemplate
 
 ObjCHeaderEOF3.eotemplate
 
 ObjCSourceEOF3.eotemplate
 
 ObjCSubclassHeader.eotemplate
 
 ObjCSubclassSource.eotemplate
 
 These templates produce source equivalent to that generated by EOModeler using
 the default Apple templates.  The templates for a specific version of EOF will
 be used by default on that platform.
 
 However, the default templates are more intended to work with minimum fuss out
 of the box, and do not necessarily represent the best programming practice.  For
 example, the default superclass is always EOCustomObject or EOGenericRecord\*,
 where it is usually better to define your own abstract superclass for your EO
 classes since a lot of abstract functionality can be added there.  For another
 example, these templates can be used to generate String constants for entity and
 attribute names, so that compile-time checked values can be passed into the
 various EOF APIs that require entity or attribute names.  Therefore, EOGenerator
 also supplies the following two files:
 
 EOGJavaSource.eotemplate
 
 MyGenericRecord.java
 
 These demonstrate how to put in a different EO superclass, generate String
 constants, generate typed creation methods, generate methods to call named fetch
 specifications with typed arguments, generate typed cover methods that invoke
 addObjectToBothSidesOfRelationshipWithKey(), and more.  It is usually a good
 idea to start with the above two files and customize from there rather than just
 use the default templates.  Note, however, that these templates will not work
 out of the box -- you have to make customized versions.  These templates are
 based on the WebObjects 5.x versions; you'll need to change them if you're using
 old EOF releases.
 
 Similarly, example Objective-C templates are provided (based on the WebObjects
 4.5.1 template).  The default Objective-C templates have the further problem of
 always doing \#import \<EOControl/EOControl.h\>, which is an extremely
 heavyweight header to be importing for each EO class (which has extra
 ramifications on Windows NT/2000).\*\*  The example templates show many of the
 same techniques as the example Java template, and also how to generate
 cross-framework \#imports correctly, and how to avoid \#importing too much.
 
 EOGObjCHeader.eotemplate
 
 EOGObjCSource.eotemplate
 
 Specific template files can be specified using the -sourceTemplate, 
 -headerTemplate, -subclassSourceTemplate, -subclassHeaderTemplate,
 -javaTemplate, and/or -subclassJavaTemplate flags.
 
 \* Many projects will want to use a custom abstract superclass instead, as it
 offers an easy way to implement behavior that affects all EOs.  For example, if
 there's a requirement to store all database fields in uppercase, you can
 implement validateValueForKey() to generically uppercase all String values that
 come through.  For Objective-C, you can implement reference counting with an
 instance variable instead of using NSObject's slower versions (sometimes a good
 idea since EOs are retained and released a lot).
 
 \*\* In general, many people feel that \#importing or \#including comprehensive
 header files "clutters" the namespace, i.e. you are more likely to have name
 conflicts in your code the more you \#import.  More practically, the
 preprocessor and compiler may have to do more work, slowing down compiles. 
 Precompiled headers solve the speed problem on OPENSTEP and MacOS X, but they
 don't work on Windows NT.  Worse, the NT linker isn't smart enough to unique
 debugging symbol information when it links multiple object files, so the more
 \#import's you have the bigger your .obj and .dll/.exe files are.  If \#import
 \<EOControl/EOControl.h\> is in every EO header file, that means that each EO
 class, plus any other source file that even indirectly \#imports an EO header
 (i.e. virtually all of them), will have entries for every single EOControl,
 Foundation, and ANSI C symbol in its object file.  Thus, the size of the final
 (unstripped) .dll/.exe will be huge, since it has lots of copies of each symbol
 entry.  This makes the linker use a lot more memory and temporary disk space,
 potentially making compiles go much slower.  In short, I feel it is better to
 limit the use of these comprehensive \#imports to being inside .m files only, if
 they're used at all.  The unfortunate downside is a lot of repetitive \#imports
 in each .m file.  It's probably useful to \#import a few specific EOControl and
 Foundation headers in the .h template file (or the custom superclass' .h file)
 to minimize this.
 
 **Template Formatting**
 
 The template files are implemented using the MiscMerge engine.  It is similar
 but more flexible than EOModeler's system, as (among other things) conditionals
 are allowed and it can be more easily extended.  Its usage should be fairly
 straightforward, but it has its peculiarities if you are picky about whitespace
 in the generated files.  See the included MiscMerge.rtf for a detailed
 description.
 
 The object used to drive the template engine is the EOEntity instance.  You may
 alter the template files and use methods associated with EOEntity to drive the
 output.  Most of the methods used are the same ones that Apple's templates use,
 which are implemented in EOModeler.framework.  *eogenerator* implements some
 additional methods that can be used, which can be found in FoundationAdditions.h
 and EOAccessAdditions.h.  Additionally, values that should be available to the
 templates can be specified on the command line using the -define-\<key\>
 parameter.
 
 Of particular note for Objective-C is the EOModel method **-frameworkName**. 
 The framework name is derived from finding the framework the .eomodeld is
 contained in, either by the PB.project file or a path component ending in
 ".framework".  This information is then used by other EOEntity extension methods
 to generate cross-framework \#imports correctly.  While the framework name
 should be derived correctly in almost all cases, when necessary it can be set
 explicitly by putting the framework name under the "EOGeneratorFrameworkName"
 key in the EOModel's userInfo dictionary.
 
 **Please do not add timestamps to the templates!**  (Do not use the MiscMerge
 "date" command.)  Before a file is generated, it is compared byte-for-byte
 against the existing version of the file to determine if the file needs to be
 overwritten.  This is done to avoid needless recompilation of source files.  If
 there are timestamps used in the template, then the two versions of the file
 will always be different and it will be regenerated every time, causing needless
 compilations.
 
 **Invocation Options**
 
 There is only one required parameter to the program; the EOModel must be
 specified.  In most situations custom templates will be used, and if so these
 need to be specified as well.  The parameters can be can be used in full, or as
 substrings where unique (e.g. -destination can be specified as -d or -dest). 
 The order of options is not important.
 
 Only one kind of of classes can be generated at once.  If more than one type is
 needed (e.g. regular and client-side classes) then *eogenerator* must be invoked
 multiple times.
 
 \-objc
 
 Specifies that Objective-C source code files are to be generated.  This is the
 default for WebObjects 4.5 and earlier.
 
 \-java
 
 Specifies that Java source code files are to be generated.  Java is the default
 for WebObjects 5.x projects; Objective-C is the default with WebObjects 4.5 and
 earlier.
 
 \-javaclient
 
 Specifies that Java client source code files are to be generated, which use
 slightly different templates by default and could potentially have a different
 class name.  Implies -java.
 
 \-model *modelpath*
 
 Loads the EOModel found at *modelpath*, and generates classes for all entities
 found inside (unless specific entities are given on the command line).
 
 \-refmodel *modelpath*
 
 Loads the EOModel found at *modelpath*, but does not generate classes for its
 entities (unless specific entities are given on the command line, in which case
 this is the same as -model).  This is useful if you only want to generate
 entities for one model, but need to load other models to resolve all of the
 relationships in the main model.
 
 \-force
 
 Force overwriting of read-only files.  By default, read-only files will not be
 overwritten, and a warning message printed instead.  This can be a useful
 reminder in some revision control environments to check out the necessary files
 first.
 
 \-destination *destinationdirectory*
 
 Used to specify a destination directory for generated source code files.  By
 default, files are generated in the current directory*.*
 
 \-subclassDestination *destinationdirectory*
 
 Used to specify a destination directory for the empty subclass source code
 files.  This allows the generated files and the actively edited source to be
 placed in different directories.  By default, the subclass files are
 generated/looked for in the -destination directory*.*
 
 \-packagedirs
 
 When doing Java generation, creates directories corresponding to the Java
 package name components underneath the -destination directory.  This will
 generate the classes into a typical Java directory structure.  [Note that the
 old ProjectBuilder, still sometimes used on Windows, does not support classes
 laid out in this manner.  Xcode should not have this problem.]
 
 \-prefix *string*
 
 Uses string as the prefix for the generated class names (to distinguish them
 from the real EO class names).  By default this is a single underscore ( "\_"
 )*.*
 
 \-templatedir *directory*
 
 Prepends *directory* to the search path used to find template files.  Multiple
 -templatedir flags can be specified; the directories will be searched in the
 order they appear on the command line.
 
 \-sourceTemplate *file*
 
 \-headerTemplate *file*
 
 \-subclassSourceTemplate *file*
 
 \-subclassHeaderTemplate *file*
 
 \-javaTemplate *file*
 
 \-subclassJavaTemplate *file*
 
 Used to specify alternate template files to use.  *file* can be an absolute
 path, a relative path, or a filename found in one of the search path
 directories.  If not specified, the default templates are used*.*
 
 \-filenameTemplate *string*
 
 This argument causes *string* to be used as a MiscMerge template, with the
 result being used as the base name for the generated files.  Normally, filenames
 based on the entity's class name are used, which is sufficient for most
 situations.  Occasionally it can be useful to have custom filename patterns
 (coupled with custom templates), and this parameter can allow for a lot of
 flexibility.  For example, if you want Java interfaces to be generated along
 with the classes, a template of "{javaClassName}Interface" will cause
 \`Interface' to be appended to each filename. The delimiters for this template
 are \`{' and \`}', and the base object is the EOEntity instance (just like the
 regular class templates).  Regular EOEntity methods can be used as keys, as can
 entries in the userInfo dictionary.  When generating Java classes, if the
 generated filename has what looks like a Java package, it will override the
 package normally specified in the EOModel.
 
 The boolean variables "isSubclass" and "isSuperclass" are defined for use in if
 statements as necessary.  For example, to generate the abstract superclasses
 into a separate "eogen" subpackage, something like the following can be used
 (coupled with changes to the templates of course):
 
 \-filenameTemplate '{classPackageName}{if
 isSuperclass}.eogen{endif}.{classNameWithoutPackage}'
 
 \-encoding *enc*
 
 Specifies the character encoding to be used for generated files.  The name can
 be specified as a value returned from the NSString
 +localizedNameOfStringEncoding: method, or (on MacOS X) an IANA name (typically
 what Java uses).  Defaults to the local platform string encoding.
 
 \-templateEncoding *enc*
 
 Specifies the character encoding to be used when reading template files.
 Defaults to the value specified for -encoding.
 
 \-define-*key value*
 
 This option adds the specified key-value pair to the list of variables available
 to the template, in addition to the EOEntity methods.  A key specified in this
 manner will **not** come before an EOEntity method of the same name when the
 template searches for the value.
 
 \-verbose
 
 Causes more verbose debugging output to be logged to standard output.
 
 \-version
 
 Displays the version number for *eogenerator*.
 
 \-help
 
 Displays the command line options available in *eogenerator*, with synopses of
 their purposes.
 
 By default, *eogenerator* generates all needed files for all entities in the
 EOModel, with the exception of entities defined to be EOGenericRecords and
 EOPrototypes entities.  If a smaller list of entities is desired, they can be
 specified on the command line:
 
 \$ eogenerator -model model.eomodeld Employee Organization Marketing
 
 Note that you are specifying the entity name.  Do not use the underscore name as
 the item to generate.  If one of these arguments contains the string ".eomodel",
 then -model is assumed.  If the name contains a \`\*' or \`?' character then the
 name is treated as a wildcard, matching any of the entity names in the models
 specified with -model (i.e., models specified with -refmodel are not searched). 
 The method underlying EOQualifier's "like" comparisons is used to do the
 matching.  Since the command shell will likely expand wildcards into filenames,
 the entity wildcard will probably have to be placed inside of double or single
 quotes (e.g.  "PW\*") to get passed to *eogenerator* correctly.
 
 As noted before, files are not overwritten if the generated contents matches the
 existing source code exactly.  This remains true even if entities are explicitly
 specified in the above manner.
 
  
 
 **Makefile Integration**
 
 The simplest way to integrate *eogenerator* into a project (unless you're using
 Xcode on MacOS X, see below) is typically to add rules to Makefile.postamble in
 the project where the .eomodeld lives, e.g.:
 
 EOGENERATOR = /path/to/eogenerator/binary
 
 EOGEN\_ARGS = -destination GeneratedEO.subproj \\
 
              -subclassDestination .           \\
 
              -java                            \\
 
              -javaTemplate MyJava.eotemplate  \\
 
              -subclassJavaTemplate MySubclassJava.eotemplate
 
 model1\_eos:
 
 \$(EOGENERATOR) \$(EOGEN\_ARGS) -model Model1.eomodeld -refmodel Model2.eomodeld
 
 model2\_eos:
 
 \$(EOGENERATOR) \$(EOGEN\_ARGS) -refmodel Model1.eomodeld -model Model2.eomodeld
 
 all\_eos:
 
 \$(EOGENERATOR) \$(EOGEN\_ARGS) -model Model1.eomodeld -model Model2.eomodeld
 
 Then add "model1\_eos", "model2\_eos", and "all\_eos" under the 'Build Targets'
 popup in ProjectBuilder's Build inspector for that project.  You will then be
 able to choose any of those targets from the Build panel.
 
 While we personally can't stand doing this, some people may want force EO
 regeneration every time the project is built.  To do this, further add a
 statement to Makefile.preamble:
 
 BEFORE\_PREBUILD += all\_eos  (or whichever rule name is desired)
 
 **Advanced Makefile Integration**
 
 If you don't mind getting complex, gnumake has several powerful features that
 can be very useful.  For instance, it's possible to search the paths named in
 the FRAMEWORK\_PATHS make variable (defined from settings in ProjectBuilder) to
 look for eomodels.  This makes use of a few of gnumake's string manipulation
 functions.
 
 \# Remove the "-F" in FRAMEWORK\_PATHS to get the list of paths
 
 MODEL\_PATHS := \$(subst -F,, \$(FRAMEWORK\_PATHS))
 
 \# Find the prototypes model in the specified path.  This is done by building
 
 \# a list of all possible paths (tack "Protos.eomodeld" after each path in
 
 \# MODEL\_PATHS), use the wildcard function to trim the list to the ones
 
 \# that actually exist, then take the firstword of the result in case there
 
 \# is more than one existing path.  This is a trick to do "search paths" using
 
 \# Makefile variables.  We actually try both directly in the framework
 directory,
 
 \# plus in the Resources of any .frameworks underneath it, in case the path
 
 \# is a framework project directory or is for installed frameworks.
 
 \#
 
 PROTO\_MODEL = \$(firstword \$(wildcard \$(foreach FPATH, \$(MODEL\_PATHS),
 \$(FPATH)/\*.framework/Resources/Protos.eomodeld \$(FPATH)/Protos.eomodeld)))
 
 \# Build both regular and client-side EOs
 
 build\_eos:
 
 \$(EOGENERATOR) -java -model MyModel.eomodeld -refmodel \$(PROTO\_MODEL)
 
 \$(EOGENERATOR) -javaclient -model MyModel.eomodeld -refmodel \$(PROTO\_MODEL)
 -destination ClientSideJava.subproj
 
 This trick can be wrapped inside an additional "foreach" to loop over a list of
 models:
 
 \# List of models to search for
 
 MODELS = Model1.eomodeld Model2.eomodeld Protos.eomodeld
 
 \# Use the search path trick to find list of models
 
 MODEL\_PATHS := \$(subst -F,, \$(FRAMEWORK\_PATHS))
 
 ALL\_MODELS = \$(foreach MODEL, \$(MODELS), \$(firstword \$(wildcard \$(foreach
 FPATH, \$(MODEL\_PATHS), \$(FPATH)/\*.framework/Resources/\$(MODEL)
 \$(FPATH)/\$(MODEL)))))
 
 \# Add "-refmodel" in front of each model
 
 REF\_MODELS = \$(foreach MODEL, \$(ALL\_MODELS), -refmodel \$(MODEL))
 
 \# Add the -refmodel flags to EOGEN\_ARGS
 
 EOGEN\_ARGS += \$(REF\_MODELS)
 
 \# Build the EOs for a Model3.eomodeld in the local directory
 
 build\_eos:
 
 \$(EOGENERATOR) \$(EOGEN\_ARGS) -model Model3.eomodeld
 
  
 
 **Xcode Integration**
 
 On MacOS X, WO 5 uses Xcode.app, which uses jam instead of gnumake as its
 underlying build tool.  The way jam is used precludes anything like
 Makefile.postamble, so you have to use the facilities settable in the UI.
 
 If you want the EO classes regenerated every build, then you can add a Shell
 Script Build Phase to your project to be run every build.  First create a shell
 script something like the following and put it in your project:
 
 \#!/bin/sh
 
 EOGENERATOR=/path/to/eogenerator/binary
 
 EOGEN\_ARGS=-destination GeneratedEO.subproj -subclassDestination . -java
 -javaTemplate MyJava.eotemplate -subclassJavaTemplate MySubclassJava.eotemplate
 
 \$EOGENERATOR \$EOGEN\_ARGS -model Model1.eomodeld -model Model2.eomodeld
 
 Then add the phase to the project:
 
 1) Choose the Targets tab in the left side of the window
 
 2) Select the main target and make sure it's active (has the check mark)
 
 3) Select Project-\>Edit Active Target from the menu
 
 4) Choose the Files and Build Phases tab
 
 5) Select the first phase listed, so there's a gray rectangle around the phase's
 box
 
 6) Select Project-\>New Build Phase-\>New Shell Script Build Phase from the menu
 
 7) Put in the shell to use (/bin/sh for the example above)
 
 8) Put in the script to execute -  \$SRCROOT/generateEO.sh for example. 
 (\$SRCROOT is defined by Xcode to be the project directory.)  NOTE: The contents
 of the shell script itself can be placed in here directly, instead of using an
 external shell script file.
 
 The EO files should now be regenerated every build.  Any new files that are
 created still have to be manually added to the project.   All of the project's
 build settings are available as environment variables, so your script can use
 those values if necessary.  These settings are basically the equivalent of the
 Makefile variables available under the old ProjectBuilder.
 
 If you don't want eogenerator to be run every time a build is done, then things
 get more interesting.  Xcode also allows you to have different Build Styles,
 which is essentially having alternate sets of build settings.  You could
 additionally add a new Build Style called "EOs", and add a GENERATE\_EOS setting
 with a value of YES.  Then, in the shell script used in the new build phase,
 check for that variable before running eogenerator:
 
 if [ "\$GENERATE\_EOS" = "YES" ] ; then
 
     \$EOGENERATOR ...
 
 fi
 
 The script will still be run every time, but eogenerator won't.  From the
 command line, "pbxbuild -buildstyle EOs" will run with that build style (or you
 could just execute the script directly of course if project variables aren't
 used).
 
 It is also possible to add an entirely new target, however the only one that
 doesn't expect to actually build something is "Legacy Makefile", where you
 specify the build tool to run.  It may be possible to have the generateEO.sh
 script run as the build tool, but it seems as if an absolute path is required --
 plus, you lose all the build setting in the environment for the other targets. 
 You could actually use gnumake as the build tool here, create a Makefile, and
 put the eogenerator instructions there as in the old Project Builder.
 
 If anyone has any further ideas for ways to use eogenerator within the Xcode,
 please let us know.
 
  
 
 **Ant Integration**
 
 Using apache ant, eogenerator can be invoked using the standard "exec" task,
 something like the following:
 
aee44525
  
 
  
 
7932fe51
     \<target name="generate.eos"\>
 
         \<exec dir="\${basedir}" executable="/path/to/eogenerator"
 
               outputproperty="eogen.log" logError="true"\>
 
             \<arg value="-model" /\>
 
             \<arg file="\${basedir}/resource/MyModel.eomodeld" /\>
 
             \<arg value="-refmodel" /\>
 
             \<arg file="\${basedir}/resource/MyPrototypes.eomodeld" /\>
 
             \<arg value="-templatedir" /\>
 
             \<arg file="\${basedir}/buildresource/EOGenTemplates" /\>
 
             \<arg value="-javaTemplate" /\>
 
             \<arg value="MyJavaTemplate.eotemplate" /\>
 
             \<arg value="-subclassJavaTemplate" /\>
 
             \<arg value="MyJavaSubclassTemplate.eotemplate" /\>
 
             \<arg value="-destination" /\>
 
             \<arg file="\${basedir}/src" /\>
 
             \<arg value="-packagedirs" /\>
 
             \<arg value="-java" /\>
 
             \<arg value="-define-copyrightYear" /\>
 
             \<arg value="2005" /\>
 
         \</exec\>
 
         \<echo message="EOGenerator"/\>
 
         \<echo message="\${eogen.log}"/\>
 
     \</target\>
 
aee44525
 \`\`\`
 
  
 
7932fe51
 Obviously, much use can be made of Ant's variable substitution, letting values
 like the models or templates be defined in external .properties files, etc.
 
  
 
 **Eclipse Integration**
 
 If you are using Eclipse for your project, you can set up EOGenerator as a
 "Builder" for your project.  These instructions are for Eclipse 3.0.1; the
 details may be slightly different in other Eclipse versions.
 
 1. Select the Project-\>Properties menu item.
 
 2. Select the "Builders" section and click the "New..." button.
 
 3. Choose "Program" as the type of external tool to create, not "Ant Build".
 
 4. In Location, put the path to the eogenerator executable.
 
 5. Put in the working directory you want; this makes it easier to use relative
 paths with any arguments. \${project\_loc} is a good value (this is a variable
 defined by Eclipse).
 
 6. Add any arguments, for example: -model resource/MyModel.eomodeld -refmodel
 resource/MyPrototypes.eomodeld -templatedir
 \${project\_loc}/buildresource/EOGenTemplates -javaTemplate
 MyJavaTemplate.eotemplate -subclassJavaTemplate
 MyJavaSubclassTemplate.eotemplate -destination \${project\_loc}/src -packagedirs
 -java -define-copyrightYear 2005
 
 7. Choose "Program" as the type of external tool to create, not "Ant Build".
 
 8. Under the "Refresh" tab, you may want to specify the folders to get refreshed
 after EOGenerator runs, so that Eclipse becomes aware of any new source files.
 
 9. Under the "Build Options" tab, you may wish to change when EOGenerator gets
 invoked.
 
 10. Click the OK button.  Back in the list of Builders, you can move EOGenerator
 above the regular Java Builder so it gets invoked before the regular Java
 compiler.
 
 Eclipse defines several other variables that can be used; click the
 "Variables..." button when defining the Location, Working Directory, or
 Arguments.  You can also define your own.
 
 Obviously, as an alternative you can just use Eclipse's Ant integration to
 invoke an ant target defined in build.xml (see Ant Integration above), which
 will also allow for building from the command line.
 
  
 
 **Feedback**
 
 We are very interested in any comments, suggestions, bug reports, or any other
 feedback on *eogenerator*; please send them to \<eogenerator\@rubicode.com\>.
 
 Mike Gentry, Carl Lindberg, and Doug McClure
 
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS \`\`AS IS'' AND ANY EXPRESS
 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO
 EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 (Or, the short version:  If it breaks, you get to keep the pieces. :-) )
 
  
 
 **History**
 
 1.7 Built as a universal binary for use on Intel Macs.
 
 Fixed Apple's buggy handling of Boolean attributes (Number attributes with a
 valueType of "c").  These should now be generated correctly as Boolean instead
 of Number.  Reported by Miguel Arroz.
 
 Added -encoding and -templateEncoding parameters to control character encoding
 of generated files and templates.  Suggested by Francis Labrie.
 
 Added enhancements to -filenameTemplate (isSubclass/isSuperclass variables) for
 more flexible filename generation.  Suggested by Stéphane Corthésy.
 
 Added -lastLetter NSString method for use in templates.  Suggested by Greg
 Hulands.
 
 Added barebones EOF headers to allow compilation with WebObjects 5.3. 
 Contributed by Mike Schrag.
 
 Fixed a bug that skipped JavaClient class generation if the server-side class
 was EOGenericRecord.  Reported by David Avendasora.
 
 Fixed WebObjects 5.2+ JavaClient generation when using entity inheritance. 
 Reported by David Avendasora.
 
 Added a log message in verbose mode when skipping EOGenericRecord entities.
 
 Avoided strange but harmless "EOControlJava RemoveMethodList..." log message
 which sometimes appeared.
 
 Updated with new MiscMerge; adds encoding support and fixes a few bugs.
 
 1.6 Fix problems with the 5.2.4 WebObjects release on MacOS X.  (The
 implementation for key-value coding is now in Foundation.framework, not
 EOControl.framework, and has a couple of implementation differences which caused
 us problems.)
 
 Added -filenameTemplate option for more flexible filename generation.  Suggested
 by Jason Jobe.
 
 Added usage message for -define-key option. 
 
 Added javaValueTypeClassName and javaScalarValueTypeClassName methods to help
 generate typed method signatures for attributes.
 
 Added initialLowercaseString string method.
 
 Reset the NEXT\_ROOT environment variable to blank so that it does not cause
 problems with EOAdapter frameworks loaded dynamically. Reported by Pierre
 Frisch.
 
 Fixed possible exceptions with the deleteAllXXXRelationships method defined in
 EOGJavaSource.eotemplate.  We were removing objects from an array during
 enumeration.
 
 Updated with new MiscMerge:
 
 Added setlocal, setmerge (was identify), setengine, and setglobal (was set)
 MiscMerge commands to set variables in different scopes.
 
 Added a debug command to print out information to stderr.
 
 Added ability to create arrays for use in places like foreach loops.
 
 Added in and notin operators for conditional expressions to check if something
 is in an array.
 
 1.5 On WebObjects 5.x systems, output now defaults to Java.
 
 Added support for WebObjects 5.2 (slightly changed templates).
 
 Added generation of methods to call named fetch specifications to the example
 templates.
 
 Added generation of relationship methods to call
 addObjectToBothSidesOfRelationshipWithKey to the example templates.  Suggested
 by Jonathan Rentzsch.
 
 Added MyGenericRecord.java as an example of a custom EO superclass.
 
 Fixed import statements in Java WO 5.x templates to conform to Apple's
 versions.  Reported by Eike Dierks.
 
 Updated to a new MiscMerge version; new features include break/continue and
 mathematical expressions.
 
 The generated classes are now declared as being abstract in Java.  Suggested by
 Joseph Leo Moreno.
 
 Avoid spurious "EOSchemaSynchronization" message being printed to console.
 
 1.4 Log explicit error message for failed model lookups.
 
 Added ability to specify the prefix used for the generated classes.  Submitted
 by Dominik Westner.
 
 Added -packagedirs option to generate classes under directories based on the
 Java package name.  Suggested by Emily Catherine Bach.
 
 Added EOGJavaSource example template.
 
 Added support for the all-Java WebObjects 5
 
 Added support for MacOS X 10.x
 
 Added Project Builder (MacOS X) integration instructions.  Submitted by David
 Teran.
 
 1.3 Added implementations of methods used in templates that are not in the
 standard frameworks -- EOModeler gets them from
 EOJavaClientExtensions.EOMBundle.  This caused accessor methods to never be
 defined in JavaClient generated classes.  Reported by Todd Thomas.
 
 Linked against EOJavaClient.framework so JavaClient generation will work with
 WOF 4.0.
 
 When generating JavaClient classes, make sure to use the clientClassName for the
 file name.  Reported by Todd Thomas.
 
 Will not overwrite read-only files, unless -force flag is given.
 
 Allow wildcards when specifying entity names.  Suggested by Rajnish Dogra.
 
 1.2 Added support for generating JavaClient classes.
 
 Fixed cosmetic whitespace errors in some of the Java templates.
 
 Made sure to ignore EOPrototypes entities, which aren't real entities.  Reported
 by William Swats.
 
 1.1 Added a JavaSubclassSourceEOF3.eotemplate, which is needed for Java projects
 using WOF 4.0, and fixed a crasher when the specified templates could not be
 found.  Reported by Richard Lewis-Shell.
 
 1.01 Fixed a typo in JavaSource.eotemplate, and class name errors in
 JavaSubclassSource.eotemplate.  Reported by Jim Roepcke.
 
 1.0 Initial release.