name mode size
project.pbxproj 100644 40 kb
**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: \ public class \_Employee extends EOGenericRecord (or EOCustomObject)  (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 , 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 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, 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/ 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 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:         \<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\> \`\`\`   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\\>. 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 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.