


#import <Foundation/NSObject.h>
#import "MCAttribute.h"


/*
These methods pre-date NSKeyValueCoding. We keep using these because we have full control of the code and things like binder, amd, tableview controller, popup controller use these methods to access data.


*/

@interface NSObject (MCAccessors)
////////////// SWIZZLING //////////////
+ (void)swizzleRemoveObserverMethod;
- (void)_MC_removeObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath;


- (BOOL)hasAttribute:(NSString *)anAttribute;
- (CCSAttributeType) attributeTypeFor:(NSString *)anAttribute;

- storedValueForAttribute:(NSString *)anAttribute;
- valueForAttribute:(NSString *)anAttribute;
- valueForAttributeKeyPath:(NSString *)keypath;

- (NSDictionary *)valuesForAttributes:(NSArray *)attributes;

- (BOOL)hasStoredValueAttribute:(NSString *)attrName;

- (void)takeStoredValue:aValue forAttribute:(NSString *)anAttribute;
- (BOOL)takeStoredValue:(id)val forAttribute:(NSString *)attribute compareBefore:(BOOL)compare;

// puts aValue into a mutableArray named anAttribute
- (void)takeStoredValue:aValue forArrayAttribute:(NSString *)anAttribute;

- (void)setValue:aValue forAttribute:(NSString *)anAttribute;
- (BOOL)setValue:(id)val forAttribute:(NSString *)attribute compareBefore:(BOOL)compare;

// the given sets of keys, set the values on the object using setValue:forAttribute:compareBefore:
// returns the number of values that where set
- (unsigned int)setValuesFromDictionary:(NSDictionary *)dict 
							  usingKeys:(NSArray *)keys 
						  compareBefore:(BOOL)compare
						 eliminateNulls:(BOOL)elim;



- (void)takeStoredAttributeValuesFromDictionary:(NSDictionary *)values;
- (void)takeStoredAttributeValuesAndNullsFromDictionary:(NSDictionary *)values;
- (void)takeAttributeValuesFromDictionary:(NSDictionary *)values;


// conveniences


// calls valueForAttribute -- if the result is NSNull, nil is returned
- (id)nullSafeValueForAttribute:(NSString *)key;

// calls storedValueForAttribute -- if the result is NSNull nil is returned
- (id)nullSafeStoredValueForAttribute:(NSString *)key;
- (NSDictionary *)nullSafeValuesForAttributes:(NSArray *)attributes;



// Sets the value only if value is not null
- (void)conditionallySetValue: (id)val forKey: (NSString *)key;

// Only sets the value if there is no value there before
- (void)softSetValue:(id)val forKey:(NSString *)key;
- (void)softSetValue:(id)val forKeyPath:(NSString *)key;


- (NSString *)textRepresentationUsingAttributes:(NSArray *)attribs 
	joinedByString:(NSString *)delim 
	startWrapString:(NSString *)start_wrap 
	endingWrapString:(NSString *)end_wrap;


/*
{
	"First Name" = "firstname";
}
*/
- (NSDictionary *)dictionaryRepresentationUsingMapping:(NSDictionary *)mapping;

- (void)setValuesForKeyPathsWithDictionary:(NSDictionary *)keyedValues;


/*
 filterArray
 
 Used when KVC inline filtering makes sense. For example, you need to get to a specific element in an sub array of an object.
 
 name = [jessica valueForKeyPath:"filterArray.{roles {roleType.name == \"Customer\" OR roleType.name == \"Executive\"}, last{name}}.smartName"];
 
 The preceding line returns the smartName of the last role in the array of roles where roleType name is Customer or Executive
 
 jessica is a contact
 roles is the array we want to filter
 roleType.name... is the NSPredicate string
 last{name} mean return the last object after sorting the filtered array by name ascending
 
 The whole filter command is braced between {}
 The predicate string is everything in the second set of braces {}
 The ", " separates the filter command from the sort command
 
 The sorting options are:
 	first							(returns the first object no matter what)
 	last							(returns the last object no matter what)
 	sort{roleType.name}				(returns the array sorted by roleType.name - ASCENDING)
 	sort{roleType.name|desc}		(returns the array sorted by roleType.name - DESCENDING)
 	first{roleType.name}			(returns the first object in the array sorted by roleType.name - ASCENDING)
 	first{roleType.name|desc}		(returns the first object in the array sorted by roleType.name - DESCENDING)
 	last{roleType.name}				(returns the last object in the array sorted by roleType.name - ASCENDING)
 	last{roleType.name|desc}		(returns the last object in the array sorted by roleType.name - DESCENDING)
 
 
 
 */
- (id)filterArray;


@end
