]> err.no Git - sope/blob - sope-core/EOControl/EOFetchSpecification.m
synced with latest additions and bumped framework versions
[sope] / sope-core / EOControl / EOFetchSpecification.m
1 /*
2   Copyright (C) 2000-2005 SKYRIX Software AG
3
4   This file is part of SOPE.
5
6   SOPE is free software; you can redistribute it and/or modify it under
7   the terms of the GNU Lesser General Public License as published by the
8   Free Software Foundation; either version 2, or (at your option) any
9   later version.
10
11   SOPE is distributed in the hope that it will be useful, but WITHOUT ANY
12   WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14   License for more details.
15
16   You should have received a copy of the GNU Lesser General Public
17   License along with SOPE; see the file COPYING.  If not, write to the
18   Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19   02111-1307, USA.
20 */
21
22 #include "EOFetchSpecification.h"
23 #include "EOQualifier.h"
24 #include "EOSortOrdering.h"
25 #include "common.h"
26
27 @implementation EOFetchSpecification
28
29 + (EOFetchSpecification *)fetchSpecificationWithEntityName:(NSString *)_ename
30   qualifier:(EOQualifier *)_qualifier
31   sortOrderings:(NSArray *)_sortOrderings
32 {
33   EOFetchSpecification *fs = nil;
34
35   fs = [[self alloc] initWithEntityName:_ename
36                      qualifier:_qualifier
37                      sortOrderings:_sortOrderings
38                      usesDistinct:NO isDeep:NO
39                      hints:nil];
40   return [fs autorelease];
41 }
42
43 - (id)initWithEntityName:(NSString *)_name
44   qualifier:(EOQualifier *)_qualifier
45   sortOrderings:(NSArray *)_sortOrderings
46   usesDistinct:(BOOL)_dflag isDeep:(BOOL)_isDeep
47   hints:(NSDictionary *)_hints
48 {
49   if ((self = [super init])) {
50     self->entityName    = [_name copyWithZone:[self zone]];
51     self->qualifier     = [_qualifier     retain];
52     self->sortOrderings = [_sortOrderings retain];
53     self->fetchLimit    = 0;
54     self->hints         = [_hints retain];
55     
56     self->fsFlags.usesDistinct = _dflag  ? 1 : 0;
57     self->fsFlags.deep         = _isDeep ? 1 : 0;
58   }
59   return self;
60 }
61 - (id)initWithEntityName:(NSString *)_name
62   qualifier:(EOQualifier *)_qualifier
63   sortOrderings:(NSArray *)_sortOrderings
64   usesDistinct:(BOOL)_dflag
65 {
66   // DEPRECATED
67   // Note: this does not work with GDL2! (and probably not with EOF 4)
68   return [self initWithEntityName:_name qualifier:_qualifier 
69                sortOrderings:_sortOrderings usesDistinct:_dflag
70                isDeep:NO hints:nil];
71 }
72
73 - (id)init {
74   if ((self = [super init])) {
75   }
76   return self;
77 }
78
79 - (void)dealloc {
80   [self->hints         release];
81   [self->entityName    release];
82   [self->qualifier     release];
83   [self->sortOrderings release];
84   [super dealloc];
85 }
86
87 /* accessors */
88
89 - (void)setEntityName:(NSString *)_name {
90   id tmp;
91   
92   if (_name == self->entityName)
93     return;
94   
95   tmp = self->entityName;
96   self->entityName = [_name copyWithZone:[self zone]];
97   [tmp release];
98 }
99 - (NSString *)entityName {
100   return self->entityName;
101 }
102
103 - (void)setQualifier:(EOQualifier *)_qualifier {
104   ASSIGN(self->qualifier, _qualifier);
105 }
106 - (EOQualifier *)qualifier {
107   return self->qualifier;
108 }
109
110 - (void)setSortOrderings:(NSArray *)_orderings {
111   ASSIGN(self->sortOrderings, _orderings);
112 }
113 - (NSArray *)sortOrderings {
114   return self->sortOrderings;
115 }
116
117 - (void)setUsesDistinct:(BOOL)_flag {
118   self->fsFlags.usesDistinct = _flag ? 1 : 0;
119 }
120 - (BOOL)usesDistinct {
121   return self->fsFlags.usesDistinct ? YES : NO;
122 }
123
124 - (void)setLocksObjects:(BOOL)_flag {
125   self->fsFlags.locksObjects = _flag ? 1 : 0;
126 }
127 - (BOOL)locksObjects {
128   return self->fsFlags.locksObjects ? YES : NO;
129 }
130
131 - (void)setIsDeep:(BOOL)_flag {
132   self->fsFlags.deep = _flag ? 1 : 0;
133 }
134 - (BOOL)isDeep {
135   return self->fsFlags.deep ? YES : NO;
136 }
137
138 - (void)setFetchLimit:(unsigned)_limit {
139   self->fetchLimit = _limit;
140 }
141 - (unsigned)fetchLimit {
142   return self->fetchLimit;
143 }
144
145 - (void)setHints:(NSDictionary *)_hints {
146   ASSIGN(self->hints, _hints);
147 }
148 - (NSDictionary *)hints {
149   return self->hints;
150 }
151
152 /* bindings */
153
154 - (EOFetchSpecification *)
155   fetchSpecificationWithQualifierBindings:(NSDictionary *)_bindings
156 {
157   EOQualifier          *q     = nil;
158   EOFetchSpecification *newfs = nil;
159
160   q     = [[self qualifier] qualifierWithBindings:_bindings
161                             requiresAllVariables:NO];
162   newfs = [[[self class] alloc]
163                   initWithEntityName:[self entityName]
164                   qualifier:q
165                   sortOrderings:[self sortOrderings]
166                   usesDistinct:[self usesDistinct]];
167   
168   [newfs setLocksObjects:[self locksObjects]];
169   [newfs setFetchLimit:[self fetchLimit]];
170   
171   return [newfs autorelease];
172 }
173
174 /* GDL2 compatibility */
175
176 - (EOFetchSpecification *)
177   fetchSpecificationByApplyingBindings:(NSDictionary *)_bindings
178 {
179   return [self fetchSpecificationWithQualifierBindings:_bindings];
180 }
181
182 /* NSCopying */
183
184 - (id)copyWithZone:(NSZone *)_zone {
185   EOFetchSpecification *fspec;
186   NSDictionary *hdict;
187   
188   hdict = [[self hints] copy];
189   
190   fspec = [[[self class] alloc] initWithEntityName:[self entityName]
191                                 qualifier:[self qualifier]
192                                 sortOrderings:[self sortOrderings]
193                                 usesDistinct:[self usesDistinct]
194                                 isDeep:[self isDeep] hints:hdict];
195   [fspec setLocksObjects:[self locksObjects]];
196   [fspec setFetchLimit:[self fetchLimit]];
197   [hdict release];
198   
199   return fspec;
200 }
201
202 /* Equality */
203
204 - (BOOL)isEqualToFetchSpecification:(EOFetchSpecification *)_fspec {
205   id t1, t2;
206   if (_fspec == self)
207     return YES;
208
209   t1 = [self entityName];
210   t2 = [_fspec entityName];
211   if (t1 != t2) {
212     if (![t1 isEqualToString:t2])
213       return NO;
214   }
215   
216   t1 = [self sortOrderings];
217   t2 = [_fspec sortOrderings];
218   if (t1 != t2) {
219     if (![t1 isEqual:t2])
220       return NO;
221   }
222
223   t1 = [self qualifier];
224   t2 = [_fspec qualifier];
225   if (t1 != t2) {
226     if (![t1 isEqual:t2])
227       return NO;
228   }
229   
230   if ([self usesDistinct] != [_fspec usesDistinct])
231     return NO;
232   if ([self locksObjects] != [_fspec locksObjects])
233     return NO;
234   if ([self fetchLimit] != [_fspec fetchLimit])
235     return NO;
236
237   t1 = [self hints];
238   t2 = [_fspec hints];
239   if (t1 != t2) {
240     if (![t1 isEqual:t2])
241       return NO;
242   }
243   
244   return YES;
245 }
246 - (BOOL)isEqual:(id)_other {
247   if ([_other isKindOfClass:[EOFetchSpecification class]])
248     return [self isEqualToFetchSpecification:_other];
249   
250   return NO;
251 }
252
253 /* remapping keys */
254
255 - (EOFetchSpecification *)fetchSpecificationByApplyingKeyMap:(NSDictionary *)_m {
256   NSAutoreleasePool    *pool;
257   EOFetchSpecification *fs;
258   NSMutableDictionary  *lHints;
259   EOQualifier    *q = nil;
260   NSMutableArray *o = nil;
261
262   pool = [[NSAutoreleasePool alloc] init];
263   
264   /* process qualifier */
265   
266   q = [self->qualifier qualifierByApplyingKeyMap:_m];
267   
268   /* process attributes */
269   
270   if (self->hints) {
271     NSArray  *a;
272     unsigned len;
273     
274     a = [self->hints objectForKey:@"attributes"];
275     if ((len = [a count]) > 0) {
276       NSMutableArray *ma;
277       unsigned i;
278       
279       ma = [[NSMutableArray alloc] initWithCapacity:(len + 1)];
280       for (i = 0; i < len; i++) {
281         NSString *key, *tkey;
282         
283         key  = [a objectAtIndex:i];
284         tkey = [_m objectForKey:key];
285         
286         [ma addObject:(tkey ? tkey : key)];
287       }
288       
289       lHints = [self->hints mutableCopy];
290       [lHints setObject:ma forKey:@"attributes"];
291       [ma release];
292     }
293     else
294       lHints = [self->hints retain];
295   }
296   else 
297     lHints = nil;
298   
299   /* process orderings */
300   
301   if (self->sortOrderings) {
302     unsigned i, len;
303     
304     len = [self->sortOrderings count];
305     o   = [[NSMutableArray alloc] initWithCapacity:len];
306     for (i = 0; i < len; i++) {
307       EOSortOrdering *so, *tso;
308       
309       so  = [self->sortOrderings objectAtIndex:i];
310       tso = [so sortOrderingByApplyingKeyMap:_m];
311       [o addObject:tso ? tso : so];
312     }
313   }
314   else
315     o = nil;
316   
317   /* construct result */
318   
319   fs = [[EOFetchSpecification alloc] initWithEntityName:self->entityName
320                                      qualifier:q
321                                      sortOrderings:o
322                                      usesDistinct:[self usesDistinct]
323                                      isDeep:[self isDeep]
324                                      hints:[self hints]];
325   [fs setLocksObjects:[self locksObjects]];
326   [fs setFetchLimit:self->fetchLimit];
327   if (lHints) {
328     [fs setHints:lHints];
329     [lHints release];
330   }
331   [o release];
332   [pool release];
333   return [fs autorelease];
334 }
335
336 /* key/value archiving */
337
338 - (id)initWithKeyValueUnarchiver:(EOKeyValueUnarchiver *)_unarchiver {
339   if ((self = [super init]) != nil) {
340     self->entityName = [[_unarchiver decodeObjectForKey:@"entityName"] copy];
341     self->qualifier  = [[_unarchiver decodeObjectForKey:@"qualifier"]  retain];
342     self->hints      = [[_unarchiver decodeObjectForKey:@"hints"] copy];
343     self->sortOrderings = 
344       [[_unarchiver decodeObjectForKey:@"sortOrderings"] retain];
345     
346     self->fetchLimit = [_unarchiver decodeIntForKey:@"fetchLimit"];
347     
348     self->fsFlags.usesDistinct = 
349       [_unarchiver decodeBoolForKey:@"usesDistinct"] ? 1 : 0;
350     self->fsFlags.locksObjects = 
351       [_unarchiver decodeBoolForKey:@"locksObjects"] ? 1 : 0;
352     self->fsFlags.deep = 
353       [_unarchiver decodeBoolForKey:@"deep"] ? 1 : 0;
354   }
355   return self;
356 }
357 - (void)encodeWithKeyValueArchiver:(EOKeyValueArchiver *)_archiver {
358   [_archiver encodeObject:[self entityName]    forKey:@"entityName"];
359   [_archiver encodeObject:[self qualifier]     forKey:@"qualifier"];
360   [_archiver encodeObject:[self hints]         forKey:@"hints"];
361   [_archiver encodeObject:[self sortOrderings] forKey:@"sortOrderings"];
362
363   [_archiver encodeInt:[self fetchLimit] forKey:@"fetchLimit"];
364   
365   [_archiver encodeBool:self->fsFlags.usesDistinct forKey:@"usesDistinct"];
366   [_archiver encodeBool:self->fsFlags.locksObjects forKey:@"locksObjects"];
367   [_archiver encodeBool:self->fsFlags.deep         forKey:@"deep"];
368 }
369
370 /* description */
371
372 - (NSString *)description {
373   NSMutableString *ms;
374   id tmp;
375   
376   ms = [NSMutableString stringWithCapacity:128];
377   [ms appendFormat:@"<%@[0x%08X]:", NSStringFromClass([self class]), self];
378
379   if ((tmp = [self entityName]))
380     [ms appendFormat:@" entity=%@", tmp];
381   if ((tmp = [self qualifier]))
382     [ms appendFormat:@" qualifier=%@", tmp];
383   
384   if ((tmp = [self sortOrderings]))
385     [ms appendFormat:@" orderings=%@", tmp];
386   
387   if ([self locksObjects]) [ms appendString:@" locks"];
388   if ([self usesDistinct]) [ms appendString:@" distinct"];
389   
390   if ([self fetchLimit] > 0)
391     [ms appendFormat:@" limit=%i", [self fetchLimit]];
392
393   if ((tmp = [self hints])) {
394     NSEnumerator *e;
395     NSString *hint;
396     BOOL isFirst = YES;
397     
398     [ms appendString:@" hints:"];
399     e = [tmp keyEnumerator];
400     while ((hint = [e nextObject])) {
401       if (isFirst) isFirst = NO;
402       else [ms appendString:@","];
403       [ms appendString:hint];
404       [ms appendString:@"="];
405       [ms appendString:[[(NSDictionary *)tmp objectForKey:hint] stringValue]];
406     }
407   }
408   
409   [ms appendString:@">"];
410   return ms;
411 }
412
413 @end /* EOFetchSpecification */