Skip to content

Instantly share code, notes, and snippets.

@ifournight
Last active December 16, 2015 21:39
Show Gist options
  • Save ifournight/5500944 to your computer and use it in GitHub Desktop.
Save ifournight/5500944 to your computer and use it in GitHub Desktop.
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
// SNode class is one of the two most important objects throughout the entire Xcode Reader Project.
// Because all documents in every Apple's documentation library, are categorized into two category: Token and Node, and stored in Core Data.
// Token represents reference/ API: OBC C++ Class, Protocol, Method, Enum, Struct, Constant, Function, Macro, Notification...
// Node represents guide/ sample code and all the articles.
// They all have many properties and a graphic stored in Core Data's NSManagedObjectModel.
// Throughout Xcode Reader's workflow, tokens and node will be prefetched into memory from Core Data.
// And Their properties may be used in different context.
// So SToken and SNode are classes that wrap all the needed information and helper methods of token and node.
// So they can respectively hold and represent token or node in memory and other view controllers can conveniently fetch information from them.
@interface SNode: NSObject <NSCopying>
// Name and ID are the identifier's properties.
// Name.
@property (nonatomic, copy) NSString *name;
// NSManagedObjectID of in Core Data.
@property (nonatomic, strong) NSManagedObjectID *ID;
// Type, expandable, subNodes, URL are information properties.
// They would be fetched from core data in batch when needed, using method fetchInformationPropertiesWithContext:.
// The copy: method would not copy information properties
// Node Type.
@property (nonatomic, copy) NSString *nodeType;
// Document Type
@property (nonatomic, assign) NSInteger *documentType;
// When node has subNodes, it is expandable.
@property (nonatomic, assign) BOOL expandable;
// Node's subNodes.
@property (nonatomic, strong) NSArray *subNodes;
// URL.
@property (nonatomic, strong) NSURL *URL;
// Designated initializer.
- (id)initWithName:(NSString *)name ID:(NSManagedObjectID *)ID;
// Fetch all information properties.
- (void)fetchInformationPropertiesWithContext:(NSManagedObjectContext *)context;
@end
#import "SNode.h"
#import "SLibrary.h"
#import "SLibraryManager.h"
@implementation SNode
- (id)initWithName:(NSString *)name ID:(NSManagedObjectID *)ID
{
self = [super init];
if (self) {
_name = name;
_ID = ID;
}
return self;
}
- (id)copyWithZone:(NSZone *)zone
{
SNode *copy = [[self class] allocWithZone:zone] init];
copy.name = [self.name copyWithZone:zone];
copy.ID = [self.ID copyWithZone:zone];
return copy;
}
- (NSString *)nodeTypeForNodeWithObject:(NSManagedObject *)managedObject
{
return [managedObject valueForKey:@"kNodeType"];
}
- (NSInteger) documentTypeForNodeWithObject:(NSManagedObject *)managedObject
{
return [managedObject valueForKey:@"kDocumentType"];
}
- (BOOL)isExpandableForNodeWithObject:(NSManageObject *)managedObject
{
return [managedObject valueForKey:@"kIsSearchable"];
}
- (NSArray *)subNodesForNodeWithObject:(NSManagedObject *)managedObject
{
NSSet *orderedSubNodes = [managedObject valueForKey:@"orderedSubnodes"];
NSSortDescriptor *orderSortDescriptor = [NSSortDescriptor sortDescriptorWithName:@"order" ascending:YES];
return [[[orderedSubNodes sortedArrayUsingDescriptors:@[orderSortDescriptor]] valueForKeyPath:@"node"];
}
- (NSURL *)URLForNodeWithObject:(NSManagedObject *)managedObject
{
NRURL *URL = nil;
NSPersistentStore *store = self.ID.persistentStore;
SLibrary *library = [[SLibraryManager share] librariesByStoreID][store.identifier];
NSString *kPath = [managedObject valueForKey:@"kPath"];
NSString *kAnchor = [managedObject valueForKey:@"kAnchor"];
NSString *path = [[[library.path stringByAppendingPathComponent:kLibraryDocumentPath] stringByAppendingPathComponent:kPath];
URL = [NSURl fileURLWithPath:path];
if (kAnchor) {
URL = [[NSURL URLWithString:[[URL absoluteString] stringByAppendingFormat:@"#%@", kAnchor]];
}
}
- (void)fetchInformationPropertiesWithContext:(NSManagedObjectContext *)context
{
NSManagedObject *managedObject = [context existingObjectWithID:self.ID error:nil];
if (managedObject) {
self.nodeType = [self nodeTypeForNodeWithObject:managedObject];
self.documentType = [self documentTypeForNodeWithObject:managedObject];
self.expandable = [self isExpandableForNodeWithObject:managedObject];
if (self.expandable) {
self.subNodes = [self subNodesForNodeWithObject:managedObject];
}
self.URL = [self URLForNodeWithObject:managedObject];
} else {
NSLog(@"SNode: NSManagedObject == nil when fetching information properties");
}
}
@end
#import <Foundation/Foundation.h>
#import "SNode.h"
// A subclass of SNode that has extra properties to assistant SNodeSearchOperation.
@interface SSearchNode : SNode <NSCopying>
// A mutable array contains all match ranges regarding search string with this node.
@property (nonatomic, strong) NSMutableArray *matchRanges;
// Minimum match range's location among all ranges in matchRanges.
@property (nonatomic, assign) NSInteger minimumMatchLocation;
@end
#import "SSearchNode.h"
@implementation SSearchNode
- (id)initWithName:(NSString *)name ID:(NSManagedObjectID *)ID
{
self = [super initWithName:name ID:ID];
if (self) {
_matchRanges = [[NSMutableArray alloc] init];
}
return self;
}
- (id)copyWithZone:(NSZone *)zone
{
SSearchNode *copy = [super copyWithZone:zone];
copy.matchRanges = [[NSMutableArray alloc] initWithArray:self.matchRanges copyItems:YES];
return copy;
}
@end
#import <Foundation/Foundation.h>
#import <CoreData/CoreData/h>
#import "SToken.h"
// A Subclass of SToken that has extra properties to assistant STokenSearchOperation.(operation for short)
@interface SSearchToken : SToken <NSCopying>
// When operation do word match and character match, token's searchRange property determine this token's searchRange.
// Read STokenSearchOperation.m to see the details.
@property (nonatomic, assign) NSRange searchRange;
// A mutable array contain all the match range of search string with this token.
@property (nonatomic, assign) NSMutableArray *matchRanges;
// The minimum location among all ranges in matchRanges, used for sorting.
@property (nonatomic, assign) NSInteger minimumMatchLocation;
// The maximum length among all ranges in matchRanges, used for sorting.
@property (nonatomic, assign) NSInteger maximumMatchLength;
// Call this initializer to create token with specific searchRange and matchRanges.
// If aiming to create a token with default searchRange and matchRange, use super class's initializer - initWithName:ID:.
- (id)initWithName:(NSString *)name ID:(NSManagedObjectID *)ID searchRange:(NSRange)searchRange matchRanges:(NSMutableArray *)matchRanges;
@end
#import "SSearchToken.h"
@implementation SSearchToken
- (id)initWithName:(NSString *)name ID:(NSManagedObjectID *)ID
{
self = [super initWithName:name ID:ID];
if (self) {
_searchRange = NSMakeRange(0, _name.length);
_matchRanges = [[NSMutableArray alloc] init];
}
return self;
}
- (id)initWithName:(NSString *)name ID:(NSManagedObjectID *)ID searchRange:(NSRange)searchRange matchRanges:(NSMutableArray *)matchRanges
{
self = [self initWithName:name ID:ID];
if (self) {
_searchRange = NSMakeRange(searchRange.location, searchRange.length);
_matchRanges = [matchRanges mutableCopy];
}
return self;
}
- (id)copyWithZone:(NSZone *)zone
{
SSearchToken *copy = [super copyWithZone:zone];
if (copy) {
copy.searchRange = NSMakeRange(self.searchRange.location, self.searchRange.length);
copy.matchRanges = [[NSMutableArray alloc] initWithArray:self.matchRanges copyItems:YES];
}
return copy;
}
@end
#import <Foundation/Foundation.h>
#import <CoraData/CoreData.h>
// SToken class is one of the two most important objects throughout the entire Xcode Reader Project.
// Because all documents in every Apple's documentation library, are categorized into two category: Token and Node, and stored in Core Data.
// Token represents reference/ API: OBC C++ Class, Protocol, Method, Enum, Struct, Constant, Function, Macro, Notification...
// Node represents guide/ sample code and all the articles.
// They all have many properties and a graphic stored in Core Data's NSManagedObjectModel.
// Throughout Xcode Reader's workflow, tokens and node will be prefetched into memory from Core Data.
// And Their properties may be used in different context.
// So SToken and SNode are classes that wrap all the needed information and helper methods of token and node.
// So they can respectively hold and represent token or node in memory and other view controllers can conveniently fetch information from them.
// The class conforms NSCopying protocal.
@interface SToken : NSObject <NSCopying>
// Name and ID are the identifier's properties.
// Name.
@property (nonatomic, copy) NSString *name;
// NSManagedObjectID of in Core Data.
@property (nonatomic, strong) NSManagedObjectID *ID;
// All properties below are the information properties
// They would be fetched from Core Data in batch when needed, using method: fetchInformationPropertiesWithContext:.
// The copy method will not copy these properties.
@property (nonatomic, copy) NSString *container;
@property (nonatomic, copy) NSString *abstract;
@property (nonatomic, assign) BOOL deprecated;
@property (nonatomic, copy) NSString *deprecatedSinceVersion;
@property (nonatomic, copy) NSString *type;
// URL, so webView can open it.
@property (nonatomic, strong) NSURL *URL;
// Designated Initializer.
- (id)initWithName:(NSString *)name ID:(NSManagedObjectID *)ID;
// Fetch all information properties.
- (void)fetchInformationPropertiesWithContext:(NSManagedObjectContext *)context;
@end
#import "SToken.h"
@implementation SToken
- (id)initWithName:(NSString *)name ID:(NSManagedObjectID *)ID
{
self = [super init];
if (self) {
_name = name;
_ID = ID;
}
return self;
}
- (NSString *)containerForTokenWithObject:(NSManagedObject *)managedObject
{
return [managedObject valueForKeyPath:@"container.containerName"];
}
- (NSString *)abstractForTokenWithObject:(NSManagedObject *)managedObject
{
return [managedObject valueForKeyPath:@"metainformation.abstract"];
}
- (BOOL)isDeprecatedForTokenWithObject:(NSManagedObject *)managedObject
{
NSSet *deprecatedInVersions = [managedObject valueForKeyPath:@"metainformation.deprecatedInVersions"];
return deprecatedInVersions.count > 0 ? YES : NO;
}
- (NSString *)deprecatedSinceVersionForTokenWithObject:(NSManagedObject *)managedObject
{
NSSet *deprecatedInVersions = [managedObject valueForKeyPath:@"metainformation.deprecatedInVersions"];
NSSortDescriptor *versionStringSortDescriptor = [NSSortDescriptor sortDescriptorWithName:@"versionString" ascending:YES];
return [[deprecatedInVersions sortedArrayUsingDescriptors:@[versionStringSortDescriptor]][0] valueForKey:@"versionString"];
}
- (NSString *)typeForTokenWithObject:(NSManagedObject *)managedObject
{
return [managedObject valueForKeyPath:@"tokenType.typeName"];
}
- (NSURL *)URLForTokenWithObject:(NSManagedObject *)managedObject
{
NSURL *URL = nil;
// Anchor and file path
NSString *anchor = [managedObject valueForKey:@"anchor"];
NSString *filePath = [managedObject valueForKeyPath:@"file.path"];
NSString *path = nil;
if (filePath) {
NSPersistentStore *store = self.ID.persistentStore;
SLibrary *library = [[SLibraryManager share] librariesByStoreID][store.indentifier];
path = [[library.path stringByAppendingPathComponent:kLibraryDocumentPath] stringByAppendingPathComponent:filePath];
} else {
// Parent node path.
NSManagedObject *parentNode = [managedObject valueForKey:@"parentNode"];
NSString *parentNodePath = [[parentNode URLForNodeWithManagedObject:parentNode] path];
path = parentNodePath;
}
URL = [NSURL fileURLWithPath:path];
if (anchor.length > 0) {
URL = [[NSURL URLWithString:[[URL absoluteString] stringByAppendingFormate:@"#%@",anchor]];
}
return URL;
}
- (id)copyWithZone:(NSZone *)zone
{
SToken *copy = [[[self class] allocWithZone:zone] init];
copy.name = [self.name copyWithZone:zone];
copy.ID = [self.ID copyWithZone:zone];
return copy;
}
- (void)fetchInformationPropertiesWithContext:(NSManagedObjectContext *)context
{
NSManagedObject *managedObject = [context existingObjectWith:self.ID error:nil];
if (managedObject) {
self.container = [self containerForTokenWithObject:managedObject];
self.abstract = [self abstractForTokenWithObject:managedObject];
self.deprecated = [self isDeprecatedForTokenWithObject:managedObject];
if (self.deprecated) {
self.deprecatedSinceVersion = [self deprecatedSinceVersionForTokenWithObject:managedObject];
}
self.type = [self typeForTokenWithObject:managedObject];
self.URL = [self URLForTokenWithObject:managedObject];
} else {
NSLog(@"SToken: NSManagedObject == nil when fetching information properties");
}
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment