]> err.no Git - sope/blob - sope-appserver/SoOFS/OFSFolderDataSource.m
added strict OSX bundle dependencies
[sope] / sope-appserver / SoOFS / OFSFolderDataSource.m
1 /*
2   Copyright (C) 2002-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 "OFSFolderDataSource.h"
23 #include <EOControl/EOQualifier.h>
24 #include <EOControl/EOSortOrdering.h>
25 #include "common.h"
26
27 @interface OFSFolderFetchEnum : NSEnumerator
28 {
29   id           folder;
30   NSEnumerator *names;
31   EOQualifier  *qualifier;
32   unsigned     limit;
33   unsigned     count;
34 }
35
36 - (id)initWithFolder:(id)_folder 
37   fetchSpecification:(EOFetchSpecification *)_fs;
38
39 @end
40
41 @implementation OFSFolderDataSource
42
43 - (id)initWithFolder:(id)_folder {
44   if ((self = [super init])) {
45     self->folder = [_folder retain];
46   }
47   return self;
48 }
49 - (id)init {
50   return [self initWithFolder:nil];
51 }
52 + (id)dataSourceOnFolder:(id)_folder {
53   return [[[self alloc] initWithFolder:_folder] autorelease];
54 }
55
56 - (void)dealloc {
57   [self->fetchSpecification release];
58   [self->folder             release];
59   [super dealloc];
60 }
61
62 /* accessors */
63
64 - (id)folder {
65   return self->folder;
66 }
67
68 - (void)setFetchSpecification:(EOFetchSpecification *)_fspec {
69   if ([self->fetchSpecification isEqual:_fspec])
70     return;
71   
72   [self->fetchSpecification autorelease];
73   self->fetchSpecification = [_fspec copy];
74   
75   [self postDataSourceChangedNotification];
76 }
77 - (EOFetchSpecification *)fetchSpecification {
78   return self->fetchSpecification;
79 }
80
81 /* operations */
82
83 - (NSEnumerator *)fetchEnumerator {
84   OFSFolderFetchEnum   *e;
85   EOFetchSpecification *fs;
86   NSArray              *sortOrderings;
87   NSAutoreleasePool    *pool;
88   NSArray              *array;
89   unsigned    limit;
90   EOQualifier *q;
91   
92   if ((fs = [self fetchSpecification]) == nil) {
93     e = [[OFSFolderFetchEnum alloc] initWithFolder:[self folder]
94                                        fetchSpecification:nil];
95     return [e autorelease];
96   }
97     
98   sortOrderings = [fs sortOrderings];
99   if ([sortOrderings count] == 0) {
100     /* can do incremental fetch ... */
101     e = [[OFSFolderFetchEnum alloc] initWithFolder:[self folder]
102                                        fetchSpecification:fs];
103     return [e autorelease];
104   }
105   
106   /* fetch => filter => limit => sort, then return enum ... */
107   
108   pool = [[NSAutoreleasePool alloc] init];
109         
110   array = [[self folder] allValues];
111   
112   if ((q = [fs qualifier])) 
113     array = [array filteredArrayUsingQualifier:q];
114
115   if ((limit = [fs fetchLimit]) > 0) {
116     /* limit ... */
117     if (limit < [array count])
118       array = [array subarrayWithRange:NSMakeRange(0, limit)];
119   }
120   
121   array = [array sortedArrayUsingKeyOrderArray:sortOrderings];
122   
123   e = [[array objectEnumerator] retain];
124   
125   [pool release];
126   return [e autorelease];
127 }
128
129 - (NSArray *)fetchObjects {
130   NSEnumerator *e;
131   
132   e = [self fetchEnumerator];
133   return [[[NSArray alloc] initWithObjectsFromEnumerator:e] autorelease];
134 }
135
136 /* NSCopying */
137
138 - (id)copyWithZone:(NSZone *)_zone {
139   OFSFolderDataSource *ds;
140   
141   ds = [[[self class] alloc] initWithFolder:[self folder]];
142   [ds setFetchSpecification:[self fetchSpecification]];
143   return ds;
144 }
145
146 @end /* OFSFolderDataSource */
147
148 @implementation OFSFolderFetchEnum
149
150 - (id)initWithFolder:(id)_folder 
151   fetchSpecification:(EOFetchSpecification *)_fs
152 {
153   if ((self = [super init])) {
154     self->folder    = [_folder retain];
155     self->names     = [[[self->folder allKeys] objectEnumerator] retain];
156     self->qualifier = [[_fs qualifier] retain];
157     self->limit     = [_fs fetchLimit];
158   }
159   return self;
160 }
161 - (id)init {
162   return [self initWithFolder:nil fetchSpecification:nil];
163 }
164
165 - (void)dealloc {
166   [self->qualifier release];
167   [self->names     release];
168   [self->folder    release];
169   [super dealloc];
170 }
171
172 /* state */
173
174 - (void)clear {
175   [self->qualifier release]; self->qualifier = nil;
176   [self->names     release]; self->names     = nil;
177   [self->folder    release]; self->folder    = nil;
178 }
179
180 /* enumerator */
181
182 - (id)_nextObjectToBeFiltered {
183   NSString *nextName;
184   id object;
185   
186   if ((nextName = [self->names nextObject]) == nil) {
187     [self clear];
188     return nil;
189   }
190   if ((object = [self->folder objectForKey:nextName]) == nil) {
191     [self clear];
192     return nil;
193   }
194   return object;
195 }
196
197 - (id)nextObject {
198   id obj;
199
200   if(self->qualifier != nil) {
201     do {
202       if ((obj = [self _nextObjectToBeFiltered]) == nil) {
203         [self clear];
204         return nil;
205       }
206     }
207     while (![(id<EOQualifierEvaluation>)self->qualifier
208       evaluateWithObject:obj]);
209   }
210   else {
211     if ((obj = [self _nextObjectToBeFiltered]) == nil) {
212       [self clear];
213       return nil;
214     }
215   }
216
217   self->count++;
218   if (self->limit > 0 && self->count > self->limit) {
219     [self clear];
220     return nil;
221   }
222   
223   return obj;
224 }
225
226 @end /* OFSFolderFetchEnum */