]> err.no Git - sope/blob - sope-appserver/NGObjWeb/DynamicElements/WOFrame.m
use %p for pointer formats, fixed gcc 4.1 warnings, minor code improvs
[sope] / sope-appserver / NGObjWeb / DynamicElements / WOFrame.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 "WOElement+private.h"
23 #include "WOHTMLDynamicElement.h"
24 #include <NGObjWeb/WOApplication.h>
25 #include <NGObjWeb/WOResourceManager.h>
26 #include <NGObjWeb/WODynamicElement.h>
27 #include "decommon.h"
28
29 #define FRAME_TYPE_None  0
30 #define FRAME_TYPE_Page  1
31 #define FRAME_TYPE_Href  2
32 #define FRAME_TYPE_Value 3
33 #define FRAME_TYPE_DA    4
34
35 @interface WOFrame : WOHTMLDynamicElement
36 {
37   // WODynamicElement: extraAttributes
38   // WODynamicElement: otherTagString
39 @protected
40   /* new in WO4 */
41   WOAssociation *queryDictionary;
42   NSDictionary  *queryParameters;  /* associations beginning with ? */
43 }
44
45 @end
46
47 @interface _WOPageFrame : WOFrame
48 {
49   WOAssociation *pageName;
50 }
51 @end
52
53 @interface _WOHrefFrame : WOFrame
54 {
55   WOAssociation *src;
56 }
57 @end
58
59 @interface _WOValueFrame : WOFrame
60 {
61   WOAssociation *value;
62 }
63 @end
64
65 @interface _WODirectActionFrame : WOFrame
66 {
67   WOAssociation *actionClass;
68   WOAssociation *directActionName;
69   BOOL          sidInUrl;          /* include session-id in wa URL ? */
70 }
71 @end
72
73 @interface WOFrame(PrivateMethods)
74
75 - (id)_initWithName:(NSString *)_name
76   associations:(NSDictionary *)_config
77   template:(WOElement *)_t;
78
79 - (NSString *)associationDescription;
80
81 @end
82
83 #if COCOA_Foundation_LIBRARY || NeXT_Foundation_LIBRARY
84 @interface NSObject(Miss)
85 - (void)subclassResponsibility:(SEL)_cmd;
86 @end
87 #endif
88
89 @implementation WOFrame
90
91 + (int)version {
92   return 1;
93 }
94
95 - (id)initWithName:(NSString *)_name
96   associations:(NSDictionary *)_config
97   template:(WOElement *)_t
98 {
99   Class frameClass = Nil;
100   
101   if ([_config objectForKey:@"value"])
102     frameClass = [_WOValueFrame class];
103   else if ([_config objectForKey:@"pageName"])
104     frameClass = [_WOPageFrame class];
105   else if ([_config objectForKey:@"src"])
106     frameClass = [_WOHrefFrame class];
107   else
108     frameClass = [_WODirectActionFrame class];
109
110   [self release];
111   return [[frameClass alloc]
112                       initWithName:_name associations:_config template:_t];
113 }
114
115 - (id)_initWithName:(NSString *)_name
116   associations:(NSDictionary *)_config
117   template:(WOElement *)_tmpl
118 {
119   if ((self = [super initWithName:_name associations:_config template:_tmpl])) {
120     self->queryDictionary = OWGetProperty(_config, @"queryDictionary");
121     self->queryParameters = OWExtractQueryParameters(_config);
122   }
123   return self;
124 }
125
126 - (void)dealloc {
127   RELEASE(self->queryDictionary);
128   RELEASE(self->queryParameters);
129   [super dealloc];
130 }
131
132 // ******************** responder ********************
133
134 #define StrVal(__x__) [self->__x__ stringValueInComponent:sComponent]
135
136 - (BOOL)_appendHrefToResponse:(WOResponse *)_response
137   inContext:(WOContext *)_ctx
138 {
139   [self subclassResponsibility:_cmd];
140   return NO;
141 }
142
143 - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx {
144   WOComponent *sComponent = [_ctx component];
145   NSString *queryString = nil;
146   if ([[_ctx request] isFromClientComponent])
147     return;
148
149   WOResponse_AddCString(_response, "<frame src=\"");
150     
151   if ([self _appendHrefToResponse:_response inContext:_ctx]) {
152     queryString = [self queryStringForQueryDictionary:
153                         [self->queryDictionary valueInComponent:sComponent]
154                         andQueryParameters:self->queryParameters
155                         inContext:_ctx];
156   }
157
158   if (queryString) {
159     [_response appendContentCharacter:'?'];
160     WOResponse_AddString(_response, queryString);
161   }
162   WOResponse_AddChar(_response, '"');
163   
164   [self appendExtraAttributesToResponse:_response inContext:_ctx];
165     
166   if (self->otherTagString) {
167     WOResponse_AddChar(_response, ' ');
168     WOResponse_AddString(_response,
169                          [self->otherTagString stringValueInComponent:
170                               [_ctx component]]);
171   }
172   WOResponse_AddEmptyCloseParens(_response, _ctx);
173 }
174
175 // description
176
177 - (NSString *)associationDescription {
178   return @"";
179 }
180
181 @end /* WOFrame */
182
183 @implementation _WOPageFrame
184
185 - (id)initWithName:(NSString *)_name
186   associations:(NSDictionary *)_config
187   template:(WOElement *)_t
188 {
189   if ((self = [super _initWithName:_name associations:_config template:_t])) {
190     self->pageName = OWGetProperty(_config, @"pageName");
191
192     if (self->pageName == nil) {
193       NSLog(@"missing pageName association for WOFrame ..");
194       RELEASE(self);
195       return nil;
196     }
197
198 #if DEBUG
199     if ([_config objectForKey:@"value"] ||
200         [_config objectForKey:@"src"]     ||
201         [_config objectForKey:@"directActionName"] ||
202         [_config objectForKey:@"actionClass"]) {
203       NSLog(@"WARNING: inconsistent association settings in WOFrame !"
204             @" (assign only one of pageName, href, "
205             @"directActionName or action)");
206     }
207 #endif
208   }
209   return self;
210 }
211
212 #if !LIB_FOUNDATION_BOEHM_GC
213 - (void)dealloc {
214   RELEASE(self->pageName);
215   [super dealloc];
216 }
217 #endif
218
219 /* value generation */
220
221 - (id)invokeActionForRequest:(WORequest *)_request
222   inContext:(WOContext *)_ctx
223 {
224   NSString    *name;
225   WOComponent *page;
226
227   name = [self->pageName stringValueInComponent:[_ctx component]];
228   page = [[WOApplication application] pageWithName:name inContext:_ctx];
229
230   [[_ctx component] debugWithFormat:@"deliver page %@", [page name]];
231
232   return page;
233 }
234
235 /* href generation */
236
237 - (BOOL)_appendHrefToResponse:(WOResponse *)_response
238   inContext:(WOContext *)_ctx
239 {
240   WOResponse_AddString(_response, [_ctx componentActionURL]);
241   return YES;
242 }
243
244 /* description */
245
246 - (NSString *)associationDescription {
247   NSMutableString *str = [NSMutableString stringWithCapacity:256];
248
249   [str appendFormat:@" pageName=%@", self->pageName];
250   [str appendString:[super associationDescription]];
251   return str;
252 }
253
254 @end /* _WOPageFrame */
255
256 @implementation _WOHrefFrame
257
258 - (id)initWithName:(NSString *)_name
259   associations:(NSDictionary *)_config
260   template:(WOElement *)_t
261 {
262   if ((self = [super _initWithName:_name associations:_config template:_t])) {
263     self->src = OWGetProperty(_config, @"src");
264
265     if (self->src == nil) {
266       NSLog(@"missing src association for WOFrame ..");
267       RELEASE(self);
268       return nil;
269     }
270
271 #if DEBUG
272     if ([_config objectForKey:@"value"] ||
273         [_config objectForKey:@"pageName"]     ||
274         [_config objectForKey:@"directActionName"] ||
275         [_config objectForKey:@"actionClass"]) {
276       NSLog(@"WARNING: inconsistent association settings in WOFrame !"
277             @" (assign only one of pageName, src, directActionName or value)");
278     }
279 #endif
280   }
281   return self;
282 }
283
284 #if !LIB_FOUNDATION_BOEHM_GC
285 - (void)dealloc {
286   RELEASE(self->src);
287   [super dealloc];
288 }
289 #endif
290
291 /* URI generation */
292
293 - (BOOL)_appendHrefToResponse:(WOResponse *)_r inContext:(WOContext *)_ctx {
294   WOResponse_AddString(_r, [self->src stringValueInComponent:[_ctx component]]);
295   return YES;
296 }
297
298 /* description */
299
300 - (NSString *)associationDescription {
301   NSMutableString *str = [NSMutableString stringWithCapacity:256];
302
303   [str appendFormat:@" src=%@", self->src];
304   [str appendString:[super associationDescription]];
305
306   return str;
307 }
308
309 @end /* _WOHrefFrame */
310
311 @implementation _WODirectActionFrame
312
313 - (id)initWithName:(NSString *)_name
314   associations:(NSDictionary *)_config
315   template:(WOElement *)_t
316 {
317   if ((self = [super _initWithName:_name associations:_config template:_t])) {
318     WOAssociation *sidInUrlAssoc;
319
320     sidInUrlAssoc          = OWGetProperty(_config, @"?wosid");
321     self->actionClass      = OWGetProperty(_config, @"actionClass");
322     self->directActionName = OWGetProperty(_config, @"directActionName");
323
324     self->sidInUrl = (sidInUrlAssoc)
325       ? [sidInUrlAssoc boolValueInComponent:nil]
326       : YES;
327     
328 #if DEBUG
329     if ([_config objectForKey:@"value"] ||
330         [_config objectForKey:@"src"]     ||
331         [_config objectForKey:@"pageName"]) {
332       NSLog(@"WARNING: inconsistent association settings in WOFrame !"
333             @" (assign only one of value, src, directActionName or pageName)");
334     }
335 #endif
336   }
337   return self;
338 }
339
340 #if !LIB_FOUNDATION_BOEHM_GC
341 - (void)dealloc {
342   RELEASE(self->actionClass);
343   RELEASE(self->directActionName);
344   [super dealloc];
345 }
346 #endif
347
348 /* href */
349
350 - (BOOL)_appendHrefToResponse:(WOResponse *)_response
351   inContext:(WOContext *)_ctx
352 {
353   WOComponent         *sComponent;
354   NSString            *daClass;
355   NSString            *daName;
356   NSMutableDictionary *qd;
357   NSDictionary        *tmp;
358
359   sComponent = [_ctx component];
360   daClass = [self->actionClass stringValueInComponent:sComponent];
361   daName  = [self->directActionName stringValueInComponent:sComponent];
362
363   if (daClass) {
364     if (daName) {
365       if (![daClass isEqualToString:@"DirectAction"])
366         daName = [NSString stringWithFormat:@"%@/%@", daClass, daName];
367     }
368     else
369       daName = daClass;
370   }
371
372   qd = [NSMutableDictionary dictionaryWithCapacity:16];
373
374       /* add query dictionary */
375       
376   if (self->queryDictionary) {
377     if ((tmp = [self->queryDictionary valueInComponent:sComponent]))
378       [qd addEntriesFromDictionary:tmp];
379   }
380       
381   /* add ?style parameters */
382
383   if (self->queryParameters) {
384     NSEnumerator *keys;
385     NSString     *key;
386
387     keys = [self->queryParameters keyEnumerator];
388     while ((key = [keys nextObject])) {
389       id assoc, value;
390
391       assoc = [self->queryParameters objectForKey:key];
392       value = [assoc stringValueInComponent:sComponent];
393           
394       [qd setObject:(value != nil ? value : (id)@"") forKey:key];
395     }
396   }
397       
398   /* add session ID */
399
400   if (self->sidInUrl) {
401     if ([_ctx hasSession]) {
402       WOSession *sn = [_ctx session];
403           
404       [qd setObject:[sn sessionID] forKey:WORequestValueSessionID];
405           
406       if (![sn isDistributionEnabled]) {
407         [qd setObject:[[WOApplication application] number]
408             forKey:WORequestValueInstance];
409       }
410     }
411   }
412
413   WOResponse_AddString(_response,
414                        [_ctx directActionURLForActionNamed:daName
415                              queryDictionary:qd]);
416   return NO;
417 }
418
419 /* description */
420
421 - (NSString *)associationDescription {
422   NSMutableString *str = [NSMutableString stringWithCapacity:256];
423
424   if (self->actionClass)
425     [str appendFormat:@" actionClass=%@", self->actionClass];
426   if (self->directActionName)
427     [str appendFormat:@" directAction=%@", self->directActionName];
428   
429   [str appendString:[super associationDescription]];
430   return str;
431 }
432
433 @end /* _WODirectActionFrame */
434
435 @implementation _WOValueFrame
436
437 - (id)initWithName:(NSString *)_name
438   associations:(NSDictionary *)_config
439   template:(WOElement *)_t
440 {
441   if ((self = [super _initWithName:_name associations:_config template:_t])) {
442     self->value = OWGetProperty(_config, @"value");
443
444     if (self->value == nil) {
445       NSLog(@"missing value association for WOFrame ..");
446       RELEASE(self);
447       return nil;
448     }
449
450 #if DEBUG
451     if ([_config objectForKey:@"pageName"] ||
452         [_config objectForKey:@"href"]     ||
453         [_config objectForKey:@"directActionName"] ||
454         [_config objectForKey:@"actionClass"]) {
455       NSLog(@"WARNING: inconsistent association settings in WOFrame !"
456             @" (assign only one of pageName, href, directActionName or value)");
457     }
458 #endif
459   }
460   return self;
461 }
462
463 #if !LIB_FOUNDATION_BOEHM_GC
464 - (void)dealloc {
465   RELEASE(self->value);
466   [super dealloc];
467 }
468 #endif
469
470 /* dynamic invocation */
471
472 - (id)invokeActionForRequest:(WORequest *)_request
473   inContext:(WOContext *)_ctx
474 {
475   return [self->value valueInComponent:[_ctx component]];
476 }
477
478 - (BOOL)_appendHrefToResponse:(WOResponse *)_response
479   inContext:(WOContext *)_ctx
480 {
481   WOResponse_AddString(_response, [_ctx componentActionURL]);
482   return YES;
483 }
484
485 /* description */
486
487 - (NSString *)associationDescription {
488   NSMutableString *str = [NSMutableString stringWithCapacity:256];
489
490   [str appendFormat:@" value=%@", self->value];
491   [str appendString:[super associationDescription]];
492   return str;
493 }
494
495 @end /* _WOValueFrame */