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 "WOGenericElement.h"
23 #include "WOElement+private.h"
25 #include <NGObjWeb/WOxElemBuilder.h>
26 #include <DOM/DOMProtocols.h>
28 // TODO: we should be able to store the key as ASCII ?
29 // TODO: does it make sense to resolve constant associations ?
30 // all constant assocs could be joined at init time ?
32 #define TagNameType_Assoc 0
33 #define TagNameType_String 1
34 #define TagNameType_ASCII 2
41 @implementation WOGenericElement
43 - (id)initWithElement:(id<DOMElement>)_element
44 templateBuilder:(WOxElemBuilder *)_builder
47 NSMutableDictionary *assocs;
49 id<NSObject,DOMNamedNodeMap> attrs;
52 name = [_element tagName];
54 /* construct associations */
57 attrs = [_element attributes];
58 if ((lcount = [attrs length]) > 0)
59 assocs = [_builder associationsForAttributes:attrs];
63 [NSMutableDictionary dictionaryWithObject:
64 [_builder associationForValue:[_element tagName]]
65 forKey:@"elementName"];
68 [assocs setObject:[_builder associationForValue:[_element tagName]]
69 forKey:@"elementName"];
72 /* construct child elements */
74 children = [_element hasChildNodes]
75 ? [_builder buildNodes:[_element childNodes] templateBuilder:_builder]
78 /* construct self ... */
79 self = [(WODynamicElement *)self initWithName:name
81 contentElements:children];
85 - (BOOL)_isASCIIString:(NSString *)_s {
86 /* TODO: not a very fast check for an ASCII string ... */
87 return [_s dataUsingEncoding:NSASCIIStringEncoding
88 allowLossyConversion:NO] != nil ? YES : NO;
91 - (void)_setupAssociations:(NSMutableDictionary *)_associations {
94 OWAttribute *mapping = NULL;
99 keys = [_associations keyEnumerator];
100 self->mappings = calloc(self->count, sizeof(OWAttribute));
102 for (mapping = self->mappings; (key = [keys nextObject]); mapping++) {
103 WOAssociation *value;
105 value = [_associations objectForKey:key];
106 mapping->key = [key copy];
107 mapping->value = [value retain];
109 [_associations removeAllObjects];
112 - (void)_configureForConstantElementName:(NSString *)s {
113 if ([self _isASCIIString:s]) {
117 len = [s cStringLength];
118 cs = malloc(len + 2);
119 [s getCString:(char *)cs];
122 self->tagNameType = TagNameType_ASCII;
125 /* a tagname which is not ASCII ?? */
126 self->tagName = [s copy];
127 self->tagNameType = TagNameType_String;
131 - (id)initWithName:(NSString *)_name
132 associations:(NSDictionary *)_associations
133 template:(WOElement *)_template
135 self = [super initWithName:_name
136 associations:_associations
142 self->tagName = a = OWGetProperty(_associations, @"elementName");
143 self->tagNameType = TagNameType_Assoc;
144 self->count = [_associations count];
146 if ([a isValueConstant]) {
147 [self _configureForConstantElementName:[a stringValueInComponent:nil]];
148 [a release]; a = nil;
152 [self _setupAssociations:(NSMutableDictionary *)_associations];
158 if (self->mappings) {
162 for (cnt = 0, map = self->mappings; cnt < self->count; cnt++, map++) {
163 [map->key release]; map->key = nil;
164 [map->value release]; map->value = nil;
166 if (self->mappings) free(self->mappings);
167 self->mappings = NULL;
170 switch (self->tagNameType) {
171 case TagNameType_Assoc: [(id)self->tagName release]; break;
172 case TagNameType_String: [(id)self->tagName release]; break;
173 case TagNameType_ASCII:
174 if (self->tagName) free(self->tagName);
177 [self errorWithFormat:@"unknown tag-name-type %i !", self->tagNameType];
183 /* response generation */
185 - (void)_appendAttributesToResponse:(WOResponse *)_response
186 inContext:(WOContext *)_ctx
188 // TODO: this seems to take some time during profiling, maybe we can
189 // optimize that (ASCII keys, constant assocs)
190 WOComponent *sComponent = [_ctx component];
194 for (cnt = 0, map = self->mappings; cnt < self->count; cnt++, map++) {
197 if ((value = [map->value valueInComponent:sComponent]) == nil)
200 WOResponse_AddChar(_response, ' ');
201 WOResponse_AddString(_response, map->key);
202 WOResponse_AddCString(_response, "=\"");
203 WOResponse_AddHtmlString(_response, [value stringValue]);
204 WOResponse_AddChar(_response, '"');
208 - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx {
209 WOComponent *sComponent;
212 if ([[_ctx request] isFromClientComponent])
215 sComponent = [_ctx component];
217 WOResponse_AddChar(_response, '<');
218 switch (self->tagNameType) {
219 case TagNameType_Assoc:
220 tag = [(id)self->tagName stringValueInComponent:sComponent];
221 WOResponse_AddString(_response, tag);
223 case TagNameType_String:
224 WOResponse_AddString(_response, self->tagName);
226 case TagNameType_ASCII:
227 WOResponse_AddCString(_response, self->tagName);
231 [self _appendAttributesToResponse:_response inContext:_ctx];
233 if (self->otherTagString) {
234 WOResponse_AddChar(_response, ' ');
235 WOResponse_AddString(_response,
236 [self->otherTagString stringValueInComponent:
239 WOResponse_AddEmptyCloseParens(_response, _ctx);
242 @end /* WOGenericElement */