1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
|
/*
Wotonomy: OpenStep design patterns for pure Java applications.
Copyright (C) 2001 Intersect Software Corporation
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, see http://www.gnu.org
*/
package net.wotonomy.control;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import net.wotonomy.foundation.NSArray;
import net.wotonomy.foundation.NSDictionary;
import net.wotonomy.foundation.NSSet;
import net.wotonomy.foundation.internal.WotonomyException;
/**
* EOCustomObject implements all the necessary interfaces to
* receive first-class treatment from the control framework.
* The implementation delegates as much class meta-behavior as
* possible to EOClassDescription, letting subclasses
* focus exclusively on business logic while still allowing
* them to customize as much class behavior as needed.
*
* @author michael@mpowers.net
* @author $Author: cgruber $
* @version $Revision: 894 $
*/
public class EOCustomObject
implements EOEnterpriseObject,
EOKeyValueCodingAdditions,
EODeferredFaulting,
EORelationshipManipulation,
EOValidation
{
private transient static EOClassDescription classDescription;
private transient EOEditingContext editingContext;
// static configuration
/**
* Specifies whether the implementation of EOKeyValueCoding
* is permitted to access field directly. This implementation
* returns true; subclasses may override to customize this behavior.
*/
public static boolean canAccessFieldsDirectly()
{
return true;
}
/**
* Specifies whether the implementation of EOKeyValueCoding
* is permitted to access private accessors. This implementation
* returns true; subclasses may override to customize this behavior.
*/
public static boolean shouldUseStoredAccessors()
{
return true;
}
/**
* Specifies whether deferred faults should be used. This implementation
* returns false; subclasses may override to customize this behavior.
*/
public static boolean usesDeferredFaultCreation()
{
return false;
}
// constructors
/**
* Default constructor initializes private state.
* EditingContext and ClassDescription are set to null.
*/
public EOCustomObject()
{
editingContext = null;
classDescription = null;
}
/**
* Preferred constructor, specifying an editing context,
* a class description, and a global id, any or all of which
* may be null. Subclasses should invoke this constructor.
*/
public EOCustomObject(
EOEditingContext aContext,
EOClassDescription aClassDescription,
EOGlobalID aGlobalID )
{
editingContext = aContext;
classDescription = aClassDescription;
}
// interface EOEnterpriseObject
/**
* Returns a List of all property keys defined on this object.
* This includes both attributes and relationships.
* This implementation returns the union of attributeKeys,
* toOneRelationshipKeys, and toManyRelationshipKeys.
*/
public NSArray allPropertyKeys()
{
NSSet union = new NSSet();
union.addAll( attributeKeys() );
union.addAll( toOneRelationshipKeys() );
union.addAll( toManyRelationshipKeys() );
return new NSArray( (Collection) union );
}
/**
* Returns a list of all attributes defined on this object.
* Attributes are all properties that are not relationships.
* This implementation retrieves the keys from the class
* description.
*/
public NSArray attributeKeys()
{
return classDescription().attributeKeys();
}
//void awakeFromClientUpdate(EOEditingContext aContext)
/**
* Called when the object has first been fetched into the
* specified editing context. This implementation calls
* awakeObjectFromFetch on the class description.
*/
public void awakeFromFetch(EOEditingContext anEditingContext)
{
classDescription().awakeObjectFromFetch( this, anEditingContext );
}
/**
* Called when the object has been inserted into the
* specified editing context. This implementation calls
* awakeObjectFromInsertion on the class description.
*/
public void awakeFromInsertion(EOEditingContext anEditingContext)
{
classDescription().awakeObjectFromInsertion( this, anEditingContext );
}
/**
* Returns a Map representing the delta of the current state
* from the state represented in the specified snapshot.
* The result will contain only the keys that have changed
* and their values. Relationship keys will map to an NSArray
* that contains an NSArray of added objects and an NSArray
* of removed objects, in that order.
*/
public NSDictionary changesFromSnapshot(NSDictionary snapshot)
{
throw new WotonomyException( "Not implemented yet." );
}
/**
* Returns a class description for this object.
* Calls EOClassDescription.classDescriptionForClass.
*/
public EOClassDescription classDescription()
{
if ( classDescription == null )
{
classDescription = EOClassDescription.classDescriptionForClass( getClass() );
if ( classDescription == null )
{
throw new WotonomyException(
"No class description found for class: " + getClass() );
}
}
return classDescription;
}
/**
* Returns a class description for the object at the
* other end of the specified relationship key.
* This implementation calls to the classDescription.
*/
public EOClassDescription classDescriptionForDestinationKey(String aKey)
{
return classDescription().classDescriptionForDestinationKey( aKey );
}
/**
* Clears all property values for this object.
* This method is called to clean-up an object that
* will no longer be used, and implementations should
* ensure that all references are set to null to
* prevent problems with garbage-collection.
*/
public void clearProperties()
{
//FIXME: clear properties here
}
/**
* Returns the delete rule constant defined on EOClassDescription
* for the relationship defined by the specified key.
* This implementation calls to the classDescription.
*/
public int deleteRuleForRelationshipKey(String aRelationshipKey)
{
return classDescription().deleteRuleForRelationshipKey( aRelationshipKey );
}
/**
* Returns the editing context in which this object is registered.
*/
public EOEditingContext editingContext()
{
return editingContext;
}
/**
* Returns the name of the entity that this object represents.
*/
public String entityName()
{
return classDescription().entityName();
}
/**
* Returns a String containing all property keys and values for
* this object. Relationships should be represented by calling
* eoShallowDescription() on the object.
*/
public String eoDescription()
{
throw new WotonomyException( "Not implemented yet." );
}
/**
* Returns a String containing all attribute keys and values for
* this object. Relationships are not included.
*/
public String eoShallowDescription()
{
throw new WotonomyException( "Not implemented yet." );
}
/**
* Returns the key used to reference this object on the
* object at the other end of the specified relationship.
* This implementation calls to the class description.
*/
public String inverseForRelationshipKey(String aRelationshipKey)
{
return classDescription().inverseForRelationshipKey( aRelationshipKey );
}
//Object invokeRemoteMethod(
// String aMethodName, Class[] aTypeArray Object[] anArgumentArray)
/**
* Returns whether the specified relationship key represents
* a to-many relationship.
*/
public boolean isToManyKey(String aKey)
{
return toManyRelationshipKeys().containsObject( aKey );
}
/**
* Returns whether the objects at the other end of the specified
* relationship should be deleted when this object is deleted.
* This implementation calls to the class description.
*/
public boolean ownsDestinationObjectsForRelationshipKey(String aKey)
{
return classDescription().ownsDestinationObjectsForRelationshipKey( aKey );
}
//void prepareValuesForClient()
/**
* Called to perform the delete propagation for this object
* on the specified editing context. All relationships
* should be processed according to their corresponding
* delete rule.
* This implementation calls to the class description.
*/
public void propagateDeleteWithEditingContext(EOEditingContext aContext)
{
classDescription().propagateDeleteForObject( this, aContext );
}
/**
* Applies the changes from the specified snapshot to
* this object.
* @see #changesFromSnapshot(NSDictionary)
*/
public void reapplyChangesFromDictionary(NSDictionary aDeltaSnapshot)
{
throw new WotonomyException( "Not implemented yet." );
}
/**
* Returns a snapshot of the current state of this object.
* All property keys are mapped to their values; nulls are
* represented by NSNull.
*/
public NSDictionary snapshot()
{
throw new WotonomyException( "Not implemented yet." );
}
/**
* Returns a List of the to-many relationship keys
* for this object.
* This implementation calls to the class description.
*/
public NSArray toManyRelationshipKeys()
{
return classDescription().toManyRelationshipKeys();
}
/**
* Returns a List of the to-one relationship keys
* for this object.
* This implementation calls to the class description.
*/
public NSArray toOneRelationshipKeys()
{
return classDescription().toOneRelationshipKeys();
}
/**
* Applies the specified snapshot to this object,
* converting NSNulls to null and calling
* takeStoredValueForKey for each key in the Map.
*/
public void updateFromSnapshot(NSDictionary aSnapshot)
{
throw new WotonomyException( "Not implemented yet." );
}
/**
* Returns a short, stateful string representation
* of this object.
* This implementation calls to the class description.
*/
public String userPresentableDescription()
{
return classDescription().userPresentableDescriptionForObject( this );
}
/**
* This method should be called by each setter method
* on this object before changes are made to the
* object's internal state. This implementation calls
* EOObserverCenter.notifyObserversObjectWillChange( this ),
*/
public void willChange()
{
EOObserverCenter.notifyObserversObjectWillChange( this );
}
// interface EOKeyValueCoding
/**
* Returns the value for the specified property.
* If the property does not exist, this method should
* call handleQueryWithUnboundKey.
*/
public Object valueForKey( String aKey )
{
return EOKeyValueCodingSupport.valueForKey( this, aKey );
}
/**
* Sets the property to the specified value.
* If the property does not exist, this method should
* call handleTakeValueForUnboundKey.
* If the property is of a type that cannot allow
* null (e.g. primitive types) and aValue is null,
* this method should call unableToSetNullForKey.
*/
public void takeValueForKey( Object aValue, String aKey )
{
EOKeyValueCodingSupport.takeValueForKey( this, aValue, aKey );
}
/**
* Returns the value for the private field that
* corresponds to the specified property.
*/
public Object storedValueForKey( String aKey )
{
return EOKeyValueCodingSupport.storedValueForKey( this, aKey );
}
/**
* Sets the the private field that corresponds to the
* specified property to the specified value.
*/
public void takeStoredValueForKey( Object aValue, String aKey )
{
EOKeyValueCodingSupport.takeStoredValueForKey( this, aValue, aKey );
}
/**
* Called by valueForKey when the specified key is
* not found on this object. Implementing classes
* should handle the specified value or otherwise
* throw an exception.
*/
public Object handleQueryWithUnboundKey( String aKey )
{
return EOKeyValueCodingSupport.handleQueryWithUnboundKey( this, aKey );
}
/**
* Called by takeValueForKey when the specified key
* is not found on this object. Implementing classes
* should handle the specified value or otherwise
* throw an exception.
*/
public void handleTakeValueForUnboundKey( Object aValue, String aKey )
{
EOKeyValueCodingSupport.handleTakeValueForUnboundKey( this, aValue, aKey );
}
/**
* Called by takeValueForKey when the type of the
* specified key is not allowed to be null, as is
* the case with primitive types. Implementing
* classes should handle this case appropriately
* or otherwise throw an exception.
*/
public void unableToSetNullForKey( String aKey )
{
EOKeyValueCodingSupport.unableToSetNullForKey( this, aKey );
}
// interface EOKeyValueCodingAdditions
/**
* Returns the value for the specified key path, which is
* a series of keys delimited by ".", for example:
* "createTime.year.length".
*/
public Object valueForKeyPath( String aKeyPath )
{
throw new WotonomyException( "Not implemented yet." );
}
/**
* Sets the value for the specified key path, which is
* a series of keys delimited by ".", for example:
* "createTime.year.length".
* The value is set for the last object referenced by
* the key path.
*/
public void takeValueForKeyPath( Object aValue, String aKeyPath )
{
throw new WotonomyException( "Not implemented yet." );
}
/**
* Returns a Map of the specified keys to their values,
* each of which might be obtained by calling valueForKey.
*/
public NSDictionary valuesForKeys( List aKeyList )
{
return KeyValueCodingUtilities.valuesForKeys( this, aKeyList );
}
/**
* Takes the keys from the specified map as properties
* and applies the corresponding values, each of which
* might be set by calling takeValueForKey.
*/
public void takeValuesFromDictionary( Map aMap )
{
KeyValueCodingUtilities.takeValuesFromDictionary( this, aMap );
}
// interface EOFaulting
/**
* Called by EOFaultHandler to prepare the object to be turned into a fault.
*/
public void clearFault()
{
throw new WotonomyException( "Not implemented yet." );
}
/**
* Returns this object's EOFaultHandler.
*/
public EOFaultHandler faultHandler()
{
throw new WotonomyException( "Not implemented yet." );
}
/**
* Returns whether this object is currently a fault.
* Returns true if this object has not yet retrieved any values.
*/
public boolean isFault()
{
throw new WotonomyException( "Not implemented yet." );
}
/**
* Turns this object into a fault using the specified fault handler.
*/
public void turnIntoFault( EOFaultHandler aFaultHandler )
{
throw new WotonomyException( "Not implemented yet." );
}
/**
* Called to completely fire the fault, reading all attributes.
* This method may be implemented to call willRead(null).
*/
public void willRead()
{
throw new WotonomyException( "Not implemented yet." );
}
/**
* Called to fire the fault for the specified key.
* The fault manager is required to populate the specified key
* with a value, and may populate any or all of the other values
* on this object. A null key will populate all values on the object.
* NOTE: This method is not part of the specification.
*/
public void willRead( String aKey )
{
throw new WotonomyException( "Not implemented yet." );
}
// interface EODeferredFaulting
/**
* Returns a fault for the specified deferred fault.
*/
public Object willReadRelationship( Object anObject )
{
throw new WotonomyException( "Not implemented yet." );
}
// interface EORelationshipManipulation
/**
* Adds the specified object to the relationship on this
* object specified by the key. For to-one relationships,
* this operation is the same as valueForKey.
*/
public void addObjectToPropertyWithKey(
Object anObject, String aKey )
{
throw new WotonomyException( "Not implemented yet." );
}
/**
* Removes the specified object from the relationship on
* this object specified by the key. For to-one relationships,
* this operation is the same as takeValueForKey with a null
* value.
*/
public void removeObjectFromPropertyWithKey(
Object anObject, String aKey )
{
throw new WotonomyException( "Not implemented yet." );
}
/**
* As addObjectToProperty with key, but also performs the
* reciprocal operation on the other side of the relationship.
*/
public void addObjectToBothSidesOfRelationshipWithKey(
EORelationshipManipulation anObject, String aKey )
{
throw new WotonomyException( "Not implemented yet." );
}
/**
* As removeObjectFromPropertyWithKey with key, but also performs the
* reciprocal operation on the other side of the relationship.
*/
public void removeObjectFromBothSidesOfRelationshipWithKey(
EORelationshipManipulation anObject, String aKey )
{
throw new WotonomyException( "Not implemented yet." );
}
// interface EOValidation
/**
* Validates this object for delete.
* Throws an exception if this object cannot be deleted.
* This implementation calls to the class description.
*/
public void validateForDelete()
{
classDescription().validateObjectForDelete( this );
}
/**
* Validates this object for insertion into the external store.
* Throws an exception if this object cannot be inserted.
* Validations here should be specific to insertion.
* This implementation calls validateForSave().
*/
public void validateForInsert()
{
validateForSave();
}
/**
* Validates this object for a commit to the external store.
* Throws an exception if this object cannot be committed.
* Validations here are not specific to either inserts or updates.
* This implementation calls to the class description.
*/
public void validateForSave()
{
classDescription().validateObjectForSave( this );
}
/**
* Validates this object for update to the external store.
* Throws an exception if this object cannot be updated.
* Validations here should be specific to updates.
* This implementation calls validateForSave().
*/
public void validateForUpdate()
{
validateForSave();
}
}
/*
* $Log$
* Revision 1.2 2006/02/16 16:47:14 cgruber
* Move some classes in to "internal" packages and re-work imports, etc.
*
* Also use UnsupportedOperationExceptions where appropriate, instead of WotonomyExceptions.
*
* Revision 1.1 2006/02/16 13:19:57 cgruber
* Check in all sources in eclipse-friendly maven-enabled packages.
*
* Revision 1.3 2001/12/06 16:42:29 mpowers
* Added appropriate constructor.
*
* Revision 1.2 2001/11/24 17:37:29 mpowers
* Implemented static methods.
*
* Revision 1.1 2001/11/17 17:18:15 mpowers
* Initial implementation of EOCustomObject.
*
*
*/
|