home *** CD-ROM | disk | FTP | other *** search
- // EOClassDescription.h
- // Copyright (c) 1995, NeXT Software, Inc. All rights reserved.
- //
- // The EOClassDescription provides a mechanism for extended all classes
- // with additional meta-data useful in interacting with Enterprise Objects.
- // It also allows this meta-information to be registered at runtime by an
- // external source (E.g. an EOEntity). In effect, the EOClassDescription
- // allows EOF to add useful behavior to your EOs using information specified
- // for the EO in the EOModel file.
- //
- // For example, the Objective-C runtime allow the list of methods and instance
- // variables for a class to be queried at runtime (this is what makes possible
- // the EOKeyValueCoding protocol). However, it does not provide information on
- // whether the property of an object is an attribute or relationship, nor whether
- // that relationship points to one or many objects -- this information is not
- // available in the source code, but is available in the EOModel.
- // Note, though, that although the EOModel is the most common source of a
- // ClassDescription for a class, it is not the only one. Objects that don't
- // have a model can implement methods like "relationshipKeys" and "attributeKeys"
- // directly as instance methods, and the rest of the Framework can treat them
- // identically to EOs that have this information provided by an external model.
- //
- // In essense, the methods defined on NSObject here and the EOKeyValueCoding protocol
- // (valueForKey:, takeValue:forKey:), define the protocol for all communication
- // between the framework and your Enterprise Objects.
- //
- #import <EOControl/EOKeyValueCoding.h>
- #import <EOControl/EODefines.h>
-
- @class EOEditingContext;
- @class EOGlobalID;
-
- typedef enum
- {
- EODeleteRuleNullify = 0,
- EODeleteRuleCascade,
- EODeleteRuleDeny
- } EODeleteRule;
-
- @interface EOClassDescription : NSObject
-
- + (void)registerClassDescription:(EOClassDescription *)description forClass:(Class)class;
- // Register a classDescription object attached to the given class
-
- + (void)invalidateClassDescriptionCache;
- // should be called when a provider of class descriptions (like an EOModel)
- // has newly become available, or is going away.
-
- // Must be implemented by subclasses.
- - (NSString *)entityName;
- // Return the name of the entity served by this class description
-
- - (id)createInstanceWithEditingContext:(EOEditingContext *)editingContext globalID:(EOGlobalID *)globalID zone:(NSZone *)zone;
- // Allocates an object of the appropriate class and if the object responds
- // to "initWithEditingContext:classDescription:globalID" it invokes that
- // method, otherwise it calls the method "init". Returns an autoreleased
- // object.
-
- - (void)awakeObject:(id)object fromInsertionInEditingContext:(EOEditingContext *)editingContext;
- // Propagates inserts. New objects are created when they don't exist for any
- // relationships that propagate the primary key.
-
- - (void)awakeObject:(id)object fromFetchInEditingContext:(EOEditingContext *)editingContext;
- // Default implementation simply returns.
-
- - (void)propagateDeleteForObject:(id)object editingContext:(EOEditingContext *)editingContext;
- // Called whenever a delete needs to be propagated.
-
- - (NSArray *)attributeKeys;
- // returns an array of keys for attributes of the EOs. Attributes
- // contain data (NSNumbers, NSStrings, ...) rather than pointers
- // to other EOs.
- - (NSArray *)toOneRelationshipKeys;
- - (NSArray *)toManyRelationshipKeys;
- // These methods return arrays of keys for the relationship
- // properties of the receiver. The toManyRelationshipKeys
- // refer to properties containing NSArrays of pointers to
- // other EOs.
-
- - (NSString *)inverseForRelationshipKey:(NSString *)relationshipKey;
- // Returns the name of the relationship pointing back at the receiver
- // from the destination of the given relationship. For example,
- // [employee inverseForRelationshipKey:@"department"] might return
- // @"employees" (such that this employee would appear in
- // [[employee valueForKey:@"department"] valueForKey:@"employees"]
-
- - (EODeleteRule)deleteRuleForRelationshipKey:(NSString *)relationshipKey;
- // Returns a delete rule indicating how to treat the destination
- // of the given relationship when the receiving object is deleted.
- // For example, an Invoice might return EODeleteRuleCascade for
- // the relationship @"lineItems" (when an invoice is removed from
- // an external store, its line items should be as well).
-
- - (BOOL)ownsDestinationObjectsForRelationshipKey:(NSString *)relationshipKey;
- // Returns whether or not the objects in the destination of the given
- // relationship should be deleted if they are removed from the relationship
- // (and not added to the cooresponding relationship of another object).
- // E.g. if a LineItem is removed from an Invoice it should be deleted.
-
- - (EOClassDescription *)classDescriptionForDestinationKey:(NSString *)detailKey;
- // Returns the class description for objects at the destination of the
- // given relationship. E.g. [project classDescriptionForDestinationKey:@"leader"]
- // might return the class description for the Employee class.
-
- - (NSException *)validateValue:(id *)valueP forKey:(NSString *)key;
- // Validate value pointed to by valueP. Return nil if value is okay,
- // or an unevaluated exception containing a user-presentable
- // (localized) error message if not. May replace *valueP with a converted
- // value (e.g. the EOAttribute may convert a string to an NSNumber).
-
- - (NSException *)validateObjectForSave:(id)object;
- // Validate the object. Return nil if object is okay,
- // or an unraised exception containing a user-presentable
- // (localized) error message if not.
-
- - (NSException *)validateObjectForDelete:(id)object;
- // Check if it's posible to delete the object. Return nil if it
- // is okay, or an unevaluated exception containing a user-presentable
- // (localized) error message if not.
-
- @end
-
-
- //
- // This informal protocol defines the initialization method which may be
- // implemented by enterprise objects. If this method is not implemented by
- // an enterprise object init is used.
- //
- @interface NSObject (EOInitialization)
-
- - initWithEditingContext:(EOEditingContext *)ec classDescription:(EOClassDescription *)classDesc globalID:(EOGlobalID *)globalID;
- // Method used to initialize eo's created by the framework. If the eo
- // doesn't implement this method then init is called instead.
-
- @end
-
- @interface NSObject (EOClassDescriptionPrimitives)
-
- - (EOClassDescription *)classDescription;
- // default implementation looks for a class description registered for
- // this objects class. EOGenericRecord returns the class description
- // for its entity.
-
- - (NSString *)entityName;
- - (NSArray *)attributeKeys;
- - (NSArray *)toOneRelationshipKeys;
- - (NSArray *)toManyRelationshipKeys;
- - (NSString *)inverseForRelationshipKey:(NSString *)relationshipKey;
- - (EODeleteRule)deleteRuleForRelationshipKey:(NSString *)relationshipKey;
- - (BOOL)ownsDestinationObjectsForRelationshipKey:(NSString *)relationshipKey;
- - (EOClassDescription *)classDescriptionForDestinationKey:(NSString *)detailKey;
- // The default implementations of these methods look for a [self classDescription]
- // object and pass the method on to it.
-
- - (NSException *)validateValue:(id *)valueP forKey:(NSString *)key;
- // Default implementation calls:
- // [[self classDescription] validateValue:valueP forKey:key];
- // and, if no error, looks for an implementation of the form:
- // - (NSException *)validateSalary:(id)value
- // corresponding to the given key.
-
- - (NSException *)validateForSave;
- // called by the default implementations validateForInsert and validateForUpdate
- // The default implementation calls validateValue:forKey: for all attributes
- // and relationship keys on the object and then calls
- // [[self classDescription] validateObjectForSave:self].
- // Validation is continued for all keys, even after an initial failure. If more
- // than one validation error occurred, the exception returned contains
- // is prepared by [NSException aggregateExceptionWithExceptions:] (see below).
-
- - (NSException *)validateForDelete;
- // Validate whether object can be deleted
- // The default implementation calls [[self classDescription] validateDeleteForObject:self]
-
- - (void)awakeFromInsertionInEditingContext:(EOEditingContext *)editingContext;
- // Invoked on newly created eo's (i.e. objects that are not being initialized
- // from persistent data). The NSObject implementation of this method simply
- // calls the corresponding method on EOClassDescription.
-
- - (void)awakeFromFetchInEditingContext:(EOEditingContext *)editingContext;
- // Invoked on eo's that are created from their persistent statue. For example,
- // when data is fetched the database or some other object store. This method is
- // called after the object has been initialized and loaded with data. The
- // NSObject implementation of this method simply calls the corresponding method
- // on EOClassDescription.
-
- @end
-
- // Notifications:
- EOCONTROL_EXTERN NSString *EOClassDescriptionNeededNotification;
- // when the default implementation of classDescription is called
- // on an unregistered class, this notification is broadcast.
- // Subscribers can call [EOClassDescription registerClassDescription:forClass:]
- // to register the class description.
-
- //
- // implemented in terms of the primitives in NSObject (EOClassDescriptionPrimitives)
- //
- @interface NSObject (EOClassDescriptionExtras)
-
- - (NSDictionary *)snapshot;
- // uses values for keys to extract snapshot of attributeKeys
- // toOneRelationshipKeys, toManyRelationshipKeys
-
- - (void)updateFromSnapshot:(NSDictionary *)snapshot;
- // [self takeValuesFromDictionary:snapshot];
-
- - (BOOL)isToManyKey:(NSString *)key;
- // lookup in toManyRelationshipKeys;
-
- - (NSException *)validateForInsert;
- - (NSException *)validateForUpdate;
- // [self validateForSave]
-
- - (NSArray *)allPropertyKeys;
- // default unions attributeKeys, toOneRelationshipKeys, and toManyRelationshipKeys
-
- - (void)clearProperties;
- // Reset all properties to nil. Used to refaut an object.
- // Could be used to broke circular references
-
- - (void)propagateDeleteWithEditingContext:(EOEditingContext *)editingContext;
- // NSObject implementation of this method simply calls the corresponding method
- // on EOClassDescription.
-
- - (NSString *)eoShallowDescription;
- - (NSString *)eoDescription;
- // Useful debugging methods for printing out EOs.
- // eoShallowDescription returns a simple string with the object's className,
- // entityName and memory address.
- // eoDescription extracts all of the values from the receiver using the
- // EOKeyValueCoding protocol and asks the destination of every relationship
- // property for its eoShallowDescription. (By calling eoShallowDescription
- // on its relationships rather than eoDescription, eoDescription avoids
- // infinite recursion for cyclical graphs of objects).
- //
- // If you want eoDescription to be used on a class when you po it in gdb,
- // add the following to your EO:
- // - (NSString *)description { return [self eoDescription]; }
- // (You could also define a shortcut print macro in your ~/.gdbinit like
- // the following:
- // define peo
- // po [$arg0 eoDescription]
- // end
-
-
- @end
-
- @interface NSObject (EOKeyRelationshipManipulation)
-
- - (void)addObject:object toPropertyWithKey:(NSString *)key;
- // adds the given object to the given array property. For the key "projects",
- // the default implementation would look for method with name addToProjects:
- // and if not found would look for a property called "projects" (via valueForKey:)
- // In the latter case, the object would be added to array (if it was an
- // NSMutableArray). Otherwise a new array including the new element would be set
- // on the object.
-
- - (void)removeObject:object fromPropertyWithKey:(NSString *)key;
- // Like addObject:toPropertyWithKey:. Looks for selector of form
- // removeFromProjects:
-
- // Implemented in terms of the above, plus inverseForRelationshipKey, & isToManyKey...
- - (void)addObject:object toBothSidesOfRelationshipWithKey:(NSString *)key;
- - (void)removeObject:object fromBothSidesOfRelationshipWithKey:(NSString *)key;
- // These methods to the right thing whether the source relationship is
- // to-one or to-many, and whether the reciprocal relationship is to-one
- // or to many.
- // [eo addObject:o toBothSidesOfRelationshipWithKey:@"toOneRelName"] will
- // remove the current object set on the to-one relationship (removing its
- // back pointer) and set the new object (and set its back pointer).
-
- @end
-
- // Convenience for constructing validation exceptions
- // (with name EOValidationException)
- EOCONTROL_EXTERN NSString *EOValidationException;
-
- @interface NSException (EOValidationError)
- + (NSException *)validationExceptionWithFormat:(NSString *)format, ...;
- + (NSException *)aggregateExceptionWithExceptions:(NSArray *)subexceptions;
- // returns an exception with the name, reason, and userInfo of the first
- // exception in the array, but with the userInfo augmented with the list of
- // subexceptions under the key EOAdditionalExceptionsKey
-
- EOCONTROL_EXTERN NSString *EOAdditionalExceptionsKey;
- @end
-