Declaring models

To declare a model, simply create a class that extends OOCModel and declare all the properties you need. Basic types (bool, double, float, int, long), and instances of NSString, NSData, and any other class that implements NSCoding can be used.

OOCIndex

An index is required in order to filter by that property. To index by a property declare it using the protocol OOCIndex.

@interface Author : OOCModel
  
@property NSString<OOCIndex>* mood;
// [[Author all] find:@{@"mood": @"happy"}]

@end

Now you can get all authors with a specific mood. More information in OOCModel.

Only non binary properties can be used as indices. This includes strings and c types, but excludes binary data or serialize objects.

A readonly property can be declared as an index and its method overwritten to be a function of other properties.

@interface Node : OOCModel

@property (readonly) BOOL available;
@property id<OOCIndex> availableMeta;
@property int capacity;
// [[Node all] find:@{@"available": @TRUE}]

@end
@implementation Node

- (BOOL) available {
    return self.capacity <= 90;
}

@end

OOCUnique

Unique is a special kind of index that does not allow the same value in two objects. Trying to do so will raise a OOCUniqueIndexViolationException. To declare a property as unique, it has to use the OOCUnique protocol.

@interface User : OOCModel

@property NSString<OOCUnique>* email;
// [User with:@"email" is:@"[email protected]"]

@end

OOCSortedIndex

A sorted index on a property allows range queries of models. An indexed property must be a double, or some class that implements the method doubleValue.

@interface Event : OOCModel

@property NSDate* date;

// d_date will be the sorted set value to be queried
@property (readonly) double d_date;
@property (readonly) id<OOCSortedIndex> d_dateMeta;
@property (readonly) int day;
// another sorted set will be created per day, so it can be sub-filtered
@property id<OOCSortedIndexGroupBy> d_date__day;

// All the events that happened today
// [Event collectionWithProperty:@"d_date" scoreBetween:0 and:INFINITY andProperty:@"day" is:[NSNumber numberWithInteger:today]]

// All the events in the last 10 minutes
// [Event collectionWithProperty:@"d_date" scoreBetween:[[NSDate date] timeIntervalSince1970] - 10 * 60 and:INFINITY]

@end
@implementation Event

+ (int)dayForDate:(NSDate*)date {
    return [date timeIntervalSince1970] / (24 * 60 * 60);
}

- (double) d_date {
    return [self.date timeIntervalSince1970];
}

- (int) day {
    return [[self class] dayForDate:self.date];
}

@end

"Meta" suffix properties

Adding protocols to properties might be awkward, since it will affect the getter and setter and require some casts (even if the protocols do not declare any new method). The problem is worse for C types that cannot declare properties.

To avoid this conflicts, you can declare another property adding "Meta" as suffix, and its protocol behavior will be applied to the original property.

@interface User : OOCModel

@property NSString* email;
@property id<OOCUnique> emailMeta;

@end

Collections in models

A model can collect references to other models. It can use either a OOCSet or a OOCList.

To specify the class of objects in the set, it must implement a protocol named as the class that it collects.

@protocol Person;

@interface Event : OOCModel

@property NSString* name;
@property id<OOCIndex> nameMeta;
@property NSString* location;
@property OOCMutableSet<Person>* attendees;

@end
@protocol Person <NSObject>
@end

@interface Person : OOCModel

@property NSString* name;

@end

The collection properties are automatically created on init. Do not create them manually.

Back references

When an object collects instances, and the instances have a reference to the object, the collection can be automatically managed by the instances.

To do so, declare a property in the collector class using the OOCCollection protocol and name it by concatenating the collection property, two underscores and the property that reference to this object in the collected class.

@protocol Post;
@interface User : OOCModel

@property NSString<OOCIndex>* fname;
@property NSString<OOCIndex>* lname;
@property OOCSet<Post>* posts;

@property id<OOCCollection> posts__user;
// When setting Post.user, it will automatically add itself to Post.user.posts

@end
@interface Post : OOCModel

@property NSString* body;
@property User* user;

@end