Skip to content

Instantly share code, notes, and snippets.

@jonnolen
Created March 5, 2013 20:42
Show Gist options
  • Save jonnolen/5094081 to your computer and use it in GitHub Desktop.
Save jonnolen/5094081 to your computer and use it in GitHub Desktop.
PSPDFAnnotationProvider implementation backed by core data
//
// UserCoreDataAnnotationProvider.m
// BoardRoom
//
// Created by Jonathan Nolen on 3/2/13.
//
//
#import "UserCoreDataAnnotationProvider.h"
#import "Annotation.h"
#import "CachedAnnotation.h"
@interface UserCoreDataAnnotationProvider()
@property (nonatomic, strong) NSMutableDictionary *pageCache;
@property (nonatomic, strong) Packet *packet;
@property (nonatomic, strong) NSString *username;
@end
@implementation UserCoreDataAnnotationProvider
@synthesize providerDelegate;
+(UserCoreDataAnnotationProvider *)coreDataAnnotationProviderWithPacket:(Packet *)packet andUser:(NSString *)username{
UserCoreDataAnnotationProvider *result = [self new];
result.packet = packet;
result.username = username;
return result;
}
-(id)init{
if (self = [super init]){
_pageCache = [NSMutableDictionary dictionaryWithCapacity:1];
}
return self;
}
-(BOOL)addAnnotations:(NSArray *)annotations forPage:(NSUInteger)page{
__block BOOL supportsAllAnnotations = YES;
[annotations enumerateObjectsUsingBlock:^(PSPDFAnnotation *annotation, NSUInteger indx, BOOL *stop){
if ((annotation.type & [self supportedTypes]) != annotation.type){
*stop = YES;
supportsAllAnnotations = NO;
return;
}
}];
if (!supportsAllAnnotations){
return NO;
}
[annotations enumerateObjectsUsingBlock:^(PSPDFAnnotation *annotation, NSUInteger idx, BOOL *stop){
Annotation *coreDataAnnotation = [self saveAnnotation:annotation];
CachedAnnotation *cachedAnnotation = [CachedAnnotation cachedAnnotationWithObjectId:coreDataAnnotation.objectID nativeAnnotation:annotation];
[self cacheAnnotationToProperPage:cachedAnnotation];
}];
return YES;
}
-(Annotation *)saveAnnotation:(PSPDFAnnotation *)annotation{
Annotation *result = [Annotation MR_createEntity];
result.packet = self.packet;
result.username = self.username;
result.page = @(annotation.page);
result.annotationJson = [[annotation externalRepresentationInFormat:PSPDFModelJSONFormat] JSONString];
[result.managedObjectContext MR_saveOnlySelfAndWait];
annotation.dirty = NO;
return result;
}
-(void)cacheAnnotationToProperPage:(CachedAnnotation *)annotation{
NSMutableSet *pageAnnotations = [self pageCacheForPage:annotation.annotation.page];
[pageAnnotations addObject:annotation];
}
- (NSArray *)annotationsForPage:(NSUInteger)page{
NSMutableSet *annotationsForPage = [self pageCacheForPage:page];
return [annotationsForPage valueForKey:@"annotation"];
}
-(NSMutableSet *)pageCacheForPage:(NSUInteger)page{
NSMutableSet *pageAnnotations = nil;
@synchronized(self){
if (self.pageCache[@(page)]){
pageAnnotations = self.pageCache[@(page)];
}
else{
//get core data annotations for page.
NSArray *coreDataAnnotations = [self coreDataAnnotationsForPage:page];
pageAnnotations = [NSMutableSet setWithCapacity:coreDataAnnotations.count];
//for each core data annotation, create the CacheAnnotation object and add it to pageAnnotations.
[coreDataAnnotations enumerateObjectsUsingBlock:^(Annotation *annotation, NSUInteger idx, BOOL *stop){
[pageAnnotations addObject:[CachedAnnotation cachedAnnotationWithCoreDataAnnotation:annotation]];
}];
self.pageCache[@(page)] = pageAnnotations;
}
}
return pageAnnotations;
}
-(CachedAnnotation *)cachedAnnotationForNativeAnnotation:(PSPDFAnnotation *)nativeAnnotation{
NSSet *annnotationsForNativeAnnotationPage = self.pageCache[@(nativeAnnotation.page)];
CachedAnnotation *cachedAnnotation = [[annnotationsForNativeAnnotationPage objectsPassingTest:^(CachedAnnotation *ca, BOOL *stop){
return (BOOL)(ca.annotation == nativeAnnotation);
}] anyObject];
return cachedAnnotation;
}
-(NSArray *)coreDataAnnotationsForPage:(NSUInteger)page{
NSFetchRequest *fetchAnnotationsForUserInPacketForPage = [Annotation
MR_requestAllWithPredicate:[NSPredicate
predicateWithFormat:@"packet == %@ AND username == %@ and page == %@",
self.packet,
self.username,
@(page)]];
return [Annotation MR_executeFetchRequest:fetchAnnotationsForUserInPacketForPage];
}
- (void) didChangeAnnotation:(PSPDFAnnotation *)annotation originalAnnotation:(PSPDFAnnotation *)originalAnnotation keyPaths:(NSArray *)keyPaths options:(NSDictionary *)options{
CachedAnnotation *cachedAnnotation = [self cachedAnnotationForNativeAnnotation:annotation];
if (cachedAnnotation){
Annotation *coreDataAnnotation = (Annotation *)[[NSManagedObjectContext MR_contextForCurrentThread] objectWithID:cachedAnnotation.objectId];
if ([keyPaths[0] isEqualToString:@"isDeleted"]){
[coreDataAnnotation MR_deleteEntity];
[self deleteAnnotation:cachedAnnotation];
}
else{
NSError *error = nil;
NSDictionary *jsonRepresentation = [annotation externalRepresentationInFormat:PSPDFModelJSONFormat];
[jsonRepresentation enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop){
NSLog(@"key class/value: %@/%@, obj class/value: %@/%@", [key class], key, [obj class], obj);
}];
coreDataAnnotation.annotationJson = [[annotation externalRepresentationInFormat:PSPDFModelJSONFormat] JSONStringWithOptions:JKSerializeOptionNone error:&error];
if (error){
NSLog(@"%@", error);
}
}
[coreDataAnnotation.managedObjectContext MR_saveOnlySelfWithCompletion:nil];
annotation.dirty = NO;
}
}
-(void)deleteAnnotation:(CachedAnnotation *)cachedAnnotation{
[self.pageCache[@(cachedAnnotation.annotation.page)] removeObject:cachedAnnotation];
}
-(NSDictionary *)dirtyAnnotations{
return @{};
}
-(BOOL)hasLoadedAnnotationsForPage:(NSUInteger)page{
return (self.pageCache[@(page)] != nil);
}
-(BOOL)saveAnnotationsWithError:(NSError *__autoreleasing *)error{
return YES;
}
-(PSPDFAnnotationType)supportedTypes{
return (PSPDFAnnotationTypeHighlight |
PSPDFAnnotationTypeInk |
PSPDFAnnotationTypeNote );
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment