<commit_before>/*
	Copyright (C) 2010 <NAME>

	Author:  <NAME> <<EMAIL>>, 
	         <NAME> <<EMAIL>>
	Date:  November 2010
	License:  Modified BSD  (see COPYING)
 */

#import <Foundation/Foundation.h>
#import <EtoileFoundation/EtoileFoundation.h>
#import <CoreObject/COQuery.h>

@class COEditingContext, CORevision, COCommitTrack;

/**
 * Working copy of an object, owned by an editing context.
 * Relies on the context to resolve fault references to other COObjects.
 *
 * You should use ETUUID's to refer to objects outside of the context
 * of a COEditingContext.
 *
 * @section Initialization
 *
 * A core object can be instantiated in one or two steps by using respectively:
 *
 * <list>
 * <item>-[COEditingContext insertObjectWithEntityName:] or similar 
 * COEditingContext methods</item>
 * <item>-init and -becomePersistentInContext:rootObject:</item>
 * </list>
 *
 * In both cases, -init is used to initialize the object.<br />
 * With -insertObjectWithEntityName:, the object becomes persistent immediately.
 * However in the second case, the object doesn't become persistent until 
 * -becomePersistentInContext:rootObject: is called. You can use this approach   
 * to instantiate transient objects or to mix transient and persistent instances.
 *
 * When writing a COObject subclass, -init can be overriden to initialize the 
 * the subclass properties. The designated initializer rule remains valid in 
 * a COObject class hierarchy. See the example in -init documentation.
 *
 * @section Persistency
 *
 * Whan an object becomes persistent, you invoke 
 * -becomePersistentInContext:rootObject: or the editing context does it. 
 * Hence -becomePersistentInContext:rootObject: can be overriden to udpate   
 * or initialize properties at persistency time. For example, 
 * -becomePersistentInContext:rootObject: can be propagated to the instance 
 * relationships to transively turn a transient object graph into a persistent 
 * one.
 */
@interface COObject : NSObject <NSCopying, COObjectMatching>
{
	@package
	ETEntityDescription *_entityDescription;
	ETUUID *_uuid;
	COEditingContext *_context; // weak reference
	COObject *_rootObject; // weak reference
	NSMapTable *_variableStorage;
	BOOL _isIgnoringDamageNotifications;
	BOOL _isIgnoringRelationshipConsistency;
	BOOL _inDescription; // FIXME: remove; only for debugging
	BOOL _isInitialized;
}

/** @taskunit Initialization */

/** <init />
 * Initializes and returns a non-persistent object.
 *
 * The receiver can be made persistent later, by inserting it into an editing 
 * context with -becomePersistentInContext:rootObject:.<br />
 * Its identity will remain stable once persistency has been enabled, because 
 * this initializer gives a UUID to the object.
 *
 * You should use insertion methods provided by COEditingContext to create 
 * objects that are immediately persistent. Take note that these insertion 
 * methods use -init to initialize the object.
 *
 * For the initializer in subclasses, you must never create entity objects that 
 * correspond to relationships with insertion methods provided by 
 * COEditingContext (this ensures your subclasses support both immediate and 
 * late persistency with -becomePersistentInContext:rootObject:). For example, 
 * you must write:
 *
 * <example>
 * - (id)init
 * {
 *     SUPERINIT;
 *     // Don't instantiate the group with -[COEditingContext insertObjectWithEntityName:]
 *     personGroup = [[COGroup alloc] init];
 *     return self;
 * }
 * </example>
 */
- (id)init;

/** 
 * Makes the receiver persistent by inserting it into the given editing context.
 *
 * If the root object argument is the receiver itself, then the receiver becomes 
 * a root object (or a persistent root from the storage standpoint).
 *
 * Raises an exception if any argument is nil.<br />
 * When the root object is not the receiver or doesn't belong to the editing 
 * context, raises an exception too.
 */
- (void)becomePersistentInContext: (COEditingContext *)aContext 
                       rootObject: (COObject *)aRootObject;
- (id)copyWithZone: (NSZone *)aZone usesModelDescription: (BOOL)usesModelDescription;

/** taskunit Persistency Attributes */

/** 
 * Returns the UUID that uniquely identifies the persistent object that 
 * corresponds to the receiver.
 *
 * A persistent object has a single instance per editing context.
 */
- (ETUUID *)UUID;
- (ETEntityDescription *)entityDescription;
/** 
 * Returns the editing context when the receiver is persistent, otherwise  
 * returns nil.
 */
- (COEditingContext *)editingContext;
/** 
 * Returns the root object when the receiver is persistent, otherwise returns nil.
 *
 * When the receiver is persistent, returns either self or the root object that 
 * encloses the receiver as an embedded object.
 *
 * See also -isRoot.
 */
- (COObject *)rootObject;
/**
 * Returns NO when the object is loaded, otherwise returns YES.
 * 
 * When YES is returned, the receiver class is set to +faultClass.
 *
 * You can send a message that COFault doesn't implement to unfault the object 
 * (in other words, load the instance variable values).
 */
- (BOOL)isFault;
/**
 * Returns whether the receiver is saved on the disk.
 *
 * When persistent, the receiver has both a valid editing context and root object.
 */
- (BOOL)isPersistent;
/** 
 * Returns whether the receiver is a root object that can enclose embedded 
 * objects.
 *
 * Embedded or non-persistent objects returns NO.
 *
 * See also -rootObject.
 */
- (BOOL)isRoot;
- (BOOL)isDamaged;

/** @taskunit History Attributes */

/**
 * Return the revision of this object in the editing context.
 */
- (CORevision *)revision;
/**
 * Returns the commit track for this object.
 */
- (COCommitTrack *)commitTrack;

/** @taskunit Contained Objects based on the Metamodel */

/**
 * Returns an array containing all COObjects "strongly contained" by this one.
 * This means objects which are values for "composite" properties.
 */
- (NSArray *)allStronglyContainedObjects;
- (NSArray *)allStronglyContainedObjectsIncludingSelf;
- (NSSet *)allInnerObjectsIncludingSelf;

/** @taskunit Basic Properties */

/**
 * The object name.
 */
@property (nonatomic, retain) NSString *name;

/**
 * <override-dummy />
 * Returns the object identifier.
 *
 * By default, returns -name which can be nil and might not be unique even 
 * within a COCollection content.
 *
 * Can be overriden to return a custom string.
 */
- (NSString *)identifier;
/**
 * Returns the last time the receiver changes were committed.
 *
 * The returned date is the last root object revision date. See -[CORevision date].
 *
 * Can be more recent than the present receiver revision (see -revision).
 */
- (NSDate *)modificationDate;
/**
 * Returns the first time the receiver changes were committed.
 *
 * The returned date is the first root object revision date. See -[CORevision date].
 */
- (NSDate *)creationDate;
/**
 * Returns -name.
 */
- (NSString *)displayName;
/**
 * Returns the groups to which the receiver belongs to.
 *
 * Groups are COGroup or subclass instances.
 *
 * See also -tags.
 */
- (NSArray *)parentGroups;
/**
 * Returns the tags attached to the receiver. 
 *
 * This method returns a -parentGroups subset. Groups which don't belong to 
 * -[COEditingContext tagGroup] are filtered out.
 */
- (NSArray *)tags;

/** @taskunit Property-Value Coding */

/** 
 * Returns the properties declared in the receiver entity description.
 *
 * See also -entityDescription and -persistentPropertyNames.
 */
- (NSArray *)propertyNames;
/** 
 * Returns the persistent properties declared in the receiver entity description.
 *
 * The returned array contains the property descriptions which replies YES to 
 * -[ETPropertyDescription isPersistent].
 *
 * See also -entityDescription and -propertyNames.
 */
- (NSArray *)persistentPropertyNames;
/**
 * Returns the property value.
 *
 * When the property is not declared in the entity description, raises an 
 * NSInvalidArgumentException.
 *
 * See also -setValue:forProperty:.
 */
- (id)valueForProperty: (NSString *)key;
/**
 * Sets the property value.
 *
 * When the property is not declared in the entity description, raises an 
 * NSInvalidArgumentException.
 *
 * See also -valueForProperty:.
 */
- (BOOL)setValue: (id)value forProperty: (NSString *)key;

/** @taskunit Direct Access to the Variable Storage */

/**
 * Returns a value from the variable storage.
 *
 * Can be used to read a property with no instance variable.
 *
 * This is a low-level method whose use should be restricted to serialization 
 * code and accessors that expose properties with no related instance variable.
 */
- (id)primitiveValueForKey: (NSString *)key;
/**
 * Sets a value in the variable storage.
 *
 * Can be used to write a property with no instance variable.
 *
 * This is a low-level method whose use should be restricted to serialization 
 * code and accessors that expose properties with no related instance variable.
 *
 * This method involves no integrity check or relationship consistency update.
 * It won't invoke -willChangeValueForProperty: and -didChangeValueForProperty: 
 * (or -willChangeValueForKey: and -didChangeValueForKey:).
 */
- (void)setPrimitiveValue: (id)value forKey: (NSString *)key;

/** @taskunit Notifications to be called by Accessors */

/**
 * Tells the receiver that the value of the property (transient or persistent) 
 * is about to change.
 *
 * By default, limited to calling -willChangeValueForKey:.
 *
 * Can be overriden, but the superclass implementation must be called.
 */
- (void)willChangeValueForProperty: (NSString *)key;
/**
 * Tells the receiver that the value of the property (transient or persistent)
 * has changed. 
 *
 * By default, notifies the editing context about the receiver change and 
 * triggers Key-Value-Observing notifications by calling -didChangeValueForKey:.
 *
 * Can be overriden, but the superclass implementation must be called.
 */
- (void)didChangeValueForProperty: (NSString *)key;
- (void)didChangeValueForProperty: (NSString *)key oldValue: (id)oldValue;

/** @taskunit Collection Mutation with Integrity Check */

/** 
 * Checks the insertion and the object that goes along respect the metamodel 
 * constraints, then calls -insertObject:atIndex:hint: on the collection bound 
 * to the property.<br />
 * Finally if the property is a relationship, this method updates the 
 * relationship consistency.
 *
 * See also ETCollectionMutation and -updateRelationshipConsistencyWithValue:.
 */
- (void) insertObject: (id)object atIndex: (NSUInteger)index hint: (id)hint forProperty: (NSString *)key;
/** 
 * Checks the insertion and the object that goes along respect the metamodel 
 * constraints, then calls -removeObject:atIndex:hint: on the collection bound 
 * to the property.<br />
 * Finally if the property is a relationship, this method updates the 
 * relationship consistency.
 *
 * See also ETCollectionMutation and -updateRelationshipConsistencyWithValue:. 
 */
- (void) removeObject: (id)object atIndex: (NSUInteger)index hint: (id)hint forProperty: (NSString *)key;

/** @taskunit Overridable Notifications */

/**
 * A notification that the object was created for the first time.
 *
 * Overrides this method to perform any initialisation that should be performed 
 * the very first time an object is instantiated, such as calculating and 
 * setting default values.<br />
 * The superclass implementation must be called before the subclass code.
 *
 * This method won't be called when the new instance is a fault, or when the 
 * object was loaded or reloaded with -[COEditingContext loadObject:atRevision:]. `
 * For these cases, both -awakeFromFetch and -didReload can be used.
 */
- (void)didCreate;
- (void)awakeFromFetch;
- (void)willTurnIntoFault;
- (void)didTurnIntoFault;
- (void)didReload;

/** @taskunit Object Equality */

/** Returns a hash based on the UUID. */
- (NSUInteger)hash;
/**
 * Returns whether anObject is equal to the receiver.
 *
 * Two persistent objects are equal if they share the same UUID.<br />
 * For now, returns YES even when the two object revisions don't match (this 
 * is subject to change).
 *
 * Use <code>[a isEqual: b] && ![a isTemporalInstance: b]</code> to check 
 * temporal equality. For example, when the same object is in use in multiple 
 * editing contexts simultaneously.
 *
 * See also -isTemporalInstance:.
 */
- (BOOL)isEqual: (id)anObject;
/** 
 * Returns whether anObject is a temporal instance of the receiver. 
 *
 * Two persistent objects are temporal instances of each other if they share the 
 * same UUID but differ by their revision. 
 *
 * See also -isEqual:.
 */
- (BOOL) isTemporalInstance: (id)anObject;
<commit_msg>Wrote documentation about Faulting and Reloading<commit_after>/*
	Copyright (C) 2010 <NAME>

	Author:  <NAME> <<EMAIL>>, 
	         <NAME> <<EMAIL>>
	Date:  November 2010
	License:  Modified BSD  (see COPYING)
 */

#import <Foundation/Foundation.h>
#import <EtoileFoundation/EtoileFoundation.h>
#import <CoreObject/COQuery.h>

@class COEditingContext, CORevision, COCommitTrack;

/**
 * Working copy of an object, owned by an editing context.
 * Relies on the context to resolve fault references to other COObjects.
 *
 * You should use ETUUID's to refer to objects outside of the context
 * of a COEditingContext.
 *
 * @section Initialization
 *
 * A core object can be instantiated in one or two steps by using respectively:
 *
 * <list>
 * <item>-[COEditingContext insertObjectWithEntityName:] or similar 
 * COEditingContext methods</item>
 * <item>-init and -becomePersistentInContext:rootObject:</item>
 * </list>
 *
 * In both cases, -init is used to initialize the object.<br />
 * With -insertObjectWithEntityName:, the object becomes persistent immediately.
 * However in the second case, the object doesn't become persistent until 
 * -becomePersistentInContext:rootObject: is called. You can use this approach   
 * to instantiate transient objects or to mix transient and persistent instances.
 *
 * When writing a COObject subclass, -init can be overriden to initialize the 
 * the subclass properties. See the example in -init documentation.<br />
 * The designated initializer rule remains valid in a COObject class hierarchy, 
 * but -init must work correctly too (it must not return nil or a wrongly 
 * initialized instance), usually you have to override it to call the designated 
 * initializer. And secondary initializers must return valid instances or nil. 
 *
 * @section Persistency
 *
 * Whan an object becomes persistent, you invoke 
 * -becomePersistentInContext:rootObject: or the editing context does it. 
 * Hence -becomePersistentInContext:rootObject: can be overriden to udpate   
 * or initialize properties at persistency time. For example, 
 * -becomePersistentInContext:rootObject: can be propagated to the instance 
 * relationships to transively turn a transient object graph into a persistent 
 * one.
 *
 * @section Writing Accessors
 *
 * You can use Property-Value Coding to read and write properties. However 
 * implementing accessors can improve readability, type checking etc. For 
 * most attributes, we have a basic accessor pattern. For Multivalued properties 
 * (relationships or collection-based attributes), the basic accessor pattern 
 * won't work correctly.
 *
 * <strong>Basic Accessor Pattern</strong/>
 *
 * <example>
 * - (void)name
 * {
 *     // When no ivar is provided, you can use the variable storage as below
 *     // return [self primitiveValueForKey: @"name"];
 *     return name;
 * }
 *
 * - (void)setName: (NSString *)aName
 * {
 *     [self willChangeValueForProperty: @"name"];
 *     // When no ivar is provided, you can use the variable storage as below
 *     // [self setPrimitiveValue: aName: forKey: @"name"];
 *     ASSIGN(name, aName);
 *     [self didChangeValueForProperty: @"name"];
 * }
 * </example>
 *
 * <strong>Multivalued Accessor Pattern</strong/>
 *
 * The example below is based on a COObject subclass using a<em>names</em> 
 * instance variable. If the value is stored in the variable storage, the 
 * example must be adjusted to use -primitiveValueForKey: and 
 * -setPrimitiveValue:forKey:.<br />
 * -removeObject:atIndex:hint:forProperty: and 
 * -insertObject:atIndex:hint:forProperty: use the instance variable whose 
 * name matches the property (based on Key-Value Coding ivar search rules), or 
 * resort the variable storage when there is no matching ivar.
 *
 * <example>
 *
 * - (void)names
 * {
 *     return names;
 * }
 *
 * - (void)addName: (NSString *)aName
 * {
 *     [self insertObject: aName: atIndex: ETUndeterminedIndex hint: nil forProperty: @"names"];
 * }
 *
 * - (void)removeName: (NSString *)aName
 * {
 *     [self removeObject: aName: atIndex: ETUndeterminedIndex hint: nil forProperty: @"names"];
 * }
 *
 * // Direct setters are rare, but nonetheless it is possible to write one as below...
 * - (void)setNames: (id <ETCollection>)newNames
 * {
 *     id oldCollection = [[names mutableCopy] autorelease];
 *     [self willChangeValueForProperty: @"names"];
 *     ASSIGN(names, newNames);
 *     [self didChangeValueForProperty: @"names" oldValue: oldCollection];
 * }
 * </example>
 *
 * @section Notifications
 *
 * To better control persistency, -awakeFromFetch, -didReload, -willTurnIntoFault
 *
 * @section Serialization
 *
 * @section Faulting and Reloading
 *
 * When a core object not present in memory but exists in the store, 
 * -[COEditingContext objectWithUUID:] uses -[COEditingContext loadObject:] to 
 * bring the object back in memory. All the attribute values are immediately 
 * brought back, however relationships are not loaded immediately. For example, 
 * if a relationship consists of multiple objects that belong to an array, 
 * CoreObject doesn't load the real objects missing in memory, but put a COFault 
 * object in the array for each real object not yet loaded.<br /> 
 * Faults are core objects whose state remain unitialized until a message is 
 * sent to them.
 *
 * Each fault has the same UUID than the core object it stands for. As a result, 
 * when requesting multiple times the same object not present in memory, 
 * the same fault instance is returned every time by 
 * -[COEditingContext objectWithUUID:].
 *
 * When an object that was previously a fault is loaded, then once the 
 * attribute values have been deserialized, -awakeFromFetch is sent to the 
 * object to let it update its state before being used. You can thus override 
 * -awakeFromFetch to recreate transient properties, recompute correct property 
 * values based on the deserialized values, update relationships etc.<br />
 * Don't forget to call the superclass implementation first.<br />
 * In addition, navigating a root object history results in -awakeFromFetch 
 * being sent to each object loaded to a new revision in the object graph (not 
 * yet the case), rather being turned back into a fault. When every object in 
 * the object graph has been reloaded or turned back into fault, -didReload is 
 * sent to the root object.
 *
 * For various reasons such as memory usage or root objects being reloaded to  
 * some revision, core objects can be turned back into faults (not yet supported).
 * Before unloading an object, -willTurnIntoFault is called on it, then the 
 * object is unloaded (property values are released and reset to a null value), 
 * in the end COFault becomes its class and the resulting fault receives 
 * the message -didTurnIntoFault.
 */
@interface COObject : NSObject <NSCopying, COObjectMatching>
{
	@package
	ETEntityDescription *_entityDescription;
	ETUUID *_uuid;
	COEditingContext *_context; // weak reference
	COObject *_rootObject; // weak reference
	NSMapTable *_variableStorage;
	BOOL _isIgnoringDamageNotifications;
	BOOL _isIgnoringRelationshipConsistency;
	BOOL _inDescription; // FIXME: remove; only for debugging
	BOOL _isInitialized;
}

/** @taskunit Initialization */

/** <init />
 * Initializes and returns a non-persistent object.
 *
 * The receiver can be made persistent later, by inserting it into an editing 
 * context with -becomePersistentInContext:rootObject:.<br />
 * Its identity will remain stable once persistency has been enabled, because 
 * this initializer gives a UUID to the object.
 *
 * You should use insertion methods provided by COEditingContext to create 
 * objects that are immediately persistent. Take note that these insertion 
 * methods use -init to initialize the object.
 *
 * For the initializer in subclasses, you must never create entity objects that 
 * correspond to relationships with insertion methods provided by 
 * COEditingContext (this ensures your subclasses support both immediate and 
 * late persistency with -becomePersistentInContext:rootObject:). For example, 
 * you must write:
 *
 * <example>
 * - (id)init
 * {
 *     SUPERINIT;
 *     // Don't instantiate the group with -[COEditingContext insertObjectWithEntityName:]
 *     personGroup = [[COGroup alloc] init];
 *     return self;
 * }
 * </example>
 */
- (id)init;

/** 
 * Makes the receiver persistent by inserting it into the given editing context.
 *
 * If the root object argument is the receiver itself, then the receiver becomes 
 * a root object (or a persistent root from the storage standpoint).
 *
 * Raises an exception if any argument is nil.<br />
 * When the root object is not the receiver or doesn't belong to the editing 
 * context, raises an exception too.
 */
- (void)becomePersistentInContext: (COEditingContext *)aContext 
                       rootObject: (COObject *)aRootObject;
- (id)copyWithZone: (NSZone *)aZone usesModelDescription: (BOOL)usesModelDescription;

/** taskunit Persistency Attributes */

/** 
 * Returns the UUID that uniquely identifies the persistent object that 
 * corresponds to the receiver.
 *
 * A persistent object has a single instance per editing context.
 */
- (ETUUID *)UUID;
- (ETEntityDescription *)entityDescription;
/** 
 * Returns the editing context when the receiver is persistent, otherwise  
 * returns nil.
 */
- (COEditingContext *)editingContext;
/** 
 * Returns the root object when the receiver is persistent, otherwise returns nil.
 *
 * When the receiver is persistent, returns either self or the root object that 
 * encloses the receiver as an embedded object.
 *
 * See also -isRoot.
 */
- (COObject *)rootObject;
/**
 * Returns NO when the object is loaded, otherwise returns YES.
 * 
 * When YES is returned, the receiver class is set to +faultClass.
 *
 * You can send a message that COFault doesn't implement to unfault the object 
 * (in other words, load the instance variable values).
 */
- (BOOL)isFault;
/**
 * Returns whether the receiver is saved on the disk.
 *
 * When persistent, the receiver has both a valid editing context and root object.
 */
- (BOOL)isPersistent;
/** 
 * Returns whether the receiver is a root object that can enclose embedded 
 * objects.
 *
 * Embedded or non-persistent objects returns NO.
 *
 * See also -rootObject.
 */
- (BOOL)isRoot;
- (BOOL)isDamaged;

/** @taskunit History Attributes */

/**
 * Return the revision of this object in the editing context.
 */
- (CORevision *)revision;
/**
 * Returns the commit track for this object.
 */
- (COCommitTrack *)commitTrack;

/** @taskunit Contained Objects based on the Metamodel */

/**
 * Returns an array containing all COObjects "strongly contained" by this one.
 * This means objects which are values for "composite" properties.
 */
- (NSArray *)allStronglyContainedObjects;
- (NSArray *)allStronglyContainedObjectsIncludingSelf;
- (NSSet *)allInnerObjectsIncludingSelf;

/** @taskunit Basic Properties */

/**
 * The object name.
 */
@property (nonatomic, retain) NSString *name;

/**
 * <override-dummy />
 * Returns the object identifier.
 *
 * By default, returns -name which can be nil and might not be unique even 
 * within a COCollection content.
 *
 * Can be overriden to return a custom string.
 */
- (NSString *)identifier;
/**
 * Returns the last time the receiver changes were committed.
 *
 * The returned date is the last root object revision date. See -[CORevision date].
 *
 * Can be more recent than the present receiver revision (see -revision).
 */
- (NSDate *)modificationDate;
/**
 * Returns the first time the receiver changes were committed.
 *
 * The returned date is the first root object revision date. See -[CORevision date].
 */
- (NSDate *)creationDate;
/**
 * Returns -name.
 */
- (NSString *)displayName;
/**
 * Returns the groups to which the receiver belongs to.
 *
 * Groups are COGroup or subclass instances.
 *
 * See also -tags.
 */
- (NSArray *)parentGroups;
/**
 * Returns the tags attached to the receiver. 
 *
 * This method returns a -parentGroups subset. Groups which don't belong to 
 * -[COEditingContext tagGroup] are filtered out.
 */
- (NSArray *)tags;

/** @taskunit Property-Value Coding */

/** 
 * Returns the properties declared in the receiver entity description.
 *
 * See also -entityDescription and -persistentPropertyNames.
 */
- (NSArray *)propertyNames;
/** 
 * Returns the persistent properties declared in the receiver entity description.
 *
 * The returned array contains the property descriptions which replies YES to 
 * -[ETPropertyDescription isPersistent].
 *
 * See also -entityDescription and -propertyNames.
 */
- (NSArray *)persistentPropertyNames;
/**
 * Returns the property value.
 *
 * When the property is not declared in the entity description, raises an 
 * NSInvalidArgumentException.
 *
 * See also -setValue:forProperty:.
 */
- (id)valueForProperty: (NSString *)key;
/**
 * Sets the property value.
 *
 * When the property is not declared in the entity description, raises an 
 * NSInvalidArgumentException.
 *
 * See also -valueForProperty:.
 */
- (BOOL)setValue: (id)value forProperty: (NSString *)key;

/** @taskunit Direct Access to the Variable Storage */

/**
 * Returns a value from the variable storage.
 *
 * Can be used to read a property with no instance variable.
 *
 * This is a low-level method whose use should be restricted to serialization 
 * code and accessors that expose properties with no related instance variable.
 */
- (id)primitiveValueForKey: (NSString *)key;
/**
 * Sets a value in the variable storage.
 *
 * Can be used to write a property with no instance variable.
 *
 * This is a low-level method whose use should be restricted to serialization 
 * code and accessors that expose properties with no related instance variable.
 *
 * This method involves no integrity check or relationship consistency update.
 * It won't invoke -willChangeValueForProperty: and -didChangeValueForProperty: 
 * (or -willChangeValueForKey: and -didChangeValueForKey:).
 */
- (void)setPrimitiveValue: (id)value forKey: (NSString *)key;

/** @taskunit Notifications to be called by Accessors */

/**
 * Tells the receiver that the value of the property (transient or persistent) 
 * is about to change.
 *
 * By default, limited to calling -willChangeValueForKey:.
 *
 * Can be overriden, but the superclass implementation must be called.
 */
- (void)willChangeValueForProperty: (NSString *)key;
/**
 * Tells the receiver that the value of the property (transient or persistent)
 * has changed. 
 *
 * By default, notifies the editing context about the receiver change and 
 * triggers Key-Value-Observing notifications by calling -didChangeValueForKey:.
 *
 * Can be overriden, but the superclass implementation must be called.
 */
- (void)didChangeValueForProperty: (NSString *)key;
- (void)didChangeValueForProperty: (NSString *)key oldValue: (id)oldValue;

/** @taskunit Collection Mutation with Integrity Check */

/** 
 * Checks the insertion and the object that goes along respect the metamodel 
 * constraints, then calls -insertObject:atIndex:hint: on the collection bound 
 * to the property.<br />
 * Finally if the property is a relationship, this method updates the 
 * relationship consistency.
 *
 * See also ETCollectionMutation and -updateRelationshipConsistencyWithValue:.
 */
- (void)insertObject: (id)object atIndex: (NSUInteger)index hint: (id)hint forProperty: (NSString *)key;
/** 
 * Checks the insertion and the object that goes along respect the metamodel 
 * constraints, then calls -removeObject:atIndex:hint: on the collection bound 
 * to the property.<br />
 * Finally if the property is a relationship, this method updates the 
 * relationship consistency.
 *
 * See also ETCollectionMutation and -updateRelationshipConsistencyWithValue:. 
 */
- (void)removeObject: (id)object atIndex: (NSUInteger)index hint: (id)hint forProperty: (NSString *)key;

/** @taskunit Overridable Notifications */

- (void)awakeFromFetch;
- (void)willTurnIntoFault;
- (void)didTurnIntoFault;
- (void)didReload;

/** @taskunit Object Equality */

/** Returns a hash based on the UUID. */
- (NSUInteger)hash;
/**
 * Returns whether anObject is equal to the receiver.
 *
 * Two persistent objects are equal if they share the same UUID.<br />
 * For now, returns YES even when the two object revisions don't match (this 
 * is subject to change).
 *
 * Use <code>[a isEqual: b] && ![a isTemporalInstance: b]</code> to check 
 * temporal equality. For example, when the same object is in use in multiple 
 * editing contexts simultaneously.
 *
 * See also -isTemporalInstance:.
 */
- (BOOL)isEqual: (id)anObject;
/** 
 * Returns whether anObject is a temporal instance of the receiver. 
 *
 * Two persistent objects are temporal instances of each other if they share the 
 * same UUID but differ by their revision. 
 *
 * See also -isEqual:.
 */
- (BOOL)isTemporalInstance: (id)anObject;

{'fraction_non_alphanumeric': 0.09021087381257158, 'fraction_numerical': 0.0005389746008219363, 'mean_word_length': 3.9470088318613565, 'pattern_counts': {'":': 0, '<': 78, '<?xml version=': 0, '>': 78, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7162961', 'n_tokens_mistral': 8232, 'n_tokens_neox': 7842, 'n_words': 3409}