Browse code

eogenerator ported to MulleEOF

Nat! authored on 14-08-2015 16:26:08
Showing 147 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,115 @@
1
+/* EOAccessAdditions.h created by lindberg on Mon 20-Dec-1999 */
2
+
3
+#import <EOAccess/EOModel.h>
4
+#import <EOAccess/EOEntity.h>
5
+#import <EOAccess/EOAttribute.h>
6
+#import <EOAccess/EORelationship.h>
7
+#import <EOControl/EOFetchSpecification.h>
8
+#import "SystemType.h"
9
+
10
+/* EOAccess extension methods for use by templates */
11
+
12
+@interface EOModel (EOAccessAdditions)
13
+
14
+// Tries to find the framework name. First looks to see if a value for
15
+// "EOGeneratorFrameworkName" exists in the model's -userInfo dictionary, and if
16
+// not, looks at the model's -path to find the framework the .eomodeld is in.
17
+// Both PB.project files and path components ending in ".framework" are looked
18
+// for, so it should work for .eomodels insided installed frameworks or in a
19
+// development tree. If the framework name could not be found, returns nil.
20
+- (NSString *)frameworkName;
21
+
22
+// Uses isLike: to do the comparisons
23
+- (NSArray *)entityNamesMatchingWildcard:(NSString *)wildcard;
24
+
25
+@end
26
+
27
+@interface EOEntity (EOAccessAdditions)
28
+
29
+- (BOOL)hasParentEntity;
30
+- (NSString *)frameworkName;
31
+
32
+- (NSString *)objcImportString;
33
+- (NSString *)objcImportStringInRelationToEntity:(EOEntity *)sourceEntity;
34
+- (NSString *)parentObjCImportString;
35
+
36
+//uniqued array of relationships' -objcImportString
37
+- (NSArray *)referencedObjCImportStrings;
38
+- (NSArray *)arrayWithParentObjCImportStringIfNeeded;
39
+
40
+#ifdef EOF2_ONLY
41
+// Define for use by EOF2 systems
42
+- (NSString *)classNameWithoutPackage;
43
+- (NSArray *)fetchSpecificationNames;
44
+- (EOFetchSpecification *)fetchSpecificationNamed:(NSString *)name;
45
+#endif
46
+
47
+// Getting the Java package as a string
48
+- (NSString *)classPackageName;
49
+
50
+#ifndef EOF2_ONLY
51
+- (NSString *)clientClassPackageName;
52
+- (NSString *)javaParentClientClassName;
53
+
54
+// JavaClient methods... reimplementation of ones in EOJavaClientExtensions.EOMBundle
55
+- (NSArray *)clientClassAttributes;
56
+- (NSArray *)clientClassToOneRelationships;
57
+- (NSArray *)clientClassToManyRelationships;
58
+- (NSArray *)clientClassScalarAttributes;
59
+- (NSArray *)clientClassNonScalarAttributes;
60
+#endif
61
+
62
+- (NSArray *)fetchSpecifications;
63
+- (NSArray *)beautifiedFetchSpecificationDictionaries;
64
+- (NSArray *)javaBeautifiedFetchSpecificationDictionaries;
65
+
66
+@end
67
+
68
+#ifndef EOF2_ONLY
69
+// <EOJavaClient/EOAccessAdditions.h> isn't always there (the ObjC framework
70
+// does not come with WO 4.5.1 on OS X or with WO 5), so just declare the
71
+// methods here.  Except with WO 4.0, the methods are actually implemented
72
+// in the EOAccess framework, so this is OK.
73
+@interface EOEntity (JavaClientExtensions)
74
+- (NSString *)clientClassName;
75
+- (NSString *)clientClassNameWithoutPackage;
76
+- (NSString *)referenceClientClassName;
77
+- (NSArray *)clientClassProperties;
78
+- (NSArray *)clientClassPropertyAttributeNames;
79
+- (NSArray *)clientClassPropertyToOneRelationshipNames;
80
+- (NSArray *)clientClassPropertyToManyRelationshipNames;
81
+@end
82
+#endif
83
+
84
+@interface EORelationship (EOAccessAdditions)
85
+
86
+// If the destination entity is in an external framework, returns
87
+// <Framework/ClassName.h>, otherwise returns "ClassName.h".
88
+- (NSString *)objcImportString;
89
+
90
+@end
91
+
92
+@interface EOAttribute (EOAccessAdditions)
93
+
94
+- (NSString *)javaValueTypeClassName;
95
+- (NSString *)javaScalarValueTypeClassName;
96
+
97
+@end
98
+
99
+@interface EOFetchSpecification (EOAccessAdditions)
100
+
101
+- (NSArray *)bindingParametersIsJava:(BOOL)isJava;
102
+- (NSArray *)bindingParameters;
103
+- (NSArray *)javaBindingParameters;
104
+
105
+@end
106
+
107
+@interface NSString (ModelStringManipulations)
108
+
109
+- (NSString *)uppercaseUnderbarString;
110
+- (NSString *)lowercaseNonUnderbarString;
111
+
112
+@end
113
+
114
+@interface EOGeneratorAttributePoser : EOAttribute
115
+@end
0 116
new file mode 100644
... ...
@@ -0,0 +1,647 @@
1
+/* EOAccessAdditions.m created by lindberg on Mon 20-Dec-1999 */
2
+/*-
3
+ * Copyright (c) 2002-2006 Carl Lindberg, Mike Gentry, and Doug McClure
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions
8
+ * are met:
9
+ * 1. Redistributions of source code must retain the above copyright
10
+ *    notice, this list of conditions and the following disclaimer.
11
+ * 2. Redistributions in binary form must reproduce the above copyright
12
+ *    notice, this list of conditions and the following disclaimer in the
13
+ *    documentation and/or other materials provided with the distribution.
14
+ *
15
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
16
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
19
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25
+ * POSSIBILITY OF SUCH DAMAGE.
26
+ */
27
+
28
+#import "EOAccessAdditions.h"
29
+#import "FoundationAdditions.h"
30
+#import <Foundation/Foundation.h>
31
+//#import <EOModeler/EOModelExtensions.h>
32
+
33
+#ifdef EOF2_ONLY
34
+@interface EOQualifier (EOF2AccessAdditions)
35
+- (NSArray *)bindingKeys;
36
+- (NSString *)keyPathForBindingKey:(NSString *)key;
37
+@end
38
+@interface EOEntity (JavaExtensions)
39
+- (NSString *)referenceJavaClassName;
40
+@end
41
+@interface EOAttribute (JavaExtensions)
42
+- (NSString *)javaValueClassName;
43
+@end
44
+@implementation EOQualifier (EOF2AccessAdditions)
45
+- (NSArray *)bindingKeys { return [NSArray array]; }
46
+- (NSString *)keyPathForBindingKey:(NSString *)key { return nil; }
47
+@end
48
+#endif
49
+
50
+@implementation EOModel (EOAccessAdditions)
51
+
52
+/*"
53
+ * Tries to find the framework name. First looks to see if a value for
54
+ * "EOGeneratorFrameworkName" exists in the model's -userInfo dictionary, and if
55
+ * not, looks at the model's -path to find the framework the .eomodeld is in.
56
+ * Both PB.project files and path components ending in ".framework" are looked
57
+ * for, so it should work for .eomodels insided installed frameworks or in a
58
+ * development tree. If the framework name could not be found, returns nil.
59
+ * Several other custom methods use this information to generate \#import
60
+ * statements better. If all your EO classes are in the same framework, this
61
+ * doesn't make much difference, but if there are EOModels in several different
62
+ * frameworks with interrelationships, these methods can make life a lot easier.
63
+"*/
64
+- (NSString *)frameworkName
65
+{
66
+    NSDictionary  *userInfo = [self userInfo];
67
+    NSFileManager *manager  = [NSFileManager defaultManager];
68
+    NSString      *name;
69
+
70
+    name = [userInfo objectForKey:@"EOGeneratorFrameworkName"];
71
+
72
+    if (name == nil)
73
+    {
74
+        NSString *fullPath = [self path];
75
+        NSMutableDictionary *mutableInfo = [[userInfo mutableCopy] autorelease];
76
+
77
+        if (mutableInfo == nil) mutableInfo = [NSMutableDictionary dictionary];
78
+
79
+        if (fullPath != nil && ![fullPath isAbsolutePath])
80
+            fullPath = [[manager currentDirectoryPath] stringByAppendingPathComponent:fullPath];
81
+
82
+        while ([fullPath isAbsolutePath])
83
+        {
84
+            NSString *pbPath;
85
+
86
+            fullPath = [fullPath stringByDeletingLastPathComponent];
87
+            pbPath = [fullPath stringByAppendingPathComponent:@"PB.project"];
88
+
89
+            if ([manager regularFileExistsAtPath:pbPath])
90
+            {
91
+                NSDictionary *project = [NSDictionary dictionaryWithContentsOfFile:pbPath];
92
+
93
+                if ([[project objectForKey:@"PROJECTTYPE"] hasSuffix:@"Framework"])
94
+                {
95
+                    name = [project objectForKey:@"PROJECTNAME"];
96
+                    break;
97
+                }
98
+            }
99
+            else if ([[fullPath pathExtension] isEqual:@"framework"])
100
+            {
101
+                name = [[fullPath lastPathComponent] stringByDeletingPathExtension];
102
+                break;
103
+            }
104
+        }
105
+
106
+        [mutableInfo setObject:name? name : @"" forKey:@"EOGeneratorFrameworkName"];
107
+        [self setUserInfo:mutableInfo];
108
+    }
109
+
110
+    return [name length] > 0 ? name : nil;
111
+}
112
+
113
+- (NSArray *)entityNamesMatchingWildcard:(NSString *)wildcard
114
+{
115
+    NSMutableArray *names = [NSMutableArray array];
116
+    NSArray *entities = [self entities];
117
+    int i, count = [entities count];
118
+
119
+    for (i=0; i<count; i++)
120
+    {
121
+        NSString *entityName = [(EOEntity*)[entities objectAtIndex:i] name];
122
+        if ([entityName isLike:wildcard])
123
+            [names addObject:entityName];
124
+    }
125
+
126
+    return names;
127
+}
128
+
129
+@end
130
+
131
+
132
+@implementation EOEntity (EOAccessAdditions)
133
+
134
+/*" Returns YES/NO if the there is a parent entity for this EOEntity. "*/
135
+- (BOOL)hasParentEntity
136
+{
137
+    return ([self parentEntity] != nil);
138
+}
139
+
140
+/*" Returns the framework name that the model is in. "*/
141
+- (NSString *)frameworkName
142
+{
143
+    return [[self model] frameworkName];
144
+}
145
+
146
+/*"
147
+ * Returns <Framework/ClassName.h> if inside a framework, "ClassName.h"
148
+ * otherwise.
149
+"*/
150
+- (NSString *)objcImportString
151
+{
152
+    return [self objcImportStringInRelationToEntity:nil];
153
+}
154
+
155
+/*"
156
+ * If sourceEntity is nil, returns <Framework/ClassName.h> if inside a
157
+ * framework, "ClassName.h" otherwise. If sourceEntity is non-nil, the
158
+ * <Framework/ClassName.h> version will only be returned if the receiver's
159
+ * framework and sourceEntity's framework are different.  This depends on
160
+ * the -#frameworkName method doing the right thing.
161
+"*/
162
+- (NSString *)objcImportStringInRelationToEntity:(EOEntity *)sourceEntity
163
+{
164
+    NSString *myClass = [self className];
165
+    NSString *myFramework = [self frameworkName];
166
+    NSString *sourceFramework = [sourceEntity frameworkName];
167
+
168
+    if ([myClass hasSuffix:@"EOGenericRecord"]) return nil;
169
+
170
+    if (myFramework != nil &&
171
+        (sourceEntity == nil || ![sourceFramework isEqualToString:myFramework]))
172
+    {
173
+        return [NSString stringWithFormat:@"<%@/%@.h>", myFramework, myClass];
174
+    }
175
+    else
176
+    {
177
+        return [NSString stringWithFormat:@"\"%@.h\"", myClass];
178
+    }
179
+}
180
+
181
+/*"
182
+ * If there is no parent entity, returns nil. Otherwise, uses
183
+ * -#objcImportStringInRelationToEntity: to determine the string needed to
184
+ * \#import the parent class. I'm not sure if EOModeler lets you have the parent
185
+ * entity in an external .eomodeld, but we'll provide this to be safe.
186
+"*/
187
+- (NSString *)parentObjCImportString
188
+{
189
+    return [[self parentEntity] objcImportStringInRelationToEntity:self];
190
+}
191
+
192
+/*"
193
+ * If -#parentObjCImportString is nil, returns an empty array, otherwise returns
194
+ * a single-element array with the parent import string.
195
+"*/
196
+- (NSArray *)arrayWithParentObjCImportStringIfNeeded
197
+{
198
+    NSString *import = [self parentObjCImportString];
199
+
200
+    if (import != nil)
201
+        return [NSArray arrayWithObject:import];
202
+    else
203
+        return [NSArray array];
204
+}
205
+
206
+/*"
207
+ * A parallel for -#referencedClassNames for dealing with import strings. The
208
+ * array will contain a uniqued list of \#import strings for all related
209
+ * entities.
210
+"*/
211
+- (NSArray *)referencedObjCImportStrings
212
+{
213
+    NSArray        *relationships = [self relationships];
214
+    int            i, count = [relationships count];
215
+    NSMutableArray *refImports = [NSMutableArray arrayWithCapacity:count];
216
+
217
+    for (i=0; i<count; i++)
218
+    {
219
+        EORelationship *relationship = [relationships objectAtIndex:i];
220
+        EOEntity       *destEntity   = [relationship destinationEntity];
221
+
222
+        if (![[destEntity className] hasSuffix:@"EOGenericRecord"])
223
+        {
224
+            NSString *import = [relationship objcImportString];
225
+            if (import && ![refImports containsObject:import])
226
+                [refImports addObject:import];
227
+        }
228
+    }
229
+
230
+    return [refImports sortedArrayUsingSelector:@selector(compare:)];
231
+}
232
+
233
+
234
+- (NSString *)classPackageName
235
+{
236
+    NSString *className = [self className];
237
+    NSRange  dotRange = [className rangeOfString:@"." options:NSBackwardsSearch];
238
+
239
+    if (dotRange.length > 0)
240
+        return [className substringToIndex:dotRange.location];
241
+
242
+    return nil;
243
+}
244
+
245
+#ifndef EOF2_ONLY
246
+- (NSString *)clientClassPackageName
247
+{
248
+    NSString *className = [self clientClassName];
249
+    NSRange  dotRange = [className rangeOfString:@"." options:NSBackwardsSearch];
250
+
251
+    if (dotRange.length > 0)
252
+        return [className substringToIndex:dotRange.location];
253
+
254
+    return nil;
255
+}
256
+
257
+- (NSString *)javaParentClientClassName
258
+{
259
+    NSString *parentClass = [[self parentEntity] clientClassName];
260
+    if (parentClass == nil || [parentClass length] == 0)
261
+        parentClass = @"EOGenericRecord";
262
+    return parentClass;
263
+}
264
+
265
+/*
266
+ * Implementations for some JavaClient-specific methods that EOModeler gets
267
+ * because they are in the EOJavaClientExtensions.EOMBundle. We could possibly
268
+ * load the bundle, but this is easier.
269
+ */
270
+
271
+- (NSArray *)clientClassAttributes
272
+{
273
+    NSArray *names = [self clientClassPropertyAttributeNames];
274
+    int     i, count = [names count];
275
+    NSMutableArray *attributes = [NSMutableArray arrayWithCapacity:count];
276
+
277
+    for (i=0; i<count; i++)
278
+        [attributes addObject:[self attributeNamed:[names objectAtIndex:i]]];
279
+
280
+    return attributes;
281
+}
282
+
283
+- (NSArray *)clientClassToOneRelationships
284
+{
285
+    NSArray *names = [self clientClassPropertyToOneRelationshipNames];
286
+    int     i, count = [names count];
287
+    NSMutableArray *relationships = [NSMutableArray arrayWithCapacity:count];
288
+
289
+    for (i=0; i<count; i++)
290
+        [relationships addObject:[self relationshipNamed:[names objectAtIndex:i]]];
291
+
292
+    return relationships;
293
+}
294
+
295
+- (NSArray *)clientClassToManyRelationships
296
+{
297
+    NSArray *names = [self clientClassPropertyToManyRelationshipNames];
298
+    int     i, count = [names count];
299
+    NSMutableArray *relationships = [NSMutableArray arrayWithCapacity:count];
300
+
301
+    for (i=0; i<count; i++)
302
+        [relationships addObject:[self relationshipNamed:[names objectAtIndex:i]]];
303
+
304
+    return relationships;
305
+}
306
+
307
+// These next two aren't used, but the bundle implements them, so we might as
308
+// well too in case someone wants to use them.
309
+- (NSArray *)clientClassScalarAttributes
310
+{
311
+    NSArray *attributes = [self clientClassAttributes];
312
+    int     i, count = [attributes count];
313
+    NSMutableArray *scalars = [NSMutableArray arrayWithCapacity:count];
314
+
315
+    for (i=0; i<count; i++)
316
+    {
317
+        EOAttribute *attrib = [attributes objectAtIndex:i];
318
+        if ([attrib isScalar])
319
+            [scalars addObject:attrib];
320
+    }
321
+
322
+    return scalars;
323
+}
324
+
325
+- (NSArray *)clientClassNonScalarAttributes
326
+{
327
+    NSArray *attributes = [self clientClassAttributes];
328
+    int     i, count = [attributes count];
329
+    NSMutableArray *nonscalars = [NSMutableArray arrayWithCapacity:count];
330
+
331
+    for (i=0; i<count; i++)
332
+    {
333
+        EOAttribute *attrib = [attributes objectAtIndex:i];
334
+        if (![attrib isScalar])
335
+            [nonscalars addObject:attrib];
336
+    }
337
+
338
+    return nonscalars;
339
+}
340
+
341
+#endif
342
+
343
+#ifdef EOF2_ONLY
344
+/* Define for use by EOF2 systems */
345
+- (NSString *)classNameWithoutPackage
346
+{
347
+    NSString *className = [self className];
348
+    NSRange  dotRange = [className rangeOfString:@"." options:NSBackwardsSearch];
349
+
350
+    if (dotRange.length > 0)
351
+        className = [className substringFromIndex:NSMaxRange(dotRange)];
352
+
353
+    return className;
354
+}
355
+
356
+- (NSString *)referenceJavaClassName
357
+{
358
+    return [self className];
359
+}
360
+
361
+- (NSArray *)fetchSpecificationNames
362
+{
363
+    return [NSArray array];
364
+}
365
+- (EOFetchSpecification *)fetchSpecificationNamed:(NSString *)name
366
+{
367
+    return nil;
368
+}
369
+- (NSArray *)clientClassProperties
370
+{
371
+    return [NSArray array];
372
+}
373
+
374
+#endif
375
+
376
+- (NSArray *)fetchSpecifications
377
+{
378
+    NSArray *fetchSpecificationNames = [self fetchSpecificationNames];
379
+    NSMutableArray *fetchSpecifications = [NSMutableArray arrayWithCapacity:[fetchSpecificationNames count]];
380
+    NSEnumerator *fetchNameEnumerator = [fetchSpecificationNames objectEnumerator];
381
+    NSString *fetchName;
382
+
383
+    while ( fetchName = [fetchNameEnumerator nextObject] ) {
384
+        NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
385
+        [dictionary setObject:fetchName forKey:@"name"];
386
+        [dictionary setObject:[self fetchSpecificationNamed:fetchName] forKey:@"spec"];
387
+        [dictionary setObject:[fetchName beautifyString] forKey:@"niceName"];
388
+        [fetchSpecifications addObject:dictionary];
389
+    }
390
+
391
+    return fetchSpecifications;
392
+}
393
+
394
+- (NSArray *)_beautifiedFetchSpecificationDictionariesIsJava:(BOOL)isJava
395
+{
396
+    NSArray *fetchSpecificationNames = [self fetchSpecificationNames];
397
+    NSMutableArray *fetchSpecifications = [NSMutableArray arrayWithCapacity:[fetchSpecificationNames count]];
398
+    NSMutableArray *addedNames = [NSMutableArray arrayWithCapacity:[fetchSpecificationNames count]];
399
+    NSEnumerator *fetchNameEnumerator = [fetchSpecificationNames objectEnumerator];
400
+    NSString *fetchName;
401
+
402
+    while ( fetchName = [fetchNameEnumerator nextObject] ) {
403
+        NSString *beautifyName = [fetchName beautifyString];
404
+        NSMutableString *methodName = [NSMutableString stringWithFormat:@"objectsFor%@", beautifyName];
405
+        EOFetchSpecification *fetchSpec = [self fetchSpecificationNamed:fetchName];
406
+        NSArray *bindings = [fetchSpec bindingParametersIsJava:isJava];
407
+        NSEnumerator *bindingEnumerator = [bindings objectEnumerator];
408
+        NSDictionary *binding;
409
+
410
+        if ( !isJava ) {
411
+            // To prevent duplicate method names, we must composite a complete ObjC name which will be
412
+            // the fetch specification name, beautified, and each of the bindings as a parameter
413
+            // ie: objectForFetchEmployees:departmentNumber:projectNumber:
414
+            [methodName appendString:@":"];
415
+
416
+            while ( binding = [bindingEnumerator nextObject] ) {
417
+                [methodName appendFormat:@"%@:", [binding objectForKey:@"name"]];
418
+            }
419
+        }
420
+        else {
421
+            // To prevent duplicate method names, we must composite a complete Java method name which will be
422
+            // the fetch specification name, beautified, and each binding's type as a parameter
423
+            // ie: objectForFetchEmployees(EOEditingContext,Department,Project)
424
+            [methodName appendString:@"(EOEditingContext"];
425
+
426
+            while ( binding = [bindingEnumerator nextObject] ) {
427
+                [methodName appendFormat:@",%@", [binding objectForKey:@"type"]];
428
+            }
429
+
430
+            [methodName appendString:@")"];
431
+        }
432
+
433
+        if ( [addedNames containsObject:methodName] ) {
434
+            ErrPrintf(@"Ignoring '%@' fetch specification in entity %@. Method name '%@' already used.", fetchName, [self name], methodName);
435
+        }
436
+        else {
437
+            NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
438
+            [dictionary setObject:methodName forKey:@"name"];
439
+            [dictionary setObject:fetchName forKey:@"fetchName"];
440
+            [dictionary setObject:beautifyName forKey:@"niceName"];
441
+            [dictionary setObject:fetchSpec forKey:@"fetchSpec"];
442
+            [dictionary setObject:bindings forKey:@"bindings"];
443
+            [fetchSpecifications addObject:dictionary];
444
+            [addedNames addObject:methodName];
445
+        }
446
+    }
447
+
448
+    return fetchSpecifications;
449
+}
450
+
451
+- (NSArray *)beautifiedFetchSpecificationDictionaries
452
+{
453
+    return [self _beautifiedFetchSpecificationDictionariesIsJava:NO];
454
+}
455
+
456
+- (NSArray *)javaBeautifiedFetchSpecificationDictionaries
457
+{
458
+    return [self _beautifiedFetchSpecificationDictionariesIsJava:YES];
459
+}
460
+
461
+@end
462
+
463
+
464
+// [PJYF June 3 2003]
465
+// Added this implemention to use the valueType in EOModeler for Java
466
+@implementation EOAttribute (EOAccessAdditions)
467
+
468
+- (NSString *)javaValueTypeClassName
469
+{
470
+    NSString *valueClassName = [self javaValueClassName];
471
+    NSString *valueType = [self valueType];
472
+
473
+    if ( [valueClassName isEqualToString:@"Number"] && ([valueType length] > 0) ) {
474
+        switch ( [valueType characterAtIndex:0] ) {
475
+            case 'b': return @"Byte";
476
+            case 's': return @"Short";
477
+            case 'i': return @"Integer";
478
+            case 'l': return @"Long";
479
+            case 'f': return @"Float";
480
+            case 'd': return @"Double";
481
+            case 'B': return @"java.math.BigDecimal";
482
+            case 'c': return @"Boolean";
483
+        }
484
+    }
485
+
486
+    return valueClassName;
487
+}
488
+
489
+- (NSString *)javaScalarValueTypeClassName
490
+{
491
+    NSString *valueClassName = [self javaValueClassName];
492
+    NSString *valueType = [self valueType];
493
+
494
+    if ( [valueClassName isEqualToString:@"Number"] && ([valueType length] > 0) ) {
495
+        switch ( [valueType characterAtIndex:0] ) {
496
+            case 'b': return @"byte";
497
+            case 's': return @"short";
498
+            case 'i': return @"int";
499
+            case 'l': return @"long";
500
+            case 'f': return @"float";
501
+            case 'd': return @"double";
502
+            case 'c': return @"boolean";
503
+        }
504
+    }
505
+
506
+    return nil;
507
+}
508
+
509
+@end
510
+
511
+
512
+@implementation EORelationship (EOAccessAdditions)
513
+
514
+- (NSString *)objcImportString
515
+{
516
+    return [[self destinationEntity] objcImportStringInRelationToEntity:[self entity]];
517
+}
518
+
519
+@end
520
+
521
+
522
+@implementation EOFetchSpecification (EOAccessAdditions)
523
+
524
+- (NSArray *)bindingParametersIsJava:(BOOL)forJava
525
+{
526
+    NSArray *bindings = [[self qualifier] bindingKeys];
527
+    EOClassDescription *classDesc = [EOClassDescription classDescriptionForEntityName:[self entityName]];
528
+    int i, count = [bindings count];
529
+    NSMutableArray *parameters = [NSMutableArray arrayWithCapacity:count];
530
+
531
+    for (i=0; i<count; i++)
532
+    {
533
+        NSString *binding = [bindings objectAtIndex:i];
534
+        NSString *keyPath = [[self qualifier] keyPathForBindingKey:binding];
535
+        EOClassDescription *currDesc = classDesc;
536
+        NSRange dotRange = [keyPath rangeOfString:@"."];
537
+        NSMutableDictionary *param = [NSMutableDictionary dictionary];
538
+
539
+        while (dotRange.length > 0)
540
+        {
541
+            currDesc = [currDesc classDescriptionForDestinationKey:[keyPath substringToIndex:dotRange.location]];
542
+            keyPath  = [keyPath substringFromIndex:NSMaxRange(dotRange)];
543
+            dotRange = [keyPath rangeOfString:@"."];
544
+        }
545
+
546
+        [param setObject:binding forKey:@"name"];
547
+        [param setObject:((forJava) ? @"java.lang.Object" : @"id") forKey:@"type"]; //set a default
548
+        [param setObject:((forJava) ? @"java.lang.Object " : @"id ") forKey:@"codeType"]; //set a default
549
+
550
+        if ([currDesc isKindOfClass:[EOEntityClassDescription class]])
551
+        {
552
+            EOEntity *entity = [(EOEntityClassDescription *)currDesc entity];
553
+
554
+            if ([entity attributeNamed:keyPath])
555
+            {
556
+                EOAttribute *attrib = [entity attributeNamed:keyPath];
557
+                NSString *type;
558
+
559
+                if (forJava) {
560
+                    type = [attrib javaValueClassName];
561
+                    [param setObject:type forKey:@"type"];
562
+                    [param setObject:[type stringByAppendingString:@" "] forKey:@"codeType"];
563
+                }
564
+                else {
565
+                    type = [attrib valueClassName];
566
+                    [param setObject:type forKey:@"type"];
567
+                    [param setObject:[type stringByAppendingString:@" *"] forKey:@"codeType"];
568
+                }
569
+
570
+                [param setObject:attrib forKey:@"attribute"];
571
+            }
572
+            else if ([entity relationshipNamed:keyPath])
573
+            {
574
+                EORelationship *rel = [entity relationshipNamed:keyPath];
575
+                NSString *type;
576
+
577
+                if (forJava) {
578
+                    type = [[rel destinationEntity] referenceJavaClassName];
579
+                    [param setObject:type forKey:@"type"];
580
+                    [param setObject:[type stringByAppendingString:@" "] forKey:@"codeType"];
581
+                }
582
+                else {
583
+                    type = [[rel destinationEntity] referenceClassName];
584
+                    [param setObject:[type substringToIndex:[type length]-2] forKey:@"type"]; // Removes the ' *' from the reference value type
585
+                    [param setObject:type forKey:@"codeType"];
586
+                }
587
+
588
+                [param setObject:rel forKey:@"relationship"];
589
+            }
590
+        }
591
+
592
+        [parameters addObject:param];
593
+    }
594
+
595
+    return parameters;
596
+}
597
+
598
+- (NSArray *)bindingParameters
599
+{
600
+    return [self bindingParametersIsJava:NO];
601
+}
602
+- (NSArray *)javaBindingParameters
603
+{
604
+    return [self bindingParametersIsJava:YES];
605
+}
606
+
607
+@end
608
+
609
+@implementation NSString (ModelStringManipulations)
610
+
611
+/*" Useful for turning key names into constant names "*/
612
+- (NSString *)uppercaseUnderbarString
613
+{
614
+    return [NSString externalNameForInternalName:self separatorString:@"_" useAllCaps:YES];
615
+}
616
+
617
+/*" Inverse of above method, just for completeness "*/
618
+- (NSString *)lowercaseNonUnderbarString
619
+{
620
+    return [NSString nameForExternalName:self separatorString:@"_" initialCaps:YES];
621
+}
622
+
623
+@end
624
+
625
+/*
626
+ * WO5 supports a valueType of "c" to juse java.lang.Boolean, but the
627
+ * javaValueClassName method still generates "Number".  We need to pose
628
+ * to fix this.
629
+ */
630
+@implementation EOGeneratorAttributePoser : EOAttribute
631
+- (NSString *)javaValueClassName
632
+{
633
+    if ([[self valueClassName] isEqual:@"NSNumber"] && [[self valueType] isEqual:@"c"])
634
+        return @"Boolean";
635
+    return [super javaValueClassName];
636
+}
637
+@end
638
+
639
+/* In WO5, some library that gets loaded looks for this class (it's in EOModeler).
640
+Not necessary but prevents an error from being printed out.
641
+*/
642
+@interface EOSchemaSynchronizationController : NSObject
643
+@end
644
+@implementation EOSchemaSynchronizationController
645
+@end
646
+
647
+
0 648
new file mode 100644
... ...
@@ -0,0 +1,310 @@
1
+<$comment
2
+EO Template for use by "eogenerator" based upon MiscMerge engine.
3
+You may customize this file to modify the templates generated
4
+by this tool.  See the MiscMerge documentation for a description
5
+of the parsing language.  The engine gets passed this file and an
6
+EOEntity to process, so the methods used must be ones that an
7
+EOEntity can respond to.
8
+
9
+BE SURE NOT TO INCLUDE DATES IN THIS FILE.  Since the "eogenerator"
10
+tool tries to compare the newly generated file with the old file,
11
+adding dates to this file will guarantee the old file gets
12
+overridden by the new file, forcing a recompilation of your EO.$>
13
+// <$GEN_PREFIX$><$classNameWithoutPackage$>.java
14
+// 
15
+// Created by eogenerator
16
+// DO NOT EDIT.  Make changes to <$classNameWithoutPackage$>.java instead.
17
+
18
+<$foreach package classPackage do$>package <$package$>;
19
+<$endforeach do$>
20
+import com.webobjects.foundation.*;
21
+import com.webobjects.eocontrol.*;
22
+import java.math.BigDecimal;
23
+import java.util.Enumeration;
24
+
25
+<$comment This is how to put in a custom EO superclass.  We also declare
26
+this class as being abstract, since it should never be instantiated.
27
+$>
28
+public abstract class <$GEN_PREFIX$><$classNameWithoutPackage$> extends <$if hasParentEntity$><$javaParentClassName$><$else$>MyEOSuperclass<$endif$>
29
+{
30
+<$comment
31
+
32
+Some people like to have constant strings defined for each key. For an
33
+attribute named fooBar, this will declare a FOO_BAR_KEY constant string,
34
+which can be used in calls to valueForKey(), addObjectToBothSides..., etc.
35
+A constant of ENTITY_NAME can be used for fetch specs and other methods.
36
+This lets the compiler flag usages of these keys when the names change.
37
+Additionally, it can be handy to have constants defined for the name 
38
+of the database table, the names of all the attribute column names, and fetch
39
+specifications.
40
+
41
+$>
42
+    public static final String ENTITY_NAME = "<$name$>";
43
+<$if externalName$>
44
+    public static final String ENTITY_TABLE_NAME = "<$externalName$>";<$endif$>
45
+<$foreach attribute attributes.@sortedNameArray do$>
46
+    public static final String <$attribute.name.uppercaseUnderbarString$>_KEY = "<$attribute.name$>";<$endforeach$>
47
+<$foreach attribute attributes.@sortedNameArray do$><$if attribute.columnName$>
48
+    public static final String <$attribute.name.uppercaseUnderbarString$>_COLKEY = "<$attribute.columnName$>";<$endif$><$endforeach$>
49
+<$foreach rel classToOneRelationships.@sortedNameArray do$>
50
+    public static final String <$rel.name.uppercaseUnderbarString$>_KEY = "<$rel.name$>";<$endforeach$>
51
+<$foreach rel classToManyRelationships.@sortedNameArray do$>
52
+    public static final String <$rel.name.uppercaseUnderbarString$>_KEY = "<$rel.name$>";<$endforeach$>
53
+<$foreach spec javaBeautifiedFetchSpecificationDictionaries.@sortedNameArray do$>
54
+    public static final String <$spec.fetchName.uppercaseUnderbarString$>_SPEC = "<$spec.fetchName$>";<$endforeach$>
55
+
56
+<$comment
57
+
58
+These do the same thing, but use mixed case strings instead of all uppercase.
59
+These are commented out by default
60
+
61
+    public static final String EntityName = "<$name$>";
62
+<$if externalName$>
63
+    public static final String EntityTableName = "<$externalName$>";<$endif$>
64
+<$foreach attribute attributes.@sortedNameArray do$>
65
+    public static final String <$attribute.name.initialCapitalString$>Key = "<$attribute.name$>";<$endforeach$>
66
+<$foreach attribute attributes.@sortedNameArray do$><$if attribute.columnName$>
67
+    public static final String <$attribute.name.initialCapitalString$>ColKey = "<$attribute.columnName$>";<$endif$><$endforeach$>
68
+<$foreach rel classToOneRelationships.@sortedNameArray do$>
69
+    public static final String <$rel.name.initialCapitalString$>Key = "<$rel.name$>";<$endforeach$>
70
+<$foreach rel classToManyRelationships.@sortedNameArray do$>
71
+    public static final String <$rel.name.initialCapitalString$>Key = "<$rel.name$>";<$endforeach$>
72
+<$foreach spec javaBeautifiedFetchSpecificationDictionaries.@sortedNameArray do$>
73
+    public static final String <$spec.fetchName.initialCapitalString$>Spec = "<$spec.fetchName$>";<$endforeach$>
74
+
75
+$><$comment
76
+
77
+This section will create a method to create a new instance of this entity.
78
+It is essentially identical to EOUtilies' createAndInsertInstance method.
79
+This won't necessarily work if you are using inheritance. The commented out
80
+method following this one would be generally a better method to use if
81
+you need to deal with inheritance.
82
+
83
+$><$if !isAbstractEntity$>
84
+    public static <$classNameWithoutPackage$> newInstance(EOEditingContext context) {
85
+    	EOClassDescription desc = EOClassDescription.classDescriptionForEntityName(ENTITY_NAME);
86
+    	EOEnterpriseObject object = desc.createInstanceWithEditingContext(context, null);
87
+    	context.insertObject(object);
88
+    	return (<$classNameWithoutPackage$>)object;
89
+    }<$endif$>
90
+<$comment Java does not allow static methods of the same name in a subclass
91
+   to return a different type, so for some types of inheritance the above will
92
+   not work.  In these cases, declare the method like this:
93
+
94
+    public static <$classNameWithoutPackage$> new<$classNameWithoutPackage$>Instance(EOEditingContext context)
95
+
96
+$>
97
+    public <$GEN_PREFIX$><$classNameWithoutPackage$>() {
98
+        super();
99
+    }
100
+
101
+<$comment
102
+Add methods to call named fetch specifications, with any qualifier bindings having typed
103
+parameters.
104
+
105
+$><$foreach FetchSpec javaBeautifiedFetchSpecificationDictionaries.@sortedNameArray do$>
106
+    public static NSArray objectsFor<$FetchSpec.niceName$>(EOEditingContext context<$foreach Binding FetchSpec.bindings do2$>, <$Binding.codeType$><$Binding.name$>Binding<$endforeach do2$>) {
107
+        EOFetchSpecification spec = EOFetchSpecification.fetchSpecificationNamed("<$FetchSpec.fetchName$>", "<$name$>");
108
+<$if FetchSpec.bindings.@count > 0$>
109
+        NSMutableDictionary bindings = new NSMutableDictionary();
110
+<$foreach Binding FetchSpec.bindings do2$>
111
+        if (<$Binding.name$>Binding != null)
112
+            bindings.setObjectForKey(<$Binding.name$>Binding, "<$Binding.name$>");<$endforeach do2$>
113
+        spec = spec.fetchSpecificationWithQualifierBindings(bindings);
114
+<$endif$>
115
+        return context.objectsWithFetchSpecification(spec);
116
+    }
117
+<$endforeach do$>
118
+
119
+<$foreach Attribute classAttributes.@sortedNameArray do$>
120
+    public <$Attribute.javaValueClassName$> <$Attribute.name$>() {
121
+        return (<$Attribute.javaValueClassName$>)storedValueForKey("<$Attribute.name$>");
122
+    }
123
+    public void set<$Attribute.name.initialCapitalString$>(<$Attribute.javaValueClassName$> aValue) {
124
+        takeStoredValueForKey(aValue, "<$Attribute.name$>");
125
+    }<$comment
126
+
127
+ADVANCED EXAMPLE
128
+
129
+The following code shows an example of using the userInfo dictionary on an attribute to create
130
+additional methods.
131
+
132
+This example allows the user to define the key 'abbreviate' to create a method that will turn a
133
+string into a abbreviated version.  This can be really handy in WO components where you may need
134
+to display a text string that could be very long, but need it to always fit in a certain area.
135
+Additional methods could be made to make shorter or longer abbreviated strings.  The code checks
136
+to see if the type of the attribute is a String and if the abbreviated length is at least greater
137
+than 3 characters, before it will create the method.
138
+
139
+<$if Attribute.javaValueClassName eq 'String' and Attribute.userInfo.abbreviate gt 3$>
140
+    public String abbreviated<$Attribute.name.initialCapitalString$>() {
141
+        String value = <$Attribute.name$>();
142
+        if ( value != null && value.length() > <$Attribute.userInfo.abbreviate$> )
143
+            value = value.substring(0,<$Attribute.userInfo.abbreviate$> - 3) + "...";
144
+        return value;
145
+    }
146
+<$endif$>
147
+
148
+This is just one example of data manipulation that eogenerator can do.  You could have methods that
149
+uppercase values, strip blanks, encrypt the text, etc. all determined by entries in the userInfo
150
+dictionary.  See below for a To-Many relationship example.
151
+
152
+$>
153
+<$endforeach do$>
154
+
155
+
156
+<$foreach ToOneRelationship classToOneRelationships.@sortedNameArray do$>
157
+    public <$ToOneRelationship.destinationEntity.referenceJavaClassName$> <$ToOneRelationship.name$>() {
158
+        return (<$ToOneRelationship.destinationEntity.referenceJavaClassName$>)storedValueForKey("<$ToOneRelationship.name$>");
159
+    }
160
+    public void set<$ToOneRelationship.name.initialCapitalString$>(<$ToOneRelationship.destinationEntity.referenceJavaClassName$> aValue) {
161
+        takeStoredValueForKey(aValue, "<$ToOneRelationship.name$>");
162
+    }<$comment
163
+
164
+The following method is better than using addObjectToBothSidesOfRelationshipWithKey directly
165
+because you will get compile time type checking instead of runtime checking (plus you don't
166
+risk typos in contstant strings of key names).
167
+$>
168
+    public void set<$ToOneRelationship.name.initialCapitalString$>Relationship(<$ToOneRelationship.destinationEntity.referenceJavaClassName$> value) {
169
+        if (value == null) {
170
+            <$ToOneRelationship.destinationEntity.referenceJavaClassName$> object = <$ToOneRelationship.name$>();
171
+            if (object != null)
172
+                removeObjectFromBothSidesOfRelationshipWithKey(object, "<$ToOneRelationship.name$>");
173
+        }
174
+        else {
175
+            addObjectToBothSidesOfRelationshipWithKey(value, "<$ToOneRelationship.name$>");
176
+        }
177
+    }
178
+<$endforeach do$>
179
+
180
+
181
+<$foreach ToManyRelationship classToManyRelationships.@sortedNameArray tomanyrels$>
182
+    public NSArray <$ToManyRelationship.name$>() {
183
+        return (NSArray)storedValueForKey("<$ToManyRelationship.name$>");
184
+    }
185
+    public void set<$ToManyRelationship.name.initialCapitalString$>(NSMutableArray aValue) {
186
+        takeStoredValueForKey(aValue, "<$ToManyRelationship.name$>");
187
+    }
188
+    public void addTo<$ToManyRelationship.name.initialCapitalString$>(<$ToManyRelationship.destinationEntity.referenceJavaClassName$> object) {
189
+        NSMutableArray array = (NSMutableArray)<$ToManyRelationship.name$>();
190
+        willChange();
191
+        array.addObject(object);
192
+    }
193
+    public void removeFrom<$ToManyRelationship.name.initialCapitalString$>(<$ToManyRelationship.destinationEntity.referenceJavaClassName$> object) {
194
+        NSMutableArray array = (NSMutableArray)<$ToManyRelationship.name$>();
195
+        willChange();
196
+        array.removeObject(object);
197
+    }<$comment
198
+
199
+The following adds typed methods to add or remove an object from a to-many relationship.
200
+This is better than using addObjectToBothSidesOfRelationshipWithKey directly because
201
+you will get compile time type checking instead of runtime checking, and you avoid the
202
+possibility of making a typo in the key name.
203
+$>
204
+    public void addTo<$ToManyRelationship.name.initialCapitalString$>Relationship(<$ToManyRelationship.destinationEntity.referenceJavaClassName$> object) {
205
+        addObjectToBothSidesOfRelationshipWithKey(object, "<$ToManyRelationship.name$>");
206
+    }
207
+    public void removeFrom<$ToManyRelationship.name.initialCapitalString$>Relationship(<$ToManyRelationship.destinationEntity.referenceJavaClassName$> object) {
208
+        removeObjectFromBothSidesOfRelationshipWithKey(object, "<$ToManyRelationship.name$>");
209
+    }<$comment
210
+
211
+The following adds typed methods to create, and delete objects from a to-many relationship.
212
+The main difference in the delete mechanism, versus the removeFrom... method above is that
213
+this delete method will remove the object from the editing context if it is we do not own
214
+its destination.  The user can override these methods in the subclass to provide additional
215
+functionality on these methods.
216
+$>
217
+    public <$ToManyRelationship.destinationEntity.referenceJavaClassName$> create<$ToManyRelationship.name.initialCapitalString$>Relationship() {
218
+	EOClassDescription eoClassDesc = EOClassDescription.classDescriptionForEntityName("<$ToManyRelationship.destinationEntity.name$>");
219
+	EOEnterpriseObject eoObject = eoClassDesc.createInstanceWithEditingContext(editingContext(), null);
220
+	editingContext().insertObject(eoObject);
221
+	addObjectToBothSidesOfRelationshipWithKey(eoObject, "<$ToManyRelationship.name$>");
222
+	return (<$ToManyRelationship.destinationEntity.referenceJavaClassName$>)eoObject;
223
+    }
224
+    public void delete<$ToManyRelationship.name.initialCapitalString$>Relationship(<$ToManyRelationship.destinationEntity.referenceJavaClassName$> object) {
225
+        removeObjectFromBothSidesOfRelationshipWithKey(object, "<$ToManyRelationship.name$>");<$
226
+if !ToManyRelationship.ownsDestination$>
227
+        editingContext().deleteObject(object);<$endif$>
228
+    }
229
+    public void deleteAll<$ToManyRelationship.name.initialCapitalString$>Relationships() {
230
+	Enumeration objects = new NSArray(<$ToManyRelationship.name$>()).objectEnumerator();
231
+	while ( objects.hasMoreElements() )
232
+	    delete<$ToManyRelationship.name.initialCapitalString$>Relationship((<$ToManyRelationship.destinationEntity.referenceJavaClassName$>)objects.nextElement());
233
+    }<$comment
234
+
235
+ADVANCED EXAMPLE
236
+
237
+The following code is an example of something fancier that can be done than just making creating
238
+the default accessor methods.
239
+
240
+A common task in many EOs is to have methods that will return sorted arrays of the to-many
241
+relationships.  While it is generally pretty easy to create these methods, it can become tedious
242
+if you have many relationships that need ordering.  This example provides a way to make generating
243
+those methods easier.
244
+
245
+It works by using the userInfo dictionary on an EORelationship.  You can put key-value pairs in
246
+that dictionary that can then be accessed by eogenerator to conditionally compile information.
247
+In the example below, the code looks to see if there is a key named 'sortMethods' defined in
248
+the userInfo dictionary.  If there is, then it presumes that the value will be an array of 
249
+dictionaries that define the sort methods. Each dictionary corresponds to one sort method,
250
+so that you can create multiple methods on a single relationship. This dictionary has one
251
+optional element, a key named 'by' and one required element, a key named 'ordering'. The 'by'
252
+key allows you to specify a extension to be tacked onto the method name. Because you can
253
+create multiple methods for sorting, this is needed to insure you don't have a name conflict.
254
+Note: The code doesn't check for conflicts, it just allows a way out.  The 'ordering' key takes
255
+an array of dictionaries itself.  These dictionaries just has one required element, a 'key' element
256
+and an optional 'sel' element.  The 'key' element should have the name of an attribute to sort
257
+on, while the 'sel' element is just the name of a EOSortOrdering selector, just the part after
258
+the 'EOSortOrdering.Compare' portion for simplicity. If no 'sel' value is given, then the code
259
+just uses Ascending.
260
+
261
+So say we have this example userInfo entry for 'sortMethods' on an 'employees' reletionship:
262
+
263
+  ({ by = NameAndDOB; ordering = ({key = name; sel = Ascending}, {key = dob; sel = Descending}); },
264
+   { ordering = ({key = name}) };)
265
+
266
+We end up with two methods:
267
+
268
+   public NSArray orderedEmployeesByNameAndDOB() // Ordered by ascending name and descending dob
269
+   public NSArray orderedEmployees()		 // Ordered by ascending name
270
+
271
+<$foreach SortMethod ToManyRelationship.userInfo.sortMethods sortmethodloop$><$
272
+  if SortMethod.ordering.@count gt 0$><$
273
+    if SortMethod.by ne ''$><$setmerge SortMethodBy = "By<$SortMethod.by$>"$><$endif$>
274
+
275
+    // Store the sort ordering in a private variable so that it won't take so long to execute the method
276
+    // especially useful if the sort method gets called a lot.
277
+    private static NSArray _orderingsFor<$ToManyRelationship.name.initialCapitalString$><$SortMethodBy$>;
278
+    
279
+    public NSArray ordered<$ToManyRelationship.name.initialCapitalString$><$SortMethodBy$>() {
280
+        NSArray objects = <$ToManyRelationship.name$>();
281
+        if ( objects.count() > 1 ) {
282
+            if ( _orderingsFor<$ToManyRelationship.name.initialCapitalString$><$SortMethodBy$> == null )
283
+                _orderingsFor<$ToManyRelationship.name.initialCapitalString$><$SortMethodBy$> = new NSArray(
284
+		    new Object[] {<$foreach Ordering SortMethod.ordering orderLoop$><$if OrderingIndex gt 0$>,<$endif$>
285
+                    	EOSortOrdering.sortOrderingWithKey("<$Ordering.key$>", EOSortOrdering.Compare<$if Ordering.sel$><$Ordering.sel$><$else$>Ascending<$endif$>)<$endforeach orderLoop$>
286
+                    }
287
+		);
288
+
289
+            objects = EOSortOrdering.sortedArrayUsingKeyOrderArray(objects, _orderingsFor<$ToManyRelationship.name.initialCapitalString$><$SortMethodBy$>);
290
+        }
291
+        return objects;
292
+    }<$
293
+  endif$><$
294
+endforeach sortmethodloop$>
295
+
296
+This may seem kind of complex and more effort than its worth, but a great many repetitive
297
+coding tasks can be accomplished by eogenerator in this same way.  You could have userInfo
298
+entries for attributes to do case conversion, do data conversion from one type to another
299
+(like T/F to boolean true/false), or create abbreviated strings of very long text. You could
300
+have to-many entries to setup filtering for some defined value(s) you provide.  You could
301
+even stick something in EOEntity's userInfo itself to setup some complex validation checking.
302
+
303
+We encourage you to explore the possibilities and if you find you've created some addition that is
304
+really useful, generic enough to be used by others, and you'd like to see included as an
305
+example here, your more than welcome to donate your ideas.
306
+
307
+$>
308
+<$endforeach tomanyrels$>
309
+}
310
+
0 311
new file mode 100644
... ...
@@ -0,0 +1,58 @@
1
+<$comment
2
+EOGenerator template for generated classes' Objective-C headers.
3
+This file is a more likely example of one to be actually used
4
+in a production environment, as it is much lighter-weight at
5
+#importing headers, and it shows how to do a custom EO superclass.
6
+
7
+BE SURE NOT TO INCLUDE DATES IN THIS FILE.  Since the "eogenerator"
8
+tool tries to compare the newly generated file with the old file,
9
+adding dates to this file will guarantee the old file gets
10
+overridden by the new file, forcing a recompilation of your EO.$>
11
+
12
+// <$GEN_PREFIX$><$className$>.h
13
+// 
14
+// Created by "eogenerator"
15
+// DO NOT EDIT.  Make changes to <$className$>.h instead.
16
+
17
+<$comment The below 'set' puts the FetchSpec into the global lookup space. We
18
+do this because the beautifiedFetchSpecificationDictionaries actually will
19
+print some logs and does a lot of object creation so this will keep the
20
+fuss down to a minimum.
21
+$><$set FetchSpecs = beautifiedFetchSpecificationDictionaries.@sortedNameArray$>
22
+
23
+<$if hasParentEntity$>
24
+#import <$parentObjCImportString$>
25
+<$else$>
26
+//#import <MyFramework/MyEOSuperclass.h>
27
+#import <EOControl/EOGenericRecord.h>
28
+<$endif$>
29
+<$foreach relationship referencedClasses.@reversedArray do$>
30
+@class <$relationship$>;<$endforeach do$>
31
+@class NSArray, NSMutableArray;
32
+
33
+@interface <$GEN_PREFIX$><$className$> : <$if hasParentEntity$><$parentClassName$><$else$>EOGenericRecord<$endif$>
34
+{
35
+}
36
+<$foreach attribute classAttributes.@sortedNameArray do$>
37
+- (void)set<$attribute.name.initialCapitalString$>:(<$attribute.valueClassName$> *)aValue;
38
+- (<$attribute.valueClassName$> *)<$attribute.name$>;
39
+<$endforeach do
40
+
41
+$><$foreach toOneRelationship classToOneRelationships.@sortedNameArray do$>
42
+- (void)set<$toOneRelationship.name.initialCapitalString$>:(<$toOneRelationship.destinationEntity.referenceClassName$>)aValue;
43
+- (<$toOneRelationship.destinationEntity.referenceClassName$>)<$toOneRelationship.name$>;
44
+- (void)set<$toOneRelationship.name.initialCapitalString$>Relationship:(<$toOneRelationship.destinationEntity.referenceClassName$>)aValue;
45
+<$endforeach do
46
+
47
+$><$foreach toManyRelationship classToManyRelationships.@sortedNameArray do$>
48
+- (void)set<$toManyRelationship.name.initialCapitalString$>:(NSMutableArray *)aValue;
49
+- (NSArray *)<$toManyRelationship.name$>;
50
+- (void)addTo<$toManyRelationship.name.initialCapitalString$>:(<$toManyRelationship.destinationEntity.referenceClassName$>)object;
51
+- (void)removeFrom<$toManyRelationship.name.initialCapitalString$>:(<$toManyRelationship.destinationEntity.referenceClassName$>)object;
52
+- (void)addTo<$toManyRelationship.name.initialCapitalString$>Relationship:(<$toManyRelationship.destinationEntity.referenceClassName$>)object;
53
+- (void)removeFrom<$toManyRelationship.name.initialCapitalString$>Relationship:(<$toManyRelationship.destinationEntity.referenceClassName$>)object;
54
+<$endforeach do
55
+
56
+$><$foreach FetchSpec FetchSpecs do$>
57
++ (NSArray *)objectsFor<$FetchSpec.niceName$>:(EOEditingContext *)context<$foreach Binding FetchSpec.bindings do2$> <$Binding.name$>:(<$Binding.codeType$>)<$Binding.name$>Binding<$endforeach do2$>;<$endforeach do$>
58
+@end
0 59
new file mode 100644
... ...
@@ -0,0 +1,121 @@
1
+<$comment
2
+EOGenerator template for generated classes' Objective-C source files.
3
+This file is a more likely example of one to be actually used
4
+in a production environment.
5
+
6
+BE SURE NOT TO INCLUDE DATES IN THIS FILE.  Since the "eogenerator"
7
+tool tries to compare the newly generated file with the old file,
8
+adding dates to this file will guarantee the old file gets
9
+overridden by the new file, forcing a recompilation of your EO.$>
10
+
11
+// <$GEN_PREFIX$><$className$>.m
12
+// 
13
+// Created by eogenerator
14
+// DO NOT EDIT.  Make changes to <$className$>.m instead.
15
+
16
+#import "<$GEN_PREFIX$><$className$>.h"
17
+#import <Foundation/Foundation.h>
18
+#import <EOControl/EOEditingContext.h>
19
+#import <EOControl/EOClassDescription.h>
20
+<$if FetchSpecs.@count > 0 $>
21
+#import <EOControl/EOFetchSpecification.h>
22
+<$endif$>
23
+<$comment  Use referencedObjCImportStrings instead of referencedClasses
24
+           for better #import handling for cross-framework relationships.
25
+$><$foreach importString referencedObjCImportStrings do$>#import <$importString$>
26
+<$endforeach do$>
27
+
28
+@implementation <$GEN_PREFIX$><$className$>
29
+
30
+// EOF invokes this init method when creating objects.
31
+- (id)initWithEditingContext:(EOEditingContext *)editingContext classDescription:(EOClassDescription *)classDesc globalID:(EOGlobalID *)gid
32
+{
33
+    self = [super initWithEditingContext:editingContext classDescription:classDesc globalID:gid];
34
+    return self;
35
+}
36
+
37
+// This init method is usually used from user code.
38
+- (id)init
39
+{
40
+    self = [super init];
41
+    return self;
42
+}
43
+
44
+<$foreach attribute classAttributes.@sortedNameArray do$>
45
+- (void)set<$attribute.name.initialCapitalString$>:(<$attribute.valueClassName$> *)aValue
46
+{
47
+    [self takeStoredValue:aValue forKey:@"<$attribute.name$>"];
48
+}
49
+- (<$attribute.valueClassName$> *)<$attribute.name$>
50
+{
51
+    return [self storedValueForKey:@"<$attribute.name$>"];
52
+}
53
+<$endforeach do$>
54
+
55
+<$foreach toOneRelationship classToOneRelationships.@sortedNameArray do$>
56
+- (void)set<$toOneRelationship.name.initialCapitalString$>:(<$toOneRelationship.destinationEntity.referenceClassName$>)aValue
57
+{
58
+    [self takeStoredValue:aValue forKey:@"<$toOneRelationship.name$>"];
59
+}
60
+- (<$toOneRelationship.destinationEntity.referenceClassName$>)<$toOneRelationship.name$>
61
+{
62
+    return [self storedValueForKey:@"<$toOneRelationship.name$>"];
63
+}
64
+- (void)set<$toOneRelationship.name.initialCapitalString$>Relationship:(<$toOneRelationship.destinationEntity.referenceClassName$>)aValue
65
+{
66
+    if (aValue == nil) {
67
+        <$toOneRelationship.destinationEntity.referenceClassName$>object = [self <$toOneRelationship.name$>];
68
+        if (object != nil)
69
+            [self removeObject:object fromBothSidesOfRelationshipWithKey:@"<$toOneRelationship.name$>"];
70
+    }
71
+    else {
72
+        [self addObject:aValue toBothSidesOfRelationshipWithKey:@"<$toOneRelationship.name$>"];
73
+    }
74
+}
75
+<$endforeach do$>
76
+
77
+<$foreach toManyRelationship classToManyRelationships.@sortedNameArray do$>
78
+- (void)set<$toManyRelationship.name.initialCapitalString$>:(NSMutableArray *)aValue
79
+{
80
+    [self takeStoredValue:aValue forKey:@"<$toManyRelationship.name$>"];
81
+}
82
+- (NSArray *)<$toManyRelationship.name$>
83
+{
84
+    return [self storedValueForKey:@"<$toManyRelationship.name$>"];
85
+}
86
+- (void)addTo<$toManyRelationship.name.initialCapitalString$>:(<$toManyRelationship.destinationEntity.referenceClassName$>)object
87
+{
88
+    NSMutableArray *array = (NSMutableArray *)[self <$toManyRelationship.name$>];
89
+    [self willChange];
90
+    [array addObject:object];
91
+}
92
+- (void)removeFrom<$toManyRelationship.name.initialCapitalString$>:(<$toManyRelationship.destinationEntity.referenceClassName$>)object
93
+{
94
+    NSMutableArray *array = (NSMutableArray *)[self <$toManyRelationship.name$>];
95
+    [self willChange];
96
+    [array removeObject:object];
97
+}
98
+- (void)addTo<$toManyRelationship.name.initialCapitalString$>Relationship:(<$toManyRelationship.destinationEntity.referenceClassName$>)object
99
+{
100
+    [self addObject:object toBothSidesOfRelationshipWithKey:@"<$toManyRelationship.name$>"];
101
+}
102
+- (void)removeFrom<$toManyRelationship.name.initialCapitalString$>Relationship:(<$toManyRelationship.destinationEntity.referenceClassName$>)object
103
+{
104
+    [self removeObject:object fromBothSidesOfRelationshipWithKey:@"<$toManyRelationship.name$>"];
105
+}
106
+<$endforeach do$>
107
+
108
+<$foreach FetchSpec FetchSpecs do$>
109
++ (NSArray *)objectsFor<$FetchSpec.niceName$>:(EOEditingContext *)context<$foreach Binding FetchSpec.bindings do2$> <$Binding.name$>:(<$Binding.codeType$>)<$Binding.name$>Binding<$endforeach do2$>
110
+{
111
+    EOFetchSpecification *spec = [EOFetchSpecification fetchSpecificationNamed:@"<$FetchSpec.fetchName$>" entityNamed:@"<$name$>"];<$if FetchSpec.bindings.@count gt 0$>
112
+    NSMutableDictionary *bindings = [NSMutableDictionary dictionary];
113
+<$foreach Binding FetchSpec.bindings do2$>
114
+    if ( <$Binding.name$>Binding != nil )
115
+        [bindings setObject:<$Binding.name$>Binding forKey:@"<$Binding.name$>"];<$endforeach do2$>
116
+    spec = [spec fetchSpecificationWithQualifierBindings:bindings];
117
+<$endif$>
118
+    return [context objectsWithFetchSpecification:spec];
119
+}
120
+<$endforeach do$>
121
+@end
0 122
new file mode 100644
... ...
@@ -0,0 +1,5 @@
1
+#import <EOAccess/EOModel.h>
2
+#import <EOAccess/EOModelGroup.h>
3
+#import <EOAccess/EOEntity.h>
4
+#import <EOAccess/EOAttribute.h>
5
+#import <EOAccess/EORelationship.h>
0 6
new file mode 100644
... ...
@@ -0,0 +1,8 @@
1
+#import <Foundation/NSObject.h>
2
+@interface EOAttribute : NSObject
3
+{
4
+    id padding[30];
5
+}
6
+-(id)valueType;
7
+-(id)valueClassName;
8
+@end
0 9
new file mode 100644
... ...
@@ -0,0 +1,20 @@
1
+#import <Foundation/NSString.h>
2
+
3
+@interface EOEntity
4
+-(id)name;
5
+-(id)parentEntity;
6
+-(NSString *)frameworkName;
7
+-(id)model;
8
+-(id)className;
9
+-(id)relationships;
10
+-(id)className;
11
+-(id)attributeNamed:(id)name;
12
+-(id)relationshipNamed:(id)name;
13
+-(id)fetchSpecificationNames;
14
+-(id)fetchSpecificationNamed:(id)name;
15
+@end
16
+
17
+@interface NSString (EOEntityAdditions)
18
++ (NSString *)externalNameForInternalName:(NSString *)name separatorString:(NSString *)separatorString useAllCaps:(BOOL)useAllCaps;
19
++ (NSString *)nameForExternalName:(NSString *)name separatorString:(NSString *)separatorString initialCaps:(BOOL)initialCaps;
20
+@end
0 21
new file mode 100644
... ...
@@ -0,0 +1,10 @@
1
+#import <Foundation/NSObjCRuntime.h>
2
+@interface EOModel
3
++ (id)alloc;
4
+-(id)userInfo;
5
+-(NSString *)path;
6
+-(id)entities;
7
+-(NSString *)name;
8
+-setUserInfo:(id)userInfo;
9
+-release;
10
+@end
0 11
new file mode 100644
... ...
@@ -0,0 +1,9 @@
1
+@interface EOModelGroup
2
++(id)alloc;
3
++(id)defaultGroup;
4
++setDefaultGroup:(id)group;
5
+-setDelegate:(id)delegate;
6
+-(id)modelNamed:(id)name;
7
+-addModel:(id)model;
8
+-(id)entityNamed:(id)name;
9
+@end
0 10
new file mode 100644
... ...
@@ -0,0 +1,5 @@
1
+@interface EORelationship
2
+-(id)destinationEntity;
3
+-(id)entity;
4
+-(id)name;
5
+@end
0 6
new file mode 100644
... ...
@@ -0,0 +1,5 @@
1
+@interface EOClassDescription
2
++(id)classDescriptionForEntityName:(id)name;
3
+-(id)classDescriptionForDestinationKey:(id)key;
4
+-(BOOL)isKindOfClass:(id)class;
5
+@end
0 6
new file mode 100644
... ...
@@ -0,0 +1,4 @@
1
+@interface EOEntityClassDescription
2
++(id)class;
3
+-(id)entity;
4
+@end
0 5
new file mode 100644
... ...
@@ -0,0 +1,9 @@
1
+#import <EOControl/EOClassDescription.h>
2
+#import <EOControl/EOEntityClassDescription.h>
3
+
4
+@interface EOFetchSpecification
5
+-(id)entityName;
6
+-(id)qualifier;
7
+-(id)bindingKeys;
8
+-(id)keyPathForBindingKey:(id)bindingKey;
9
+@end