Changes for page EOF-Using EOF-EOGenerator
Last modified by Pascal Robert on 2012/01/21 22:03
From version 28.1
edited by Quinton Dolan
on 2007/07/16 22:26
on 2007/07/16 22:26
Change comment:
There is no comment for this version
To version 31.1
edited by Pascal Robert
on 2012/01/21 22:03
on 2012/01/21 22:03
Change comment:
Migrated to Confluence 4.0
Summary
-
Page properties (3 modified, 0 added, 0 removed)
Details
- Page properties
-
- Title
-
... ... @@ -1,1 +1,1 @@ 1 - Programming__WebObjects-EOF-Using EOF-EOGenerator1 +EOF-Using EOF-EOGenerator - Author
-
... ... @@ -1,1 +1,1 @@ 1 -XWiki. qdolan1 +XWiki.probert - Content
-
... ... @@ -1,59 +1,67 @@ 1 -|=Contents 2 -| 1 +{{warning}} 2 +This is deprecated information! 3 +{{/warning}} 3 3 4 -{{toc style="disc" minLevel="2"}}{{/toc}} 5 +|=((( 6 +Contents 7 +))) 8 +|((( 9 +{{toc style="disc" minLevel="2"/}} 10 +))) 5 5 6 -== Overview 12 +== Overview == 7 7 8 -If you've ever used EOModeler's Java source code generator, you know how much of a pain it can be when you make changes to your model objects and have to merge changes in later. //Person.java, which contains all of the autogenerated methods.//Person.//Xxx.java files are updated, and your customizations are left untouched.//Xxx.java files.14 +If you've ever used EOModeler's Java source code generator, you know how much of a pain it can be when you make changes to your model objects and have to merge changes in later. One solution for this is to use [[EOGenerator>>url:http://www.rubicode.com/Software/EOGenerator/||shape="rect"]], an application developed by Rubicode Software, which uses the Generation Gap pattern to create your Java files from your EOModels. EOGenerator produces TWO java files for each Entity rather than one. Take the example of a Person entity. The first java file is _Person.java, which contains all of the autogenerated methods. The second java file is Person.java, and Person extends _Person. The second file is where you place all of your customizations. Any time your model changes, only your _Xxx.java files are updated, and your customizations are left untouched. Additionally, EOGenerator allows for the creation of extensive custom templates for your files, which provides the ability to place convenience methods in your _Xxx.java files. 9 9 10 -== Advantages == 16 +{{warning}} 17 +EOGenerator doesn't work on Mac OS X 10.5. You have to use [[JavaEOGenerator>>url:http://developer.apple.com/samplecode/JavaEOGenerator/||shape="rect"]] or [[Velocity EOGenerator>>doc:WOL.Velocity EOGenerator (Veogen)]]. 18 +{{/warning}} 11 11 20 +== Advantages == 21 + 12 12 There are several advantages to using EOGenerator over EOModeler's default Java file generation and merging with FileMerge. 13 13 14 -* EOGenerator uses the Generation Gap pattern, which provides a much cleaner separation of autogenerated vs customized code with no need to deal with merging at all. 15 -* EOGenerator uses the MiscMerge language for its templates. 24 +* EOGenerator uses the Generation Gap pattern, which provides a much cleaner separation of autogenerated vs customized code with no need to deal with merging at all. There are border cases with FileMerge that can cause you to deal with annoying conflicts. 25 +* EOGenerator uses the MiscMerge language for its templates. This allows you to extend the core templates with extensive customizations (see the EOGenerator Mods section below), better supporting your own custom development process and workflow. 16 16 * As David LaBer put it, "all the cool kids use it - and we all know looking cool is the **most** important criteria". 17 17 18 -== How To Use It 28 +== How To Use It == 19 19 20 -Kieran Kelleher has writtten an [[Introduction to EOGenerator>>http://homepage.mac.com/kelleherk/iblog/C1837526061/E1908382110/index.html]] on his blog. 30 +Kieran Kelleher has writtten an [[Introduction to EOGenerator>>url:http://homepage.mac.com/kelleherk/iblog/C1837526061/E1908382110/index.html||shape="rect"]] on his blog. 21 21 22 -It's actually very simple to use. 32 +It's actually very simple to use. The quick start is: 23 23 24 24 * Download and untar EOGenerator from the Rubicode site 25 25 * Run the following command: 26 26 27 27 {{panel}} 28 - 29 -eogenerator -model /path/to/model/YourModel.eomodeld -destination /path/to/source/folder 30 - -subclassDestination /path/to/source/folder -templatedir /path/to/EOGenerator/templates -java -packagedirs 31 - 38 +eogenerator -model /path/to/model/YourModel.eomodeld -destination /path/to/source/folder 39 + -subclassDestination /path/to/source/folder -templatedir /path/to/EOGenerator/templates -java -packagedirs 32 32 {{/panel}} 33 33 34 -Voila. 42 +Voila. EOGenerator will spit out your Java files for you. Let's break down the commands you can pass in: 35 35 36 -* - -define--EOGenericRecord <class>, allows you to specify the//Person class's superclass.-define--EOGenericRecord er.extensions.ERXGenericRecord//37 -* - -destination <path>, the folder that//Person.java//--//style java files will be produced in (the non-editable files)//38 -* - -java, produce java files--39 -* - -javaTemplate <filename>, the name of the Java template to use inside of the template dir (//Person)//--40 -* - -model <path>, Passes in the path of a .eomodeld you would like to generate Java files for.-model commands on the commandline41 -* - -packagedirs, produce package directory for any package statements defined in your Java files (not necessary if you don't specify package names on your entities.:))--42 -* - -refmodel <path>, Passes in the path of an .eomodeld that is required for generating Java files, but that won't actually have Java files generated for it. For instance, you should --refmodel any prototypes, or any models in other frameworks that you depend on43 -* - -subclassDestination <path>, the folder that Person.java--style java files will be produced in (the editable files)44 -* - -subclassJavaTemplate <filename>, the name of the Java subclass template to use inside of the template dir (Person)--45 -* - -templatedir <path>, the path to the folder that contains EOGenerator templates--46 -* - -verbose, turn on verbose output--44 +* -define-EOGenericRecord <class>, allows you to specify the _Person class's superclass. For instance, if you use Project Wonder, you would specify -define-EOGenericRecord er.extensions.ERXGenericRecord 45 +* -destination <path>, the folder that _Person.java-style java files will be produced in (the non-editable files) 46 +* -java, produce java files 47 +* -javaTemplate <filename>, the name of the Java template to use inside of the template dir (_Person) 48 +* -model <path>, Passes in the path of a .eomodeld you would like to generate Java files for. You can actually include multiple -model commands on the commandline 49 +* -packagedirs, produce package directory for any package statements defined in your Java files (not necessary if you don't specify package names on your entities. By the way, you should specify packages on your entities ) 50 +* -refmodel <path>, Passes in the path of an .eomodeld that is required for generating Java files, but that won't actually have Java files generated for it. For instance, you should -refmodel any prototypes, or any models in other frameworks that you depend on 51 +* -subclassDestination <path>, the folder that Person.java-style java files will be produced in (the editable files) 52 +* -subclassJavaTemplate <filename>, the name of the Java subclass template to use inside of the template dir (Person) 53 +* -templatedir <path>, the path to the folder that contains EOGenerator templates 54 +* -verbose, turn on verbose output 47 47 48 -== Custom EOGenerator Mods 56 +== Custom EOGenerator Mods == 49 49 50 -=== Zak Burke 58 +=== Zak Burke === 51 51 52 -Allow setting nulls on a to-one relationship (and turn it into a remove). 60 +Allow setting nulls on a to-one relationship (and turn it into a remove). Note, this is also included in Jonathan Rentzsch's templates. 53 53 54 54 {{code}} 55 55 56 - 64 +public void save<$ToOneRelationship.name.initialCapitalString$>(<$ToOneRelationship.destinationEntity.referenceJavaClassName$> value) 57 57 { 58 58 if (value == null) 59 59 { ... ... @@ -69,13 +69,13 @@ 69 69 70 70 {{/code}} 71 71 72 -=== Chuck Hill 80 +=== Chuck Hill === 73 73 74 74 Return the list of changes between the current EO and the last committed version of the EO: 75 75 76 76 {{code}} 77 77 78 - 86 +public NSDictionary changedProperties() { 79 79 NSDictionary commitedValues = editingContext().committedSnapshotForObject(this); 80 80 return changesFromSnapshot(commitedValues); 81 81 } ... ... @@ -82,20 +82,20 @@ 82 82 83 83 {{/code}} 84 84 85 -=== Jonathan Rentzsch 93 +=== Jonathan Rentzsch === 86 86 87 87 Jonathan Rentzsch has provided his base EOGenerator templates, which are a must-have: 88 88 89 -http:~/~/rentzsch.com/share/eogenerator52templates.zip 97 +[[http:~~/~~/rentzsch.com/share/eogenerator52templates.zip>>url:http://rentzsch.com/share/eogenerator52templates.zip||shape="rect"]] 90 90 91 -=== Markus Ruggiero 99 +=== Markus Ruggiero === 92 92 93 93 Constants for all attributes and relationships. This allows compile time error checking in situations like 94 -addObjecttoBothSidesOfRelationshipWithKey(myObject, Person.TO //MANY//Children)102 + addObjecttoBothSidesOfRelationshipWithKey(myObject, Person.TO_MANY_Children) 95 95 96 96 {{code}} 97 97 98 - 106 +<$foreach attribute classAttributes.@reversedArray do$> 99 99 public static final String ATTRIBUTE_<$attribute.name$> = "<$attribute.name$>";<$endforeach do$> 100 100 101 101 <$foreach ToOneRelationship classToOneRelationships.@reversedArray do$> ... ... @@ -110,15 +110,15 @@ 110 110 111 111 {{code}} 112 112 113 - 121 +<$if attribute.userInfo.usage h1. booleanFlag $> // boolean accessors 114 114 public void <$attribute.userInfo.setterName$>(boolean newBoolean) { 115 115 set<$attribute.name.initialCapitalString$>(newBoolean ? "true" : "false"); 116 116 } 117 - 125 + 118 118 public boolean <$attribute.userInfo.getterName$>() { 119 119 return "true".equals(<$attribute.name$>()) ? true : false; 120 120 } 121 - 129 + 122 122 // validation 123 123 public String validate<$attribute.name.initialCapitalString$>(String newValue) { 124 124 if ( newValue null ) { ... ... @@ -133,19 +133,19 @@ 133 133 134 134 {{/code}} 135 135 136 -=== Mike Schrag 144 +=== Mike Schrag === 137 137 138 -Add a constant that represents the name of the entity so that you can refer to Person.ENTITY //NAME in fetches rather than the String (allows refactoring support in Eclipse)~://146 +Add a constant that represents the name of the entity so that you can refer to Person.ENTITY_NAME in fetches rather than the String (allows refactoring support in Eclipse): 139 139 140 140 {{code}} 141 141 142 - 150 +public static final String ENTITY_NAME = "<$name$>"; 143 143 144 144 {{/code}} 145 145 146 146 Add a static factory method to your EO's ( Person createPerson(...) ) that shows you what required attributes and relationships are configured for you entity (attempts to provide a replacement "constructor" since EO constructors are empty): 147 147 148 -{{code bar="true"}}156 +{{code}} 149 149 150 150 public static <$classNameWithoutPackage$> create<$classNameWithoutPackage$>(EOEditingContext _editingContext<$foreach Attribute classAttributes.@sortedNameArray do$><$if !Attribute.allowsNull$>, <$Attribute.javaValueClassName$> _<$Attribute.name$><$endif$><$endforeach do$><$foreach ToOneRelationship classToOneRelationships.@sortedNameArray do$><$if ToOneRelationship.isMandatory$>, <$ToOneRelationship.destinationEntity.referenceJavaClassName$> _<$ToOneRelationship.name$><$endif$><$endforeach do$>) { 151 151 <$classNameWithoutPackage$> eoObject = (<$classNameWithoutPackage$>)EOUtilities.createAndInsertInstance(_editingContext, <$GEN_PREFIX$><$classNameWithoutPackage$>.ENTITY_NAME);<$foreach Attribute classAttributes.@sortedNameArray do$><$if !Attribute.allowsNull$> ... ... @@ -156,9 +156,9 @@ 156 156 157 157 {{/code}} 158 158 159 -Here's a little bitty fancier (read: nastier) version that also handles superclass mandatory attributes and fields (one level). 167 +Here's a little bitty fancier (read: nastier) version that also handles superclass mandatory attributes and fields (one level). It skips any attribute that is referenced in the restricting qualifier of your subclass (since you are probably going to set that in your awakeFromInsertion): 160 160 161 -{{code bar="true"}}169 +{{code}} 162 162 163 163 public static <$classNameWithoutPackage$> create<$classNameWithoutPackage$>(EOEditingContext editingContext<$foreach Attribute classAttributes.@sortedNameArray do$><$if !Attribute.allowsNull$>, <$Attribute.javaValueClassName$> <$Attribute.name$><$endif$><$endforeach do$><$foreach Attribute parentEntity.classAttributes.@sortedNameArray do$><$if !Attribute.allowsNull$><$set RestrictingQualifierKey = false$><$foreach QualifierKey restrictingQualifier.allQualifierKeys do$><$if Attribute.name = QualifierKey$><$set RestrictingQualifierKey = true$><$endif$><$endforeach do$><$if RestrictingQualifierKey = false$>, <$Attribute.javaValueClassName$> <$Attribute.name$><$endif$><$endif$><$endforeach do$><$foreach ToOneRelationship classToOneRelationships.@sortedNameArray do$><$if ToOneRelationship.isMandatory$>, <$ToOneRelationship.destinationEntity.referenceJavaClassName$> <$ToOneRelationship.name$><$endif$><$endforeach do$><$foreach ToOneRelationship parentEntity.classToOneRelationships.@sortedNameArray do$><$if ToOneRelationship.isMandatory$>, <$ToOneRelationship.destinationEntity.referenceJavaClassName$> <$ToOneRelationship.name$><$endif$><$endforeach do$>) { 164 164 <$classNameWithoutPackage$> eoObject = (<$classNameWithoutPackage$>)EOUtilities.createAndInsertInstance(editingContext, <$GEN_PREFIX$><$classNameWithoutPackage$>.ENTITY_NAME);<$foreach Attribute classAttributes.@sortedNameArray do$><$if !Attribute.allowsNull$> ... ... @@ -171,30 +171,37 @@ 171 171 172 172 {{/code}} 173 173 174 -Add a bunch of convience fetch methods (fetchAllPersons, fetchRequiredPerson, and other variants). 182 +Add a bunch of convience fetch methods (fetchAllPersons, fetchRequiredPerson, and other variants). It's not smart about pluralization, so it's just going to put an "s" on the end of the entity name: 175 175 176 176 {{code}} 177 - 178 - public static NSArray fetchAll<$classNameWithoutPackage$>s(EOEditingContext _editingContext) { 185 +public static NSArray fetchAll<$classNameWithoutPackage$>s(EOEditingContext _editingContext) { 179 179 return <$GEN_PREFIX$><$classNameWithoutPackage$>.fetchAll<$classNameWithoutPackage$>s(_editingContext, null); 180 180 } 188 +{{/code}} 181 181 182 - public static NSArray fetchAll<$classNameWithoutPackage$>s(EOEditingContext _editingContext, NSArray _sortOrderings) { 190 +{{code}} 191 +public static NSArray fetchAll<$classNameWithoutPackage$>s(EOEditingContext _editingContext, NSArray _sortOrderings) { 183 183 return <$GEN_PREFIX$><$classNameWithoutPackage$>.fetch<$classNameWithoutPackage$>s(_editingContext, null, _sortOrderings); 184 184 } 194 +{{/code}} 185 185 186 - public static NSArray fetch<$classNameWithoutPackage$>s(EOEditingContext _editingContext, EOQualifier _qualifier, NSArray _sortOrderings) { 196 +{{code}} 197 +public static NSArray fetch<$classNameWithoutPackage$>s(EOEditingContext _editingContext, EOQualifier _qualifier, NSArray _sortOrderings) { 187 187 EOFetchSpecification fetchSpec = new EOFetchSpecification(<$GEN_PREFIX$><$classNameWithoutPackage$>.ENTITY_NAME, _qualifier, _sortOrderings); 188 188 fetchSpec.setIsDeep(true); 189 189 NSArray eoObjects = _editingContext.objectsWithFetchSpecification(fetchSpec); 190 190 return eoObjects; 191 191 } 203 +{{/code}} 192 192 193 - public static <$classNameWithoutPackage$> fetch<$classNameWithoutPackage$>(EOEditingContext _editingContext, String _keyName, Object _value) { 205 +{{code}} 206 +public static <$classNameWithoutPackage$> fetch<$classNameWithoutPackage$>(EOEditingContext _editingContext, String _keyName, Object _value) { 194 194 return <$GEN_PREFIX$><$classNameWithoutPackage$>.fetch<$classNameWithoutPackage$>(_editingContext, new EOKeyValueQualifier(_keyName, EOQualifier.QualifierOperatorEqual, _value)); 195 195 } 209 +{{/code}} 196 196 197 - public static <$classNameWithoutPackage$> fetch<$classNameWithoutPackage$>(EOEditingContext _editingContext, EOQualifier _qualifier) { 211 +{{code}} 212 +public static <$classNameWithoutPackage$> fetch<$classNameWithoutPackage$>(EOEditingContext _editingContext, EOQualifier _qualifier) { 198 198 NSArray eoObjects = <$GEN_PREFIX$><$classNameWithoutPackage$>.fetch<$classNameWithoutPackage$>s(_editingContext, _qualifier, null); 199 199 <$classNameWithoutPackage$> eoObject; 200 200 int count = eoObjects.count(); ... ... @@ -209,14 +209,19 @@ 209 209 } 210 210 return eoObject; 211 211 } 212 - 213 - public static <$classNameWithoutPackage$> fetchRequired<$classNameWithoutPackage$>(EOEditingContext _editingContext, String _keyName, Object _value) { 227 +{{/code}} 228 + 229 +{{code}} 230 +public static <$classNameWithoutPackage$> fetchRequired<$classNameWithoutPackage$>(EOEditingContext _editingContext, String _keyName, Object _value) { 214 214 return <$GEN_PREFIX$><$classNameWithoutPackage$>.fetchRequired<$classNameWithoutPackage$>(_editingContext, new EOKeyValueQualifier(_keyName, EOQualifier.QualifierOperatorEqual, _value)); 215 215 } 233 +{{/code}} 216 216 217 - public static <$classNameWithoutPackage$> fetchRequired<$classNameWithoutPackage$>(EOEditingContext _editingContext, EOQualifier _qualifier) { 235 +{{code}} 236 + 237 +public static <$classNameWithoutPackage$> fetchRequired<$classNameWithoutPackage$>(EOEditingContext _editingContext, EOQualifier _qualifier) { 218 218 <$classNameWithoutPackage$> eoObject = <$GEN_PREFIX$><$classNameWithoutPackage$>.fetch<$classNameWithoutPackage$>(_editingContext, _qualifier); 219 - if (eoObject h1.null) {239 + if (eoObject == null) { 220 220 throw new NoSuchElementException("There was no <$classNameWithoutPackage$> that matched the qualifier '" + _qualifier + "'."); 221 221 } 222 222 return eoObject; ... ... @@ -224,16 +224,18 @@ 224 224 225 225 {{/code}} 226 226 227 -Add methods for getting local instances of EO's. 247 +Add methods for getting local instances of EO's. The static one is handy if you have a reference to an EO that might be null (it does a null check first): 228 228 229 229 {{code}} 230 - 231 - public <$classNameWithoutPackage$> localInstanceOf<$classNameWithoutPackage$>(EOEditingContext _editingContext) { 250 +public <$classNameWithoutPackage$> localInstanceOf<$classNameWithoutPackage$>(EOEditingContext _editingContext) { 232 232 return (<$classNameWithoutPackage$>)EOUtilities.localInstanceOfObject(_editingContext, this); 233 233 } 253 +{{/code}} 234 234 235 - public static <$classNameWithoutPackage$> localInstanceOf<$classNameWithoutPackage$>(EOEditingContext _editingContext, <$classNameWithoutPackage$> _eo) { 236 - return (_eo null) ? null : (<$classNameWithoutPackage$>)EOUtilities.localInstanceOfObject(_editingContext, _eo); 255 +{{code}} 256 + 257 +public static <$classNameWithoutPackage$> localInstanceOf<$classNameWithoutPackage$>(EOEditingContext _editingContext, <$classNameWithoutPackage$> _eo) { 258 + return (_eo == null) ? null : (<$classNameWithoutPackage$>)EOUtilities.localInstanceOfObject(_editingContext, _eo); 237 237 } 238 238 239 239 {{/code}} ... ... @@ -242,7 +242,7 @@ 242 242 243 243 {{code}} 244 244 245 - 267 +<$if !ToManyRelationship.inverseRelationship$> 246 246 public NSArray <$ToManyRelationship.name$>(EOQualifier qualifier) { 247 247 return <$ToManyRelationship.name$>(qualifier, null); 248 248 } ... ... @@ -251,12 +251,12 @@ 251 251 public NSArray <$ToManyRelationship.name$>(EOQualifier qualifier) { 252 252 return <$ToManyRelationship.name$>(qualifier, null, false); 253 253 } 254 - 255 - public NSArray <$ToManyRelationship.name$>(EOQualifier qualifier, boolean fetch) { 276 + 277 + public NSArray <$ToManyRelationship.name$>(EOQualifier qualifier, boolean fetch) { 256 256 return <$ToManyRelationship.name$>(qualifier, null, fetch); 257 257 } 258 258 <$endif$> 259 - 281 + 260 260 public NSArray <$ToManyRelationship.name$>(EOQualifier qualifier, NSArray sortOrderings<$if ToManyRelationship.inverseRelationship$>, boolean fetch<$endif$>) { 261 261 NSArray results; 262 262 <$if ToManyRelationship.inverseRelationship$> ... ... @@ -292,25 +292,25 @@ 292 292 293 293 {{/code}} 294 294 295 -=== John Huss 317 +=== John Huss === 296 296 297 -I wanted to share a wonderful bit of knowledge I learned today. //EO base classes and eliminate annoying compiler messages (usually uneeded import statements).//319 +I wanted to share a wonderful bit of knowledge I learned today. If you're using Java 1.5 you can add @SuppressWarnings("all") to the template for your _EO base classes and eliminate annoying compiler messages (usually uneeded import statements). 298 298 299 299 {{code}} 300 300 301 - 323 +@SuppressWarnings("all") 302 302 public class _Invoice extends ERXGenericRecord { 303 303 } 304 304 305 305 {{/code}} 306 306 307 -=== Guido Neitzer 329 +=== Guido Neitzer === 308 308 309 309 Create awakeFromInsertion() and awakeFromFetch() in your EOGenerator template as a method stub that only calls super() and has a comment for "initialize your object here ...". You only have to put in the code at that place and can't possibly forget to call super(). Here is an example: 310 310 311 311 {{code}} 312 312 313 -/** 335 +/** 314 314 * Initialization of the instance while inserting it into an editing context 315 315 */ 316 316 public void awakeFromInsertion (EOEditingContext editingContext) { ... ... @@ -321,5 +321,3 @@ 321 321 {{/code}} 322 322 323 323 This is from my JavaSubclassSourceTemplate.eotemplate 324 - 325 -Category:WebObjects