]> err.no Git - sope/blob - Recycler/NGJavaScript/Core+JS.subproj/EODataSource+JS.m
more directory hierarchy reorganisations,
[sope] / Recycler / NGJavaScript / Core+JS.subproj / EODataSource+JS.m
1 /*
2   Copyright (C) 2000-2004 SKYRIX Software AG
3
4   This file is part of OpenGroupware.org.
5
6   OGo 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   OGo 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 OGo; 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 // $Id$
22
23 #include <EOControl/EOControl.h>
24 #include <NGExtensions/EODataSource+NGExtensions.h>
25 #include <NGExtensions/NSNull+misc.h>
26 #include "../common.h"
27
28 /*
29   EODataSource JavaScript object
30   
31   Methods
32     bool     setQualifier(string [,args...]) // Format: EOQualifier Format !
33     String   getQualifier()
34     bool     setEntity(string)
35     String   getEntity()
36     bool     setSortOrdering(string)  // Format: 'name' oder '-name'
37     String   getSortOrdering()
38     bool     setHint(string, value)
39     Object   getHint(string)
40     
41     Array    fetchObjects([qual][,orderings][,grouping])
42     
43     Document createObject()
44     bool     updateObject(document)
45     bool     insertObject(document)
46     bool     deleteObject(document)
47 */
48
49 @implementation EODataSource(SkyJSDataSourceBehaviour)
50
51 static id null = nil;
52
53 static inline void _ensureNull(void) {
54   if (null == nil)
55     null = [[NSNull null] retain];
56 }
57
58 /* methods */
59
60 - (void)_updateFetchSpecWithEntityName:(NSString *)_ename
61   qualifier:(EOQualifier *)_qual
62   sortOrderings:(NSArray *)_so
63 {
64   EOFetchSpecification *fspec;
65
66   if (_ename == nil && _qual == nil && _so == nil)
67     /* nothing to update .. */
68     return;
69   
70   _ensureNull();
71   
72   if ((fspec = [self fetchSpecification]) == nil) {
73     if (_qual  == null) _qual  = nil;
74     if (_so    == null) _so    = nil;
75     if (_ename == null) _ename = nil;
76     
77     fspec = [[EOFetchSpecification alloc]
78                                    initWithEntityName:_ename
79                                    qualifier:_qual
80                                    sortOrderings:_so
81                                    usesDistinct:YES isDeep:NO hints:nil];
82     fspec = [fspec autorelease];
83     
84     [self setFetchSpecification:fspec];
85   }
86   else {
87     fspec = [[fspec copy] autorelease];
88     
89     if (_qual) {
90       if (_qual == null) _qual = nil;
91       [fspec setQualifier:_qual];
92     }
93     if (_ename) {
94       if (_ename == null) _ename = nil;
95       [fspec setEntityName:_ename];
96     }
97     if (_so) {
98       if (_so == null) _so = nil;
99       [fspec setSortOrderings:_so];
100     }
101     
102     [self setFetchSpecification:fspec];
103   }
104 }
105
106 - (id)_jsfunc_setEntity:(NSArray *)_args {
107   unsigned count;
108   NSString *entityName;
109
110   if ((count = [_args count]) == 0) {
111 #if DEBUG && 0
112     NSLog(@"%s: missing qualifier argument ..", __PRETTY_FUNCTION__);
113 #endif
114     entityName = nil;
115   }
116   else {
117     entityName = [[_args objectAtIndex:0] stringValue];
118   }
119
120   if (entityName == nil) entityName = null;
121   
122   [self _updateFetchSpecWithEntityName:entityName
123         qualifier:nil
124         sortOrderings:nil];
125   
126   return [NSNumber numberWithBool:YES];
127 }
128 - (id)_jsfunc_getEntity:(NSArray *)_args {
129   return [[self fetchSpecification] entityName];
130 }
131
132 - (id)_jsfunc_setSortOrdering:(NSArray *)_args {
133   unsigned count;
134   
135   if ((count = [_args count]) == 0) {
136     [self _updateFetchSpecWithEntityName:nil
137           qualifier:nil
138           sortOrderings:[NSArray array]];
139     
140     return [NSNumber numberWithBool:YES];
141   }
142   else if (count == 1) {
143     NSString       *key;
144     SEL            selector;
145     EOSortOrdering *ordering;
146
147     selector = EOCompareAscending;
148     
149     key = [[_args objectAtIndex:0] stringValue];
150     if ([key hasPrefix:@"-"]) {
151       selector = EOCompareDescending;
152       key = [key substringFromIndex:1];
153     }
154     
155     ordering = [EOSortOrdering sortOrderingWithKey:key selector:selector];
156     
157     [self _updateFetchSpecWithEntityName:nil
158           qualifier:nil
159           sortOrderings:[NSArray arrayWithObject:ordering]];
160     
161     return [NSNumber numberWithBool:YES];
162   }
163   
164   return [NSNumber numberWithBool:NO];
165 }
166 - (id)_jsfunc_getSortOrdering:(NSArray *)_args {
167   NSArray        *orderings;
168   unsigned       count;
169   EOSortOrdering *ordering;
170   
171   orderings = [[self fetchSpecification] sortOrderings];
172   if ((count = [orderings count]) == 0)
173     return nil;
174   
175   ordering = [orderings objectAtIndex:0];
176   
177 #if APPLE_RUNTIME || NeXT_RUNTIME
178   if ([ordering selector] == EOCompareDescending)
179     return [@"-" stringByAppendingString:[ordering key]];
180   if ([ordering selector] == EOCompareDescending)
181     return [ordering key];
182 #else
183   if (sel_eq([ordering selector], EOCompareDescending))
184     return [@"-" stringByAppendingString:[ordering key]];
185   if (sel_eq([ordering selector], EOCompareDescending))
186     return [ordering key];
187 #endif
188   return @"<unknown>";
189 }
190
191 - (id)_jsfunc_setQualifier:(NSArray *)_args {
192   EOFetchSpecification *fspec;
193   unsigned    count;
194   EOQualifier *q;
195   NSArray     *args;
196
197   _ensureNull();
198   
199   fspec = [self fetchSpecification];
200   
201   if ((count = [_args count]) == 0) {
202 #if DEBUG && 0
203     NSLog(@"%s: missing qualifier argument ..", __PRETTY_FUNCTION__);
204 #endif
205     q = nil;
206   }
207   else {
208     id qq;
209     
210     qq = [_args objectAtIndex:0];
211     
212     args = (count > 1)
213       ? [_args subarrayWithRange:NSMakeRange(1, count - 1)]
214       : [NSArray array];
215     
216     if ([qq isKindOfClass:[EOQualifier class]]) {
217       q = qq;
218     }
219     else if ([[qq stringValue] length] == 0) {
220       q = nil;
221     }
222     else {
223       q = [EOQualifier qualifierWithQualifierFormat:[qq stringValue]
224                        arguments:args];
225       
226 #if DEBUG
227       if (q == nil) {
228         NSLog(@"%s: couldn't parse qualifier '%@' ..",
229               __PRETTY_FUNCTION__, qq);
230         return [NSNumber numberWithBool:NO];
231       }
232 #endif
233     }
234   }
235   
236   if (q == nil) q = null;
237   
238   [self _updateFetchSpecWithEntityName:nil qualifier:q sortOrderings:nil];
239   
240   return [NSNumber numberWithBool:YES];
241 }
242 - (id)_jsfunc_getQualifier:(NSArray *)_args {
243   return [(id)[[self fetchSpecification] qualifier] stringValue];
244 }
245
246 - (id)_jsfunc_setHint:(NSArray *)_args {
247   unsigned count;
248   NSString *key;
249   id       value;
250   EOFetchSpecification *fspec;
251   NSMutableDictionary  *hints;
252   
253   if ((count = [_args count]) == 0)
254     return [NSNumber numberWithBool:NO];
255   if (count == 1)
256     return [NSNumber numberWithBool:NO];
257
258   key   = [[_args objectAtIndex:0] stringValue];
259   value = [_args objectAtIndex:1];
260
261   if (key == nil)
262     return [NSNumber numberWithBool:NO];
263   
264   if ((fspec = [[self fetchSpecification] copy]) == nil) {
265     fspec = [[EOFetchSpecification alloc]
266                                    initWithEntityName:nil
267                                    qualifier:nil
268                                    sortOrderings:nil
269                                    usesDistinct:YES isDeep:NO hints:nil];
270   }
271   fspec = [fspec autorelease];
272   
273   hints = [[fspec hints] mutableCopy];
274   if (hints == nil)
275     hints = [[NSMutableDictionary alloc] initWithCapacity:4];
276   
277   if (![value isNotNull]) {
278     /* delete hint */
279     [hints removeObjectForKey:key];
280   }
281   else {
282     [hints setObject:value forKey:key];
283   }
284   
285   [fspec setHints:hints];
286   [hints release]; hints = nil;
287   
288   [self setFetchSpecification:fspec];
289   
290   return [NSNumber numberWithBool:YES];
291 }
292 - (id)_jsfunc_getHint:(NSArray *)_args {
293   unsigned     count;
294   NSDictionary *hints;
295   
296   if ((count = [_args count]) == 0)
297     return nil;
298   
299   hints = [[self fetchSpecification] hints];
300   return [hints objectForKey:[[_args objectAtIndex:0] stringValue]];
301 }
302
303 /* query operation */
304
305 - (void)logException:(NSException *)_exception {
306   NSLog(@"%s: exception: %@", __PRETTY_FUNCTION__, _exception);
307 }
308
309 - (id)_jsfunc_fetchObjects:(NSArray *)_args {
310   EOFetchSpecification *fspec;
311   unsigned count;
312   id qualifier     = nil;
313   id sortOrderings = nil;
314   id groupings     = nil;
315   id results;
316   
317   count = [_args count];
318   fspec = nil;
319
320   NS_DURING {
321     if (count > 0) {
322       if ((fspec = [self fetchSpecification]) == nil) {
323         fspec = [EOFetchSpecification fetchSpecificationWithEntityName:nil
324                                       qualifier:nil
325                                       sortOrderings:nil];
326       }
327       else
328         fspec = [[fspec copy] autorelease];
329     }
330     
331     if (count > 0) {
332       NSString *qs;
333       
334       qualifier = [_args objectAtIndex:0];
335       if (![qualifier isKindOfClass:[EOQualifier class]]) {
336         qs = [qualifier stringValue];
337         qualifier = [EOQualifier qualifierWithQualifierFormat:qs];
338   #if DEBUG && 0
339         NSLog(@"%s: made q %@ for string '%@'",
340               __PRETTY_FUNCTION__, qualifier, qs);
341   #endif
342       }
343       
344       [fspec setQualifier:qualifier];
345     }
346     
347     if (count > 1) {
348       sortOrderings = [_args objectAtIndex:1];
349       [fspec setSortOrderings:sortOrderings];
350     }
351     
352     if (count > 2) {
353       groupings = [_args objectAtIndex:2];
354       // [fspec setGroupings:..];
355     }
356     
357     if (fspec)
358       [self setFetchSpecification:fspec];
359     
360     results = [self fetchObjects];
361   }
362   NS_HANDLER {
363     *(&results) = nil;
364     [self logException:localException];
365   }
366   NS_ENDHANDLER;
367   
368   return results;
369 }
370
371 /* modification operations */
372
373 - (id)_jsfunc_createObject:(NSArray *)_args {
374   id obj;
375
376   NS_DURING
377     obj = [self createObject];
378   NS_HANDLER {
379     *(&obj) = nil;
380     [self logException:localException];
381   }
382   NS_ENDHANDLER;
383   
384   return obj;
385 }
386
387 - (id)_jsfunc_insertObject:(NSArray *)_args {
388   unsigned     count;
389   NSEnumerator *e;
390   id   obj;
391   BOOL ok;
392   
393   if ((count = [_args count]) == 0)
394     return [NSNumber numberWithBool:YES];
395
396   e = [_args objectEnumerator];
397   ok = YES;
398   while ((obj = [e nextObject]) && ok) {
399     NS_DURING
400       [self insertObject:obj];
401     NS_HANDLER {
402       ok = NO;
403       [self logException:localException];
404     }
405     NS_ENDHANDLER;
406   }
407   
408   return [NSNumber numberWithBool:ok];
409 }
410
411 - (id)_jsfunc_updateObject:(NSArray *)_args {
412   unsigned     count;
413   NSEnumerator *e;
414   id   obj;
415   BOOL ok;
416   
417   if ((count = [_args count]) == 0)
418     return [NSNumber numberWithBool:YES];
419
420   e = [_args objectEnumerator];
421   ok = YES;
422   while ((obj = [e nextObject]) && ok) {
423     NS_DURING
424       [self updateObject:obj];
425     NS_HANDLER
426       ok = NO;
427     NS_ENDHANDLER;
428   }
429   return [NSNumber numberWithBool:ok];
430 }
431
432 - (id)_jsfunc_deleteObject:(NSArray *)_args {
433   unsigned     count;
434   NSEnumerator *e;
435   id   obj;
436   BOOL ok;
437   
438   if ((count = [_args count]) == 0)
439     return [NSNumber numberWithBool:YES];
440
441   e = [_args objectEnumerator];
442   ok = YES;
443   while ((obj = [e nextObject]) && ok) {
444     NS_DURING
445       [self deleteObject:obj];
446     NS_HANDLER {
447       ok = NO;
448       [self logException:localException];
449     }
450     NS_ENDHANDLER;
451   }
452   return [NSNumber numberWithBool:ok];
453 }
454
455 @end /* EOControl(SkyJSDataSourceBehaviour) */