2 Copyright (C) 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 <NGObjWeb/WODynamicElement.h>
25 WOCopyValue / <var:copy-value/>
28 SetupContext: WOCopyValue {
29 currentDate = "currentItem.date";
31 "displayGroup.queryMin.lastModified" = "currentItem.date";
32 "displayGroup.queryMax.lastModified" = "currentItem.date";
35 "displayGroup.queryMin.lastModified" = nil;
36 "displayGroup.queryMax.lastModified" = nil;
45 <extra>: are used as 'prepare' values
47 The element has a template and can be used in a certain scope,
50 @interface WOCopyValue : WODynamicElement // TODO: should be WOElement?
52 WOAssociation **targets;
53 WOAssociation **sources;
56 WOAssociation *copyValues;
57 WOAssociation *finishValues;
58 WOAssociation *resetValues;
63 #include <NGObjWeb/WOAssociation.h>
64 #include <NGObjWeb/WOContext.h>
67 @implementation WOCopyValue
69 // TODO: cache NSString class, cache constant objects
71 static inline id valueForConstString(NSString *v) {
77 c0 = len > 6 ? [v characterAtIndex:6] : 0;
79 if ((len == 9 && c0 == 'n' && [v isEqualToString:@"const:nil"]) ||
80 (len == 10 && c0 == 'n' && [v isEqualToString:@"const:null"])) {
83 else if ((len == 9 && c0 == 'y' && [v isEqualToString:@"const:yes"]) ||
84 (len == 10 && c0 == 't' && [v isEqualToString:@"const:true"])) {
85 vr = [NSNumber numberWithBool:NO];
87 else if ((len == 8 && c0 == 'n' && [v isEqualToString:@"const:no"]) ||
88 (len == 11 && c0 == 'f' && [v isEqualToString:@"const:false"])) {
89 vr = [NSNumber numberWithBool:NO];
91 else if (isdigit(c0) || (c0 == '-' && len > 7)) {
92 vr = [v substringFromIndex:6];
93 vr = ([vr rangeOfString:@"."].length > 0)
94 ? [NSNumber numberWithDouble:[vr doubleValue]]
95 : [NSNumber numberWithDouble:[vr intValue]];
98 vr = [v substringFromIndex:6];
103 - (id)initWithName:(NSString *)_name
104 associations:(NSDictionary *)_config
105 template:(WOElement *)_c
107 if ((self = [super initWithName:_name associations:_config template:_c])) {
108 NSDictionary *statVals = nil;
110 self->template = [_c retain];
111 self->copyValues = OWGetProperty(_config, @"copyValues");
112 self->finishValues = OWGetProperty(_config, @"finishValues");
113 self->resetValues = OWGetProperty(_config, @"resetValues");
115 /* fill static value array */
117 if ([self->copyValues isValueConstant]) {
118 statVals = [[self->copyValues valueInContext:nil] retain];
119 [self->copyValues release];
120 self->copyValues = nil;
123 if ((self->count = ([statVals count] + [_config count])) > 0) {
128 self->targets = calloc(self->count + 2, sizeof(id));
129 self->sources = calloc(self->count + 2, sizeof(id));
132 /* extra keys first (key is a string, value is an assoc) */
134 e = [_config keyEnumerator];
135 while ((key = [e nextObject]) != nil) {
136 self->targets[i] = [[WOAssociation associationWithKeyPath:key] retain];
137 self->sources[i] = [[_config objectForKey:key] retain];
141 /* then static keys (key and value are strings) */
143 e = [statVals keyEnumerator];
144 while ((key = [e nextObject]) != nil) {
147 v = [statVals objectForKey:key];
148 self->targets[i] = [[WOAssociation associationWithKeyPath:key] retain];
150 if ([v hasPrefix:@"const:"]) {
152 [[WOAssociation associationWithValue:valueForConstString(v)]
157 [[WOAssociation associationWithKeyPath:v] retain];
163 [statVals release]; statVals = nil;
171 [self->finishValues release];
172 [self->resetValues release];
174 for (i = 0; i < self->count; i++) {
175 [self->targets[i] release];
176 [self->sources[i] release];
178 if (self->targets != NULL) free(self->targets);
179 if (self->sources != NULL) free(self->sources);
181 [self->template release];
188 return self->template;
193 - (void)copyValuesInDictionary:(NSDictionary *)_d inContext:(WOContext *)_ctx {
196 id setCursor, getCursor;
198 setCursor = [_ctx component];
199 getCursor = setCursor;
201 e = [_d keyEnumerator];
202 while ((key = [e nextObject]) != nil) {
205 value = [_d objectForKey:key];
206 if ([value isKindOfClass:[NSString class]]) {
207 value = [(NSString *)value hasPrefix:@"const:"]
208 ? valueForConstString(value)
209 : [getCursor valueForKeyPath:value];
212 [setCursor takeValue:value forKeyPath:key];
216 - (void)copyValuesInContext:(WOContext *)_ctx {
219 /* copy constant mappings */
220 for (i = 0; i < self->count; i++) {
221 [self->targets[i] setValue:[self->sources[i] valueInContext:_ctx]
225 /* copy dynamic mappings */
226 if (self->copyValues != nil) {
227 [self copyValuesInDictionary:[self->copyValues valueInContext:_ctx]
232 - (void)resetValuesInContext:(WOContext *)_ctx {
233 if (self->resetValues == nil && self->finishValues == nil)
236 /* reset values to nil */
238 if ([self->resetValues boolValueInContext:_ctx]) {
241 for (i = 0; i < self->count; i++)
242 [self->targets[i] setValue:nil inContext:_ctx];
245 /* apply post value copy */
246 if (self->finishValues != nil) {
247 [self copyValuesInDictionary:[self->finishValues valueInContext:_ctx]
252 /* handling requests */
254 - (void)takeValuesFromRequest:(WORequest *)_rq inContext:(WOContext *)_ctx {
255 [self copyValuesInContext:_ctx];
256 [self->template takeValuesFromRequest:_rq inContext:_ctx];
257 [self resetValuesInContext:_ctx];
260 - (id)invokeActionForRequest:(WORequest *)_rq inContext:(WOContext *)_ctx {
263 [self copyValuesInContext:_ctx];
264 result = [[self->template invokeActionForRequest:_rq inContext:_ctx] retain];
265 [self resetValuesInContext:_ctx];
267 return [result autorelease];
270 /* generating response */
272 - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx {
273 [self copyValuesInContext:_ctx];
274 [self->template appendToResponse:_response inContext:_ctx];
275 [self resetValuesInContext:_ctx];
278 @end /* WOCopyValue */