]> err.no Git - sope/blob - sope-appserver/WEExtensions/WESwitch.m
fix for SoProductResourceManager.m
[sope] / sope-appserver / WEExtensions / WESwitch.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 /*
24   WESwitch      { selection | selections };
25   WECase        { key | keys };
26   WEDefaultCase {};
27   
28   Warning: The DefaultCase must appear at the last position!!!
29 */
30
31 /*  
32   example:
33   
34   // wod:
35   Switch:      WESwitch { selection = selection;           };
36   FirstCase:   WECase   { key       = "first";             };
37   SecondCase:  WECase   { keys      = ("second", "third"); };
38   DefaultCase: WEDefaultCase {};
39
40   // html:
41   <#Switch>
42     <#FirstCase>content of first case</#FirstCase>
43     <#SecondCase>content of second case</#SecondCase>
44     <#DefaultCase>content of default case</#SecondCase>
45   </#Switch>
46   
47 */
48 #include <NGObjWeb/WODynamicElement.h>
49
50 @class WOAssociation;
51
52 @interface WESwitch : WODynamicElement
53 {
54 @protected
55   WOAssociation *selection;     // string -> single switch
56   WOAssociation *selections;    // array  -> multi  switch
57   WOElement     *template;
58 }
59 @end
60
61 @interface WECase : WODynamicElement
62 {
63   WOAssociation *key;          // string -> unique identifier
64   WOAssociation *keys;         // array of unique identifiers
65
66   WOAssociation *defaultCase;  // emulates a WEDefaultCase DEPRECATED!!!
67   
68   WOElement     *template;
69 }
70 @end
71
72 @interface WEDefaultCase : WODynamicElement
73 {
74   WOElement *template;
75 }
76 @end
77
78 #include "common.h"
79
80 #if DEBUG
81 static NSString *WESwitch_DefaultCaseFound = @"WESwitch_DefaultCaseFound";
82 #endif
83 static NSString *WESwitch_CaseDidMatch     = @"WESwitch_CaseDidMatch";
84 static NSString *WESwitchSelection         = @"WESwitchSelection";
85 static NSString *WESwitchSelections        = @"WESwitchSelections";
86 static NSString *WESwitchDict              = @"WESwitchDict";
87
88 @implementation WESwitch
89
90 - (id)initWithName:(NSString *)_name
91   associations:(NSDictionary *)_config
92   template:(WOElement *)_subs
93 {
94   if ((self = [super initWithName:_name associations:_config template:_subs])) {
95     self->selection  = WOExtGetProperty(_config, @"selection");
96     self->selections = WOExtGetProperty(_config, @"selections");
97     
98     self->template   = [_subs retain];
99   }
100   return self;
101 }
102
103 - (void)dealloc {
104   [self->template   release];
105   [self->selection  release];
106   [self->selections release];
107   [super dealloc];
108 }
109
110 /* processing requests */
111
112 - (void)takeValuesFromRequest:(WORequest *)_req inContext:(WOContext *)_ctx {
113   WOComponent *cmp   = nil;
114   NSArray     *array = nil;
115   NSString    *k     = nil;
116   unsigned    i, cnt;
117   BOOL        doLazy = YES;
118
119   
120   cmp   = [_ctx component];
121   array = [self->selections valueInComponent:cmp];
122   k     = [self->selection  valueInComponent:cmp];
123   cnt   = [array count];
124
125   if (_req == nil) {
126     [self->template takeValuesFromRequest:_req inContext:_ctx];
127   }
128   else if (k) {
129     [_ctx setObject:k forKey:WESwitchSelection];
130     [self->template takeValuesFromRequest:_req inContext:_ctx];
131     [_ctx removeObjectForKey:WESwitchSelection];
132   }
133   else if (doLazy) {
134     for (i = 0; i < cnt; i++) {
135       [_ctx setObject:[array objectAtIndex:i] forKey:WESwitchSelection];
136       [self->template takeValuesFromRequest:_req inContext:_ctx];
137     }
138     if (cnt == 0) {
139       [_ctx setObject:array forKey:WESwitchSelections];
140       [self->template takeValuesFromRequest:_req inContext:_ctx];
141       [_ctx removeObjectForKey:WESwitchSelections];
142     }
143     [_ctx removeObjectForKey:WESwitchSelection];
144   }
145   else if (cnt > 0) {
146     NSLog(@"Warning(%s):This case is not implemented!!!", __PRETTY_FUNCTION__);
147     [self->template takeValuesFromRequest:_req inContext:_ctx];
148   }
149   
150 #if DEBUG
151   else {
152     [cmp logWithFormat:
153          @"Warning! WESwitch: Neither 'selection' nor 'selections' set!!!"];
154   }
155 #endif
156
157   [_ctx removeObjectForKey:WESwitch_CaseDidMatch];
158 }
159
160 - (id)invokeActionForRequest:(WORequest *)_request inContext:(WOContext *)_ctx {
161   return [self->template invokeActionForRequest:_request inContext:_ctx];
162 }
163
164 /* generating response */
165
166 - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx {
167   WOComponent *cmp   = nil;
168   NSArray     *array = nil;
169   NSString    *k     = nil;
170   unsigned    i, cnt;
171   BOOL        doLazy = YES;
172
173   
174   cmp   = [_ctx component];
175   array = [self->selections valueInComponent:cmp];
176   k     = [self->selection  valueInComponent:cmp];
177   cnt   = [array count];
178
179   if (_response == nil) {
180     [self->template appendToResponse:_response inContext:_ctx];
181   }
182   else if (k) {
183     [_ctx setObject:k forKey:WESwitchSelection];
184     [self->template appendToResponse:_response inContext:_ctx];
185     [_ctx removeObjectForKey:WESwitchSelection];
186   }
187   else if (doLazy) {
188     for (i=0; i<cnt; i++) {
189       [_ctx setObject:[array objectAtIndex:i] forKey:WESwitchSelection];
190       [self->template appendToResponse:_response inContext:_ctx];
191     }
192     if (cnt == 0) {
193       [_ctx setObject:array forKey:WESwitchSelections];
194       [self->template appendToResponse:_response inContext:_ctx];
195       [_ctx removeObjectForKey:WESwitchSelections];
196     } 
197     [_ctx removeObjectForKey:WESwitchSelection];
198   }
199   else if (cnt > 0) {
200     NSMutableDictionary *dict = nil;
201     
202     // get subcontent of WECases
203     [_ctx setObject:array forKey:WESwitchSelections];
204     [self->template appendToResponse:_response inContext:_ctx];
205     
206     dict = [_ctx objectForKey:WESwitchDict];
207
208     // append subcontent
209     if (dict) {
210       for (i=0; i<cnt; i++) {
211         NSString *k = [array objectAtIndex:i];
212         NSData   *c = [dict objectForKey:k];   // subcontent of WECase
213
214         if (c)
215           [_response appendContentData:c];
216       }
217     }
218     
219     [_ctx removeObjectForKey:WESwitchDict];
220     [_ctx removeObjectForKey:WESwitchSelections];
221   }
222   
223 #if DEBUG
224   else {
225     [cmp logWithFormat:
226          @"Warning! WESwitch: Neither 'selection' nor 'selections' set!!!"];
227   }
228 #endif
229
230   [_ctx removeObjectForKey:WESwitch_CaseDidMatch];
231 }
232
233 @end /* WESwitch */
234
235 @implementation WECase
236
237 - (id)initWithName:(NSString *)_name
238   associations:(NSDictionary *)_config
239   template:(WOElement *)_t
240 {
241   if ((self = [super initWithName:_name associations:_config template:_t])) {
242     self->key  = WOExtGetProperty(_config, @"key");
243     self->keys = WOExtGetProperty(_config, @"keys");
244
245     // DEPRECATED!!!
246     self->defaultCase  = WOExtGetProperty(_config, @"default");
247     
248     self->template = [_t retain];
249   }
250   return self;
251 }
252
253 - (void)dealloc {
254   [self->template    release];
255   [self->key         release];
256   [self->keys        release];
257   [self->defaultCase release];
258   [super dealloc];
259 }
260
261 /* processing requests */
262
263 - (void)takeValuesFromRequest:(WORequest *)_req inContext:(WOContext *)_ctx {
264   NSArray     *selections = nil;
265   NSString    *selection  = nil;
266   NSString    *k          = nil;
267   NSArray     *ks         = nil;
268   
269   k   = [self->key  stringValueInComponent:[_ctx component]];
270   ks  = [self->keys valueInComponent:[_ctx component]];
271   
272   selections = [_ctx objectForKey:WESwitchSelections];
273   selection  = [_ctx objectForKey:WESwitchSelection];
274
275   if ([self->defaultCase boolValueInComponent:[_ctx component]]) {
276     if ([_ctx objectForKey:WESwitch_CaseDidMatch] == nil)
277       [self->template takeValuesFromRequest:_req inContext:_ctx];
278     return;
279   }
280
281   if ((k == nil) && (ks == nil)) {
282 #if DEBUG
283     [[_ctx component] logWithFormat:
284                       @"Warning! WECase: Neither 'key' nor 'keys' set!!!"];
285 #endif
286     return;
287   }
288   if ((k != nil) && (ks != nil)) {
289 #if DEBUG
290     [[_ctx component] logWithFormat:
291                       @"Warning! WECase: Both, 'key' and 'keys' are set!!!"];
292 #endif
293     return;
294   }
295   
296   if (_req == nil) {
297     [self->template takeValuesFromRequest:nil inContext:_ctx];
298   }
299   if (selection) {
300     if (k && [k isEqualToString:selection]) {
301        [self->template takeValuesFromRequest:_req inContext:_ctx];
302        [_ctx setObject:@"YES" forKey:WESwitch_CaseDidMatch];
303     }
304     else if (ks && [ks containsObject:selection]) {
305       [self->template takeValuesFromRequest:_req inContext:_ctx];
306       [_ctx setObject:@"YES" forKey:WESwitch_CaseDidMatch];
307     }
308   }
309   else if (selections && [selections count] > 0) {
310     NSLog(@"Warning(%s): This case is not implemented!", __PRETTY_FUNCTION__);
311     [self->template takeValuesFromRequest:_req inContext:_ctx];
312   }
313 }
314
315 - (id)invokeActionForRequest:(WORequest *)_req inContext:(WOContext *)_ctx {
316   return [self->template invokeActionForRequest:_req inContext:_ctx];
317 }
318
319 /* generating response */
320
321 - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx {
322   NSArray     *selections = nil;
323   NSString    *selection  = nil;
324   NSString    *k          = nil;
325   NSArray     *ks         = nil;
326
327
328   k   = [self->key  stringValueInComponent:[_ctx component]];
329   ks  = [self->keys valueInComponent:[_ctx component]];
330
331   selections = [_ctx objectForKey:WESwitchSelections];
332   selection  = [_ctx objectForKey:WESwitchSelection];
333
334   if ([self->defaultCase boolValueInComponent:[_ctx component]]) {
335     if ([_ctx objectForKey:WESwitch_CaseDidMatch] == nil)
336       [self->template appendToResponse:_response inContext:_ctx];
337     return;
338   }
339
340   if ((k == nil) && (ks == nil)) {
341 #if DEBUG
342     [[_ctx component] logWithFormat:
343                       @"Warning! WECase: Neither 'key' nor 'keys' set!!!"];
344 #endif
345     return;
346   }
347   if ((k != nil) && (ks != nil)) {
348 #if DEBUG
349     [[_ctx component] logWithFormat:
350                       @"Warning! WECase: Both, 'key' and 'keys' are set!!!"];
351 #endif
352     return;
353   }
354   
355   if (_response == nil) {
356     [self->template appendToResponse:nil inContext:_ctx];
357   }
358   if (selection) {
359     if (k && [k isEqualToString:selection]) {
360        [self->template appendToResponse:_response inContext:_ctx];
361        [_ctx setObject:@"YES" forKey:WESwitch_CaseDidMatch];
362     }
363     else if (ks && [ks containsObject:selection]) {
364       [self->template appendToResponse:_response inContext:_ctx];
365       [_ctx setObject:@"YES" forKey:WESwitch_CaseDidMatch];
366     }
367   }
368   else if (selections && [selections count] > 0) {
369     if ([selections containsObject:k]) {
370       static NSData *emptyData = nil;
371       NSMutableDictionary *dict       = nil;
372       NSData              *oldContent = nil;
373
374       if (emptyData == nil)
375         emptyData = [[NSData alloc] init];
376
377       // get subcontent dictionary
378       dict = [_ctx objectForKey:WESwitchDict];
379       if (dict == nil)
380         dict = [NSMutableDictionary dictionaryWithCapacity:[selections count]];
381
382       // set new content
383       oldContent = [_response content];
384       RETAIN(oldContent);
385       [_response setContent:emptyData];
386       
387       // append template to new content
388       [self->template appendToResponse:_response inContext:_ctx];
389
390       // save new content in dict
391       if ([_response content])
392         [dict setObject:[_response content] forKey:k];
393       [_ctx setObject:dict forKey:WESwitchDict];
394
395       // restore old content
396       [_response setContent:oldContent];
397       [oldContent release]; oldContent = nil;
398
399       // TODO: use NSNumber here?
400       [_ctx setObject:@"YES" forKey:WESwitch_CaseDidMatch];
401     }
402   }
403 }
404
405 @end /* WECase */
406
407 @implementation WEDefaultCase
408
409 - (id)initWithName:(NSString *)_name
410   associations:(NSDictionary *)_config
411   template:(WOElement *)_t
412 {
413   if ((self = [super initWithName:_name associations:_config template:_t])) {
414     self->template = [_t retain];
415   }
416   return self;
417 }
418
419 - (void)dealloc {
420   [self->template release];
421   [super dealloc];
422 }
423
424 /* processing requests */
425
426 - (void)takeValuesFromRequest:(WORequest *)_req inContext:(WOContext *)_ctx {
427   if (([_ctx objectForKey:WESwitch_CaseDidMatch] == nil))
428     [self->template takeValuesFromRequest:_req inContext:_ctx];
429 }
430
431 - (id)invokeActionForRequest:(WORequest *)_req inContext:(WOContext *)_ctx {
432   return [self->template invokeActionForRequest:_req inContext:_ctx];
433 }
434
435 /* generating response */
436
437 - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx {
438   if (([_ctx objectForKey:WESwitch_CaseDidMatch] == nil))
439     [self->template appendToResponse:_response inContext:_ctx];
440   
441 #if DEBUG
442   [_ctx setObject:@"Yes" forKey:WESwitch_DefaultCaseFound];
443 #endif
444 }
445
446 @end /* WEDefaultCase */