2005-08-03 Helge Hess <helge.hess@opengroupware.org>
+ * v4.5.2
+
+ * EOFetchSpecification+CoreData.m: implemented -initWithFetchRequest:
+
+ * EOCoreDataSource.m: added key/value archiving, added ability to
+ retrieve the entity from the fetch specification, added support for
+ qualifier bindings (v4.5.2)
+
+ * EOSortOrdering+CoreData.m: implemented conversion methods
+
+ * EOQualifier+CoreData.m: implemented conversion methods
+
+ * moved NS* categories to own files
+
* v4.5.1
* moved in implementation prototypes from CoreDataBlog
--- /dev/null
+/*
+ Copyright (C) 2005 SKYRIX Software AG
+
+ This file is part of SOPE.
+
+ SOPE is free software; you can redistribute it and/or modify it under
+ the terms of the GNU Lesser General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ SOPE is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with SOPE; see the file COPYING. If not, write to the
+ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+*/
+
+#include "EOQualifier+CoreData.h"
+#include "NSPredicate+EO.h"
+#include "NSExpression+EO.h"
+#include "common.h"
+
+@implementation EOAndQualifier(CoreData)
+
+- (NSCompoundPredicateType)compoundPredicateType {
+ return NSAndPredicateType;
+}
+
+- (NSPredicate *)asPredicate {
+ NSLog(@"TODO(%s): implement me for class %@!", __PRETTY_FUNCTION__,
+ NSStringFromClass([self class]));
+ return nil;
+}
+
+@end /* EOAndQualifier(CoreData) */
+
+@implementation EOOrQualifier(CoreData)
+
+- (NSCompoundPredicateType)compoundPredicateType {
+ return NSOrPredicateType;
+}
+
+- (NSPredicate *)asPredicate {
+ NSLog(@"TODO(%s): implement me for class %@!", __PRETTY_FUNCTION__,
+ NSStringFromClass([self class]));
+ return nil;
+}
+
+@end /* EOOrQualifier(CoreData) */
+
+@implementation EONotQualifier(CoreData)
+
+- (NSCompoundPredicateType)compoundPredicateType {
+ return NSNotPredicateType;
+}
+
+- (NSPredicate *)asPredicate {
+ return [NSCompoundPredicate notPredicateWithSubpredicate:
+ [[self qualifier] asPredicate]];
+}
+
+@end /* EONotQualifier(CoreData) */
#include <EOCoreData/EOQualifier+CoreData.h>
#include <EOCoreData/EOSortOrdering+CoreData.h>
+#include <EOCoreData/NSExpression+EO.h>
+#include <EOCoreData/NSPredicate+EO.h>
+
#endif /* __EOCoreData_H__ */
This wraps a NSManagedObjectContext in an EODataSource. It corresponds to
the EODatabaseDataSource available in EOF.
+
+ Note: if you use -setFetchRequest: all the EO related methods will be reset!
*/
@class NSArray, NSDictionary;
-@class NSManagedObjectContext, NSEntityDescription;
+@class NSManagedObjectContext, NSEntityDescription, NSFetchRequest;
@class EOQualifier, EOFetchSpecification;
@interface EOCoreDataSource : EODataSource
EOFetchSpecification *fetchSpecification;
EOQualifier *auxiliaryQualifier;
NSDictionary *qualifierBindings;
+ NSFetchRequest *fetchRequest;
struct {
int isFetchEnabled:1;
- int reserved:31;
+ int isEntityFromFetchSpec:1;
+ int reserved:30;
} ecdFlags;
}
- (void)setQualifierBindings:(NSDictionary *)_bindings;
- (NSDictionary *)qualifierBindings;
+/* directly access a CoreData fetch request */
+
+- (void)setFetchRequest:(NSFetchRequest *)_fr;
+- (NSFetchRequest *)fetchRequest;
+
/* accessors */
- (NSEntityDescription *)entity;
#include "EOCoreDataSource.h"
#include "EOFetchSpecification+CoreData.h"
+#include "EOQualifier+CoreData.h"
#include "common.h"
static NSString *EODataSourceDidChangeNotification =
entity:(NSEntityDescription *)_entity
{
if ((self = [super init]) != nil) {
- if (_moc == nil || _entity == nil) {
- NSLog(@"ERROR(%s): missing object-context or entity parameter!",
+ if (_moc == nil) {
+ NSLog(@"ERROR(%s): missing object-context parameter!",
__PRETTY_FUNCTION__);
[self release];
return nil;
}
+ self->ecdFlags.isFetchEnabled = 1;
self->managedObjectContext = [_moc retain];
self->entity = [_entity retain];
}
/* fetch-spec */
+- (void)_resetFetchRequest {
+ [self->fetchRequest release]; self->fetchRequest = nil;
+}
+
- (void)setFetchSpecification:(EOFetchSpecification *)_fspec {
+ BOOL isSameEntity;
+
if ([self->fetchSpecification isEqual:_fspec])
return;
+ if ([_fspec isKindOfClass:[NSFetchRequest class]]) {
+ /* be tolerant, we ain't no Java ... */
+ [self setFetchRequest:(NSFetchRequest *)_fspec];
+ return;
+ }
+
+ isSameEntity =
+ [[self->fetchSpecification entityName] isEqual:[_fspec entityName]];
+
[self->fetchSpecification autorelease];
self->fetchSpecification = [_fspec copy];
+ /* reset derived entities */
+ if (self->ecdFlags.isEntityFromFetchSpec && !isSameEntity) {
+ self->ecdFlags.isEntityFromFetchSpec = 0;
+ }
+
+ [self _resetFetchRequest];
+
[self postDataSourceChangedNotification];
}
}
/* apply bindings */
-
+
if ((bindings = [self qualifierBindings]) != nil ) {
-#warning IMPLEMENT ME!
+ EOQualifier *q;
+
+ if ((q = [fs qualifier]) != nil) {
+ q = [q qualifierWithBindings:[self qualifierBindings]
+ requiresAllVariables:YES];
+ [fs setQualifier:q];
+ }
}
+ /* finished */
return fs;
}
- (void)setAuxiliaryQualifier:(EOQualifier *)_qualifier {
+ if ([_qualifier isKindOfClass:[NSPredicate class]]) /* be tolerant */
+ _qualifier = [EOQualifier qualifierForPredicate:(NSPredicate *)_qualifier];
+
if ([self->auxiliaryQualifier isEqual:_qualifier])
return;
+
+ ASSIGNCOPY(self->auxiliaryQualifier, _qualifier);
+ [self _resetFetchRequest];
[self postDataSourceChangedNotification];
}
- (EOQualifier *)auxiliaryQualifier {
- (void)setQualifierBindings:(NSDictionary *)_bindings {
ASSIGN(self->qualifierBindings, _bindings);
+
+ [self _resetFetchRequest];
+ [self postDataSourceChangedNotification];
}
- (NSDictionary *)qualifierBindings {
return self->qualifierBindings;
}
- (void)setIsFetchEnabled:(BOOL)_flag {
- self->ecdFlags.isFetchEnabled = _flag ? 1 : 0;
+ int f;
+
+ f = _flag ? 1 : 0;
+ if (self->ecdFlags.isFetchEnabled == f)
+ return;
+
+ self->ecdFlags.isFetchEnabled = f;
+
+ [self postDataSourceChangedNotification];
}
- (BOOL)isFetchEnabled {
return self->ecdFlags.isFetchEnabled ? YES : NO;
}
+/* directly access a CoreData fetch request */
+
+- (void)setFetchRequest:(NSFetchRequest *)_fr {
+ if (_fr == self->fetchRequest)
+ return;
+
+ /* reset EO objects */
+ [self->fetchSpecification release]; self->fetchSpecification = nil;
+ [self->auxiliaryQualifier release]; self->auxiliaryQualifier = nil;
+ [self->qualifierBindings release]; self->qualifierBindings = nil;
+
+ /* use entity of fetch-request */
+ if ([_fr entity] != nil) {
+ ASSIGN(self->entity, [_fr entity]);
+ self->ecdFlags.isEntityFromFetchSpec = 1;
+ }
+
+ ASSIGN(self->fetchRequest, _fr);
+}
+- (NSFetchRequest *)fetchRequest {
+ return self->fetchRequest;
+}
+
/* accessors */
- (NSEntityDescription *)entity {
+ if (self->entity == nil && !self->ecdFlags.isEntityFromFetchSpec) {
+ NSManagedObjectContext *moc;
+ NSString *n;
+
+ self->ecdFlags.isEntityFromFetchSpec = 1; /* also used for caching fails */
+
+ moc = [self managedObjectContext];
+ n = [[self fetchSpecification] entityName];
+ if (moc != nil && n != nil) {
+ self->entity = [[NSEntityDescription entityForName:n
+ inManagedObjectContext:moc] retain];
+ }
+ }
return self->entity;
}
- (NSManagedObjectContext *)managedObjectContext {
- (NSArray *)fetchObjects {
EOFetchSpecification *fs;
- NSFetchRequest *fr;
NSError *error = nil;
NSArray *results;
if (![self isFetchEnabled])
return [NSArray array];
- fs = [self fetchSpecificationForFetch];
- fr = [fs fetchRequestWithEntity:[self entity]];
+ // TODO: print a warning on entity mismatch?
+ if (self->fetchRequest == nil) {
+ fs = [self fetchSpecificationForFetch];
+ self->fetchRequest = [[fs fetchRequestWithEntity:[self entity]] retain];
+ }
- results = [[self managedObjectContext] executeFetchRequest:fr error:&error];
+ results = [[self managedObjectContext]
+ executeFetchRequest:self->fetchRequest error:&error];
if (results == nil) {
+ // TODO: improve (-lastException on the datasource or return the error?)
+ NSLog(@"ERROR(%s): datasource failed to fetch: %@", __PRETTY_FUNCTION__,
+ error);
+ return nil;
}
// TODO: add grouping support?
return (id)[self entity];
}
+/* archiving */
+
+- (id)initWithKeyValueUnarchiver:(EOKeyValueUnarchiver *)_unarchiver {
+ id lEntity;
+ id fs;
+ id ec;
+
+ /* fetch object context */
+
+ ec = [_unarchiver decodeObjectReferenceForKey:@"managedObjectContext"];
+ if (ec == nil)
+ ec = [_unarchiver decodeObjectReferenceForKey:@"editingContext"];
+
+ if (ec != nil && ![ec isKindOfClass:[NSManagedObjectContext class]]) {
+ NSLog(@"WARNING(%s): decode object context is of unexpected class: %@",
+ __PRETTY_FUNCTION__, ec);
+ }
+
+ /* fetch fetch specification */
+
+ fs = [_unarchiver decodeObjectForKey:@"fetchRequest"];
+ if (fs == nil)
+ fs = [_unarchiver decodeObjectForKey:@"fetchSpecification"];
+ if (fs != nil && [fs isKindOfClass:[NSFetchRequest class]])
+ fs = [[[EOFetchSpecification alloc] initWithFetchRequest:fs] autorelease];
+
+ /* setup entity */
+
+ lEntity = [_unarchiver decodeObjectForKey:@"entity"];
+ if (lEntity == nil && fs != nil) {
+ /* try to determine entity from fetch-spec */
+ lEntity = [(EOFetchSpecification *)fs entityName];
+ }
+ if ([lEntity isKindOfClass:[NSString class]]) {
+ lEntity = [NSEntityDescription entityForName:lEntity
+ inManagedObjectContext:ec];
+ }
+
+ /* create object */
+
+ if ((self = [self initWithManagedObjectContext:ec entity:lEntity]) == nil)
+ return nil;
+
+ /* add non-initializer settings */
+
+ [self setFetchSpecification:fs];
+ [self setAuxiliaryQualifier:
+ [_unarchiver decodeObjectForKey:@"auxiliaryQualifier"]];
+ [self setQualifierBindings:
+ [_unarchiver decodeObjectForKey:@"qualifierBindings"]];
+
+ [self setIsFetchEnabled:[_unarchiver decodeBoolForKey:@"isFetchEnabled"]];
+
+ return self;
+}
+- (void)encodeWithKeyValueArchiver:(EOKeyValueArchiver *)_archiver {
+ // TODO: do we need to produce the reference on our own?
+ [_archiver encodeReferenceToObject:[self managedObjectContext]
+ forKey:@"managedObjectContext"];
+
+ [_archiver encodeObject:[self fetchSpecification]
+ forKey:@"fetchSpecification"];
+ [_archiver encodeObject:[self entity]
+ forKey:@"entity"];
+ [_archiver encodeObject:[self auxiliaryQualifier]
+ forKey:@"auxiliaryQualifier"];
+ [_archiver encodeObject:[self qualifierBindings]
+ forKey:@"qualifierBindings"];
+ [_archiver encodeBool:[self isFetchEnabled]
+ forKey:@"isFetchEnabled"];
+}
+
/* description */
- (NSString *)description {
@implementation EOFetchSpecification(CoreData)
- (id)initWithFetchRequest:(NSFetchRequest *)_fr {
-#warning IMPLEMENT ME
- return nil;
+ NSMutableArray *so;
+ EOQualifier *q;
+ NSArray *sd;
+ unsigned count;
+
+ if (_fr == nil) {
+ [self release];
+ return nil;
+ }
+
+ /* convert sort descriptors */
+
+ sd = [_fr sortDescriptors];
+ so = nil;
+ if ((count = [sd count]) > 0) {
+ unsigned i;
+
+ so = [[NSMutableArray alloc] initWithCapacity:count];
+ for (i = 0; i < count; i++) {
+ EOSortOrdering *soo;
+
+ soo = [[EOSortOrdering alloc] initWithSortDescriptor:
+ [sd objectAtIndex:i]];
+ if (soo == nil) {
+ soo = [sd objectAtIndex:i]; /* oh well, this is sneaky */
+ NSLog(@"WARNING(%s): could not convert NSSortDescriptor to "
+ @"EOSortOrdering: %@", __PRETTY_FUNCTION__, soo);
+ }
+ [so addObject:soo];
+ [soo release];
+ }
+ }
+
+ /* convert predicate */
+
+ q = [EOQualifier qualifierForPredicate:[_fr predicate]];
+
+ /* create object */
+
+ // TODO: maybe add 'affectedStores' as a hint?
+ self = [self initWithEntityName:[[_fr entity] name]
+ qualifier:q sortOrderings:so
+ usesDistinct:YES isDeep:NO
+ hints:nil];
+ [so release]; so = nil;
+
+ [self setFetchLimit:[_fr fetchLimit]];
+ return self;
}
- (NSArray *)sortOrderingsAsSortDescriptors {
}
@end /* EOFetchSpecification(CoreData) */
+
+
+@implementation NSFetchRequest(EOCoreData)
+
+- (NSFetchRequest *)fetchRequestWithEntity:(NSEntityDescription *)_entity {
+ return self;
+}
+- (NSFetchRequest *)fetchRequestWithModel:(NSManagedObjectModel *)_model {
+ return self;
+}
+
+@end /* NSFetchRequest(EOCoreData) */
--- /dev/null
+/*
+ Copyright (C) 2005 SKYRIX Software AG
+
+ This file is part of SOPE.
+
+ SOPE is free software; you can redistribute it and/or modify it under
+ the terms of the GNU Lesser General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ SOPE is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with SOPE; see the file COPYING. If not, write to the
+ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+*/
+
+#include "EOQualifier+CoreData.h"
+#include "NSPredicate+EO.h"
+#include "NSExpression+EO.h"
+#include "common.h"
+
+@implementation EOKeyComparisonQualifier(CoreData)
+
++ (EOQualifier *)qualifierForComparisonPredicate:(NSComparisonPredicate *)_p {
+ SEL sel;
+
+ if ((sel = [self eoSelectorForForComparisonPredicate:_p]) == nil)
+ return (EOQualifier *)_p;
+
+ return [[[self alloc] initWithLeftKey:[[_p leftExpression] keyPath]
+ operatorSelector:sel
+ rightKey:[[_p rightExpression] keyPath]] autorelease];
+}
+
+- (NSPredicate *)asPredicate {
+ NSLog(@"TODO(%s): implement me for class %@!", __PRETTY_FUNCTION__,
+ NSStringFromClass([self class]));
+ return nil;
+}
+
+/* CoreData compatibility */
+
+- (NSComparisonPredicateModifier)comparisonPredicateModifier {
+ return NSDirectPredicateModifier;
+}
+
+- (NSPredicateOperatorType)predicateOperatorType {
+ return [[self class] predicateOperatorTypeForEOSelector:[self selector]];
+}
+
+- (unsigned)options {
+ return (SEL_EQ([self selector], EOQualifierOperatorCaseInsensitiveLike))
+ ? NSCaseInsensitivePredicateOption : 0;
+}
+
+- (SEL)customSelector {
+ return [self predicateOperatorType] == NSCustomSelectorPredicateOperatorType
+ ? [self selector] : nil;
+}
+
+@end /* EOKeyComparisonQualifier(CoreData) */
--- /dev/null
+/*
+ Copyright (C) 2005 SKYRIX Software AG
+
+ This file is part of SOPE.
+
+ SOPE is free software; you can redistribute it and/or modify it under
+ the terms of the GNU Lesser General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ SOPE is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with SOPE; see the file COPYING. If not, write to the
+ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+*/
+
+#include "EOQualifier+CoreData.h"
+#include "NSPredicate+EO.h"
+#include "NSExpression+EO.h"
+#include "common.h"
+
+@implementation EOKeyValueQualifier(CoreData)
+
++ (EOQualifier *)qualifierForComparisonPredicate:(NSComparisonPredicate *)_p {
+ SEL sel;
+
+ if ((sel = [self eoSelectorForForComparisonPredicate:_p]) == nil)
+ return (EOQualifier *)_p;
+
+ return [[[self alloc] initWithKey:[[_p leftExpression] keyPath]
+ operatorSelector:sel
+ value:[[_p rightExpression] constantValue]]
+ autorelease];
+}
+
+- (NSPredicate *)asPredicate {
+ NSLog(@"TODO(%s): implement me for class %@!", __PRETTY_FUNCTION__,
+ NSStringFromClass([self class]));
+ return nil;
+}
+
+/* CoreData compatibility */
+
+- (NSComparisonPredicateModifier)comparisonPredicateModifier {
+ return NSDirectPredicateModifier;
+}
+
+- (NSPredicateOperatorType)predicateOperatorType {
+ return [[self class] predicateOperatorTypeForEOSelector:[self selector]];
+}
+
+- (unsigned)options {
+ return (SEL_EQ([self selector], EOQualifierOperatorCaseInsensitiveLike))
+ ? NSCaseInsensitivePredicateOption : 0;
+}
+
+- (SEL)customSelector {
+ return [self predicateOperatorType] == NSCustomSelectorPredicateOperatorType
+ ? [self selector] : nil;
+}
+
+@end /* EOKeyValueQualifier(CoreData) */
#ifndef __EOQualifier_CoreData_H__
#define __EOQualifier_CoreData_H__
+#import <Foundation/NSPredicate.h>
+#import <Foundation/NSComparisonPredicate.h>
#include <EOControl/EOQualifier.h>
/*
object.
*/
-@class NSPredicate;
+@class NSArray;
+@class NSPredicate, NSExpression, NSComparisonPredicate, NSCompoundPredicate;
@interface EOQualifier(CoreData)
-- (id)initWithPredicate:(NSPredicate *)_predicate;
++ (EOQualifier *)qualifierForPredicate:(NSPredicate *)_predicate;
- (NSPredicate *)asPredicate;
+- (NSExpression *)asExpression;
+/* support methods */
+
++ (SEL)eoSelectorForForComparisonPredicate:(NSComparisonPredicate *)_p;
++ (NSPredicateOperatorType)predicateOperatorTypeForEOSelector:(SEL)_sel;
+
+/* CoreData compatibility */
+
++ (NSPredicate *)andPredicateWithSubpredicates:(NSArray *)_sub;
++ (NSPredicate *)orPredicateWithSubpredicates:(NSArray *)_sub;
++ (NSPredicate *)notPredicateWithSubpredicate:(id)_predicate;
+
+@end
+
+#import <Foundation/Foundation.h>
+
+
+/* compound qualifiers */
+
+@interface EOAndQualifier(CoreData)
+- (NSCompoundPredicateType)compoundPredicateType;
+@end
+
+@interface EOOrQualifier(CoreData)
+- (NSCompoundPredicateType)compoundPredicateType;
+@end
+
+@interface EONotQualifier(CoreData)
+- (NSCompoundPredicateType)compoundPredicateType;
+@end
+
+
+/* comparison qualifiers */
+
+@interface EOKeyValueQualifier(CoreData)
++ (EOQualifier *)qualifierForComparisonPredicate:(NSComparisonPredicate *)_p;
+- (NSComparisonPredicateModifier)comparisonPredicateModifier;
+- (NSPredicateOperatorType)predicateOperatorType;
+- (SEL)customSelector;
+- (unsigned)options;
+@end
+
+@interface EOKeyComparisonQualifier(CoreData)
++ (EOQualifier *)qualifierForComparisonPredicate:(NSComparisonPredicate *)_p;
+- (NSComparisonPredicateModifier)comparisonPredicateModifier;
+- (NSPredicateOperatorType)predicateOperatorType;
+- (SEL)customSelector;
+- (unsigned)options;
@end
#endif /* __EOQualifier_CoreData_H__ */
*/
#include "EOQualifier+CoreData.h"
+#include "NSPredicate+EO.h"
+#include "NSExpression+EO.h"
#include "common.h"
+/*
+ CoreData / Foundation EOF
+ Predicates:
+ NSComparisonPredicate EOKeyValueQualifier / EOKeyComparisonQualifier
+ NSCompoundPredicate EOAndQualifier / EOOrQualifier / EONotQualifier
+
+ NSExpressions:
+ - constant
+ - evaluatedObject
+ - variable EOQualifierVariable
+ - keypath
+ - function
+
+ EOF operators:
+ EOQualifierOperatorEqual;
+ EOQualifierOperatorNotEqual;
+ EOQualifierOperatorLessThan;
+ EOQualifierOperatorGreaterThan;
+ EOQualifierOperatorLessThanOrEqualTo;
+ EOQualifierOperatorGreaterThanOrEqualTo;
+ EOQualifierOperatorContains;
+ EOQualifierOperatorLike;
+ EOQualifierOperatorCaseInsensitiveLike;
+*/
+
@implementation EOQualifier(CoreData)
-- (id)initWithPredicate:(NSPredicate *)_predicate {
-#warning IMPLEMENT ME
- NSLog(@"TODO(%s): implement me!", __PRETTY_FUNCTION__);
- [self release];
++ (NSPredicateOperatorType)predicateOperatorTypeForEOSelector:(SEL)_sel {
+ if (SEL_EQ(_sel, EOQualifierOperatorEqual))
+ return NSEqualToPredicateOperatorType;
+ if (SEL_EQ(_sel, EOQualifierOperatorNotEqual))
+ return NSNotEqualToPredicateOperatorType;
+
+ if (SEL_EQ(_sel, EOQualifierOperatorLessThan))
+ return NSLessThanPredicateOperatorType;
+ if (SEL_EQ(_sel, EOQualifierOperatorGreaterThan))
+ return NSGreaterThanPredicateOperatorType;
+
+ if (SEL_EQ(_sel, EOQualifierOperatorLessThanOrEqualTo))
+ return NSLessThanOrEqualToPredicateOperatorType;
+ if (SEL_EQ(_sel, EOQualifierOperatorGreaterThanOrEqualTo))
+ return NSGreaterThanOrEqualToPredicateOperatorType;
+
+ if (SEL_EQ(_sel, EOQualifierOperatorContains))
+ return NSInPredicateOperatorType;
+
+ if (SEL_EQ(_sel, EOQualifierOperatorLike) ||
+ SEL_EQ(_sel, EOQualifierOperatorCaseInsensitiveLike))
+ return NSLikePredicateOperatorType;
+
+ return NSCustomSelectorPredicateOperatorType;
+}
+
++ (SEL)eoSelectorForForComparisonPredicate:(NSComparisonPredicate *)_p {
+ BOOL hasOpt;
+ SEL sel = NULL;
+
+ if (_p == nil)
+ return NULL;
+
+ hasOpt = [_p options] != 0 ? YES : NO;
+
+ // TODO: need to check options
+
+ switch ([_p predicateOperatorType]) {
+ case NSCustomSelectorPredicateOperatorType:
+ sel = hasOpt ? NULL : [_p customSelector];
+ break;
+
+ case NSLessThanPredicateOperatorType:
+ sel = hasOpt ? NULL : EOQualifierOperatorLessThan; break;
+ case NSLessThanOrEqualToPredicateOperatorType:
+ sel = hasOpt ? NULL : EOQualifierOperatorLessThanOrEqualTo; break;
+ case NSGreaterThanPredicateOperatorType:
+ sel = hasOpt ? NULL : EOQualifierOperatorGreaterThan; break;
+ case NSGreaterThanOrEqualToPredicateOperatorType:
+ sel = hasOpt ? NULL : EOQualifierOperatorGreaterThanOrEqualTo; break;
+
+ case NSEqualToPredicateOperatorType:
+ sel = hasOpt ? NULL : EOQualifierOperatorEqual; break;
+ case NSNotEqualToPredicateOperatorType:
+ sel = hasOpt ? NULL : EOQualifierOperatorNotEqual; break;
+
+ case NSLikePredicateOperatorType:
+ sel = ([_p options] == NSCaseInsensitivePredicateOption)
+ ? EOQualifierOperatorCaseInsensitiveLike
+ : (hasOpt ? NULL : EOQualifierOperatorLike);
+ break;
+
+ case NSInPredicateOperatorType:
+ // TODO: for arrays: containsObject:, for strings: containsString:
+ sel = hasOpt ? NULL : EOQualifierOperatorContains; break;
+
+ case NSBeginsWithPredicateOperatorType:
+ sel = hasOpt ? NULL : @selector(hasPrefix:); break;
+ case NSEndsWithPredicateOperatorType:
+ sel = hasOpt ? NULL : @selector(hasSuffix:); break;
+
+ /* unsupported predicates */
+ case NSMatchesPredicateOperatorType:
+ // TODO
+ default:
+ sel = NULL;
+ break;
+ }
+
+ if (sel == NULL) {
+ NSLog(@"ERROR(%s): cannot map NSComparisonPredicate to "
+ @"EOQualifier selector: %@",
+ __PRETTY_FUNCTION__, _p);
+ }
+ return sel;
+}
+
++ (EOQualifier *)qualifierForPredicate:(NSPredicate *)_predicate {
+ if (_predicate == nil)
+ return nil;
+
+ if ([_predicate respondsToSelector:@selector(asQualifier)])
+ return [_predicate asQualifier];
+
+ NSLog(@"ERROR(%s): cannot convert NSPredicate class %@!",
+ __PRETTY_FUNCTION__,
+ NSStringFromClass([self class]));
return nil;
}
+- (EOQualifier *)asQualifier {
+ return self;
+}
+
- (NSPredicate *)asPredicate {
-#warning IMPLEMENT ME
- NSLog(@"TODO(%s): implement me!", __PRETTY_FUNCTION__);
+ NSLog(@"TODO(%s): implement me for class %@!", __PRETTY_FUNCTION__,
+ NSStringFromClass([self class]));
+ return nil;
+}
+
+- (NSExpression *)asExpression {
return nil;
}
+
+/* CoreData compatibility */
+
++ (NSPredicate *)andPredicateWithSubpredicates:(NSArray *)_sub {
+ return [NSCompoundPredicate andPredicateWithSubpredicates:
+ [_sub valueForKey:@"asPredicate"]];
+}
+
++ (NSPredicate *)orPredicateWithSubpredicates:(NSArray *)_sub {
+ return [NSCompoundPredicate orPredicateWithSubpredicates:
+ [_sub valueForKey:@"asPredicate"]];
+}
+
++ (NSPredicate *)notPredicateWithSubpredicate:(id)_predicate {
+ return [NSCompoundPredicate notPredicateWithSubpredicate:
+ [_predicate asPredicate]];
+}
+
@end /* EOQualifier(CoreData) */
- (id)initWithSortDescriptor:(NSSortDescriptor *)_descriptor;
- (NSSortDescriptor *)asSortDescriptor;
+/* converting selectors */
+
+- (BOOL)isAscendingEOSortSelector:(SEL)_sel;
+- (SEL)cdSortSelectorFromEOSortSelector:(SEL)_sel;
+
@end
#endif /* __EOSortOrdering_CoreData_H__ */
@implementation EOSortOrdering(CoreData)
- (id)initWithSortDescriptor:(NSSortDescriptor *)_descriptor {
-#warning IMPLEMENT ME
- NSLog(@"TODO(%s): implement me!", __PRETTY_FUNCTION__);
- [self release];
- return nil;
+ SEL sel;
+
+ if (_descriptor == nil) {
+ [self release];
+ return nil;
+ }
+
+ sel = [_descriptor selector];
+ if (SEL_EQ(sel, @selector(compare:))) {
+ sel = [_descriptor ascending]
+ ? EOCompareAscending
+ : EOCompareDescending;
+ }
+ else if (SEL_EQ(sel, @selector(caseInsensitiveCompare:))) {
+ sel = [_descriptor ascending]
+ ? EOCompareCaseInsensitiveAscending
+ : EOCompareCaseInsensitiveDescending;
+ }
+ else {
+ if (![_descriptor ascending]) {
+ NSLog(@"WARNING(%s): cannot representing descending selector in "
+ @"NSSortDescriptor: %@", __PRETTY_FUNCTION__, _descriptor);
+ }
+ }
+
+ return [self initWithKey:[_descriptor key] selector:sel];
+}
+
+- (BOOL)isAscendingEOSortSelector:(SEL)_sel {
+ if (SEL_EQ(_sel, EOCompareDescending)) return NO;
+ if (SEL_EQ(_sel, EOCompareCaseInsensitiveAscending)) return NO;
+ return YES;
+}
+
+- (SEL)cdSortSelectorFromEOSortSelector:(SEL)_sel {
+ if (SEL_EQ(_sel, EOCompareAscending)) return @selector(compare:);
+ if (SEL_EQ(_sel, EOCompareDescending)) return @selector(compare:);
+
+ if (SEL_EQ(_sel, EOCompareCaseInsensitiveAscending))
+ return @selector(caseInsensitiveCompare:);
+ if (SEL_EQ(_sel, EOCompareCaseInsensitiveDescending))
+ return @selector(caseInsensitiveCompare:);
+
+ return _sel;
}
- (NSSortDescriptor *)asSortDescriptor {
-#warning IMPLEMENT ME
- NSLog(@"TODO(%s): implement me!", __PRETTY_FUNCTION__);
- return nil;
+ SEL sel;
+
+ sel = [self selector];
+
+ return [[[NSSortDescriptor alloc]
+ initWithKey:[self key]
+ ascending:[self isAscendingEOSortSelector:sel]
+ selector:[self cdSortSelectorFromEOSortSelector:sel]] autorelease];
}
@end /* EOSortOrdering(CoreData) */
+
+
+@implementation NSSortDescriptor(EOCoreData)
+
+- (NSSortDescriptor *)asSortDescriptor {
+ return self;
+}
+
+@end /* NSSortDescriptor(EOCoreData) */
EOFetchSpecification+CoreData.h \
EOQualifier+CoreData.h \
EOSortOrdering+CoreData.h \
+ NSExpression+EO.h \
+ NSPredicate+EO.h \
libEOCoreData_OBJC_FILES = \
- EOCoreDataSource.m \
- EOFetchSpecification+CoreData.m \
- EOQualifier+CoreData.m \
- EOSortOrdering+CoreData.m \
+ EOCoreDataSource.m \
+ EOFetchSpecification+CoreData.m \
+ EOQualifier+CoreData.m \
+ EOSortOrdering+CoreData.m \
+ NSExpression+EO.m \
+ NSPredicate+EO.m \
+ EOKeyValueQualifier+CoreData.m \
+ EOKeyComparisonQualifier+CoreData.m \
+ EOCompoundQualifiers.m \
-include GNUmakefile.preamble
--- /dev/null
+/*
+ Copyright (C) 2005 SKYRIX Software AG
+
+ This file is part of SOPE.
+
+ SOPE is free software; you can redistribute it and/or modify it under
+ the terms of the GNU Lesser General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ SOPE is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with SOPE; see the file COPYING. If not, write to the
+ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+*/
+
+#ifndef __NSExpression_EO_H__
+#define __NSExpression_EO_H__
+
+#import <Foundation/NSExpression.h>
+
+/*
+ NSExpression(EO)
+
+ Convert an NSExpression to an EOQualifier.
+*/
+
+@class NSExpression;
+@class EOQualifier;
+
+@interface NSExpression(EO)
+
+- (NSPredicate *)asPredicate;
+- (NSExpression *)asExpression;
+
+@end
+
+#endif /* __NSExpression_EO_H__ */
--- /dev/null
+/*
+ Copyright (C) 2005 SKYRIX Software AG
+
+ This file is part of SOPE.
+
+ SOPE is free software; you can redistribute it and/or modify it under
+ the terms of the GNU Lesser General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ SOPE is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with SOPE; see the file COPYING. If not, write to the
+ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+*/
+
+#import <Foundation/NSExpression.h>
+#include "common.h"
+
+@implementation NSExpression(EOCoreData)
+
+- (NSPredicate *)asPredicate {
+ return nil;
+}
+- (NSExpression *)asExpression {
+ return self;
+}
+
+@end /* NSPredicate(EOCoreData) */
--- /dev/null
+/*
+ Copyright (C) 2005 SKYRIX Software AG
+
+ This file is part of SOPE.
+
+ SOPE is free software; you can redistribute it and/or modify it under
+ the terms of the GNU Lesser General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ SOPE is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with SOPE; see the file COPYING. If not, write to the
+ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+*/
+
+#ifndef __NSPredicate_EO_H__
+#define __NSPredicate_EO_H__
+
+#import <Foundation/NSPredicate.h>
+
+/*
+ NSPredicate(EO)
+
+ Convert an NSPredicate to an EOQualifier.
+*/
+
+@class NSExpression;
+@class EOQualifier;
+
+@interface NSPredicate(EO)
+
+- (NSPredicate *)asPredicate;
+- (NSExpression *)asExpression;
+- (EOQualifier *)asQualifier;
+
+@end
+
+#endif /* __NSPredicate_EO_H__ */
--- /dev/null
+/*
+ Copyright (C) 2005 SKYRIX Software AG
+
+ This file is part of SOPE.
+
+ SOPE is free software; you can redistribute it and/or modify it under
+ the terms of the GNU Lesser General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ SOPE is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with SOPE; see the file COPYING. If not, write to the
+ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+*/
+
+#include "NSPredicate+EO.h"
+#include "EOQualifier+CoreData.h"
+#include "common.h"
+
+@implementation NSPredicate(EOCoreData)
+
+- (NSPredicate *)asPredicate {
+ return self;
+}
+- (NSExpression *)asExpression {
+ return nil;
+}
+
+@end /* NSPredicate(EOCoreData) */
+
+
+@implementation NSCompoundPredicate(EOCoreData)
+
+- (EOQualifier *)asQualifier {
+ /*
+ Compound predicates join other predicates, they do not deal with
+ expressions.
+ */
+ NSMutableArray *sq;
+ NSArray *sp;
+ unsigned i, count;
+ Class clazz;
+ BOOL isNot = NO;
+ EOQualifier *q;
+
+ sp = [self subpredicates];
+ count = [sp count];
+
+ switch ([self compoundPredicateType]) {
+ case NSNotPredicateType:
+ isNot = YES;
+ clazz = [EONotQualifier class];
+ break;
+ case NSAndPredicateType:
+ clazz = [EOAndQualifier class];
+ break;
+ case NSOrPredicateType:
+ clazz = [EOOrQualifier class];
+ break;
+ default:
+ NSLog(@"ERROR(%s): unknown compound predicate type: %@",
+ __PRETTY_FUNCTION__, self);
+ return nil;
+ }
+
+ if (count == 0)
+ return [[[clazz alloc] init] autorelease];
+
+ if (count == 1) {
+ q = [sp objectAtIndex:0];
+ return (isNot)
+ ? [[[EONotQualifier alloc] initWithQualifier:q] autorelease]
+ : q;
+ }
+
+ sq = [[NSMutableArray alloc] initWithCapacity:count];
+
+ for (i = 0; i < count; i++) {
+ q = [EOQualifier qualifierForPredicate:[sp objectAtIndex:i]];
+ if (q == nil) {
+ q = [sp objectAtIndex:i];
+ NSLog(@"ERROR(%s): could not convert predicate to qualifier: %@",
+ __PRETTY_FUNCTION__, q);
+ }
+
+ if (isNot)
+ q = [[EONotQualifier alloc] initWithQualifier:q];
+
+ [sq addObject:q];
+ if (isNot) [q release];
+
+ q = nil;
+ }
+
+ q = [[(isNot ? [EOAndQualifier class] : clazz) alloc] initWithQualifier:q];
+ [sq release];
+ return [q autorelease];
+}
+
+@end /* NSCompoundPredicate(EOCoreData) */
+
+
+@implementation NSComparisonPredicate(EOCoreData)
+
+- (EOQualifier *)asQualifier {
+ NSExpression *lhs, *rhs;
+
+ lhs = [self leftExpression];
+ rhs = [self rightExpression];
+
+ // TODO: need to check predicate modifiers
+ // TODO: add support for variables
+
+ if ([rhs expressionType] == NSKeyPathExpressionType) {
+ if ([lhs expressionType] == NSConstantValueExpressionType)
+ return [EOKeyValueQualifier qualifierForComparisonPredicate:self];
+
+ if ([lhs expressionType] == NSKeyPathExpressionType)
+ return [EOKeyComparisonQualifier qualifierForComparisonPredicate:self];
+ }
+
+ NSLog(@"ERROR(%s): cannot map NSComparisonPredicate to EOQualifier: %@",
+ __PRETTY_FUNCTION__, self);
+ return (id)self;
+}
+
+@end /* NSComparisonPredicate(EOCoreData) */
# version file
-SUBMINOR_VERSION:=1
+SUBMINOR_VERSION:=2
object = __value;}})
#endif
+
+#if GNU_RUNTIME
+# include <objc/objc.h>
+#endif
+
+#ifndef SEL_EQ
+# if GNU_RUNTIME
+# define SEL_EQ(sel1,sel2) sel_eq(sel1,sel2)
+# else
+# define SEL_EQ(sel1,sel2) (sel1 == sel2)
+# endif
+#endif
+
#endif /* __EOCoreData_COMMON_H__ */