2 Copyright (C) 2000-2005 SKYRIX Software AG
4 This file is part of SOPE.
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
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.
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
22 #include "WOComponentReference.h"
23 #include "WOElement+private.h"
24 #include "WOContext+private.h"
25 #include "WOComponent+private.h"
28 @interface WOContext(ComponentStackCount)
29 - (unsigned)componentStackCount;
32 @implementation WOComponentReference
34 static int profileComponents = -1;
35 static BOOL coreOnRecursion = NO;
36 static BOOL debugOn = NO;
37 static Class NSDateClass = Nil;
40 NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
42 profileComponents = [[ud objectForKey:@"WOProfileComponents"]
44 coreOnRecursion = [ud boolForKey:@"WOCoreOnRecursiveSubcomponents"];
45 NSDateClass = [NSDate class];
48 - (id)initWithName:(NSString *)_name
49 associations:(NSDictionary *)_config
50 template:(WOElement *)_c
52 if ((self = [super initWithName:_name associations:_config template:_c])) {
53 self->containsForm = YES;
54 self->activeComponent = OWGetProperty(_config, @"component");
55 self->bindings = [_config copyWithZone:[self zone]];
56 [(NSMutableDictionary *)_config removeAllObjects];
58 self->template = [_c retain];
64 [self->template release];
65 [self->bindings release];
66 [self->activeComponent release];
67 [self->child release];
73 - (WOComponent *)childComponent {
74 return self->child; // THREAD
78 _updateComponent(WOComponentReference *self, WOContext *_ctx)
81 Note: this is rather dangerous. We keep a processing state - the 'child'
82 ivar containing the component - inside the dynamic element. Yet
83 elements are supposed to be stateless.
85 As long as we are single-threaded this should not be a problem, but
86 keep in mind that this element is NOT reentrant.
89 WOComponent *newChild;
91 if (self->activeComponent == nil)
94 newChild = [self->activeComponent valueInComponent:[_ctx component]];
96 if (newChild == nil) {
97 [[_ctx component] logWithFormat:
98 @"missing child (got nil) "
99 @"(element=%@, association=%@, component=%@).",
100 self, self->activeComponent,
101 [[_ctx component] name]];
105 if (newChild != self->child) { // THREAD
107 NSLog(@"switched component %@ => %@ ...",
108 [self->child name], [newChild name]);
110 ASSIGN(self->child, newChild);
111 [newChild setParent:[_ctx component]];
112 [newChild setBindings:self->bindings];
116 /* handling requests */
118 - (void)takeValuesFromRequest:(WORequest *)_req inContext:(WOContext *)_ctx {
121 parent = [_ctx component];
123 _updateComponent(self, _ctx);
125 if (self->child != nil) {
126 [_ctx enterComponent:self->child content:self->template];
127 [self->child takeValuesFromRequest:_req inContext:_ctx];
128 [_ctx leaveComponent:self->child];
132 - (id)invokeActionForRequest:(WORequest *)_req inContext:(WOContext *)_ctx {
136 parent = [_ctx component];
138 _updateComponent(self, _ctx);
140 if (self->child != nil) {
141 [_ctx enterComponent:self->child content:self->template];
142 result = [self->child invokeActionForRequest:_req inContext:_ctx];
143 [_ctx leaveComponent:self->child];
149 /* generate response */
151 - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx {
154 parent = [_ctx component];
156 _updateComponent(self, _ctx);
158 if (self->child == parent) {
159 [self warnWithFormat:@"recursive call of component: %@", parent];
164 if (self->child != nil) {
165 NSTimeInterval st = 0.0;
167 if (profileComponents)
168 st = [[NSDateClass date] timeIntervalSince1970];
170 [_ctx enterComponent:self->child content:self->template];
171 [self->child appendToResponse:_response inContext:_ctx];
172 [_ctx leaveComponent:self->child];
174 if (profileComponents) {
177 diff = [[NSDateClass date] timeIntervalSince1970] - st;
178 for (i = [_ctx componentStackCount]; i >= 0; i--)
180 printf("[%s %s]: %0.3fs\n",
181 [[child name] cString],
182 #if APPLE_RUNTIME || NeXT_RUNTIME
191 [self debugWithFormat:@"missing component for reference: %@",
192 self->activeComponent];
193 [_response appendContentHTMLString:@"[missing component for reference: "];
194 [_response appendContentHTMLString:[self->activeComponent description]];
195 [_response appendContentHTMLString:@"]"];
201 - (NSString *)description {
202 NSMutableString *desc;
204 desc = [NSMutableString stringWithCapacity:64];
205 [desc appendFormat:@"<%@[0x%08X]:", NSStringFromClass([self class]), self];
207 if (self->child != nil) {
208 [desc appendFormat:@" child=%@[0x%08X] childName=%@",
209 NSStringFromClass([self->child class]),
210 self->child, [self->child name]];
213 [desc appendString:@">"];
217 @end /* WOComponentReference */