]> err.no Git - sope/blob - sope-appserver/WOXML/WOXMLMapDecoder.m
fixed install locations on OSX
[sope] / sope-appserver / WOXML / WOXMLMapDecoder.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 "WOXMLMapDecoder.h"
23 #include "WOXMLMappingModel.h"
24 #include "WOXMLMappingEntity.h"
25 #include "WOXMLMappingProperty.h"
26 #include "common.h"
27
28 #include <DOM/DOMElement.h>
29 #include <DOM/DOMDocument.h>
30
31 @implementation WOXMLMapDecoder
32
33 - (id)initWithModel:(WOXMLMappingModel *)_model {
34   self->model = [_model retain];
35   return self;
36 }
37
38 - (void)dealloc {
39   [self->model release];
40   [super dealloc];
41 }
42
43 /* operations */
44
45 - (WOXMLMappingEntity *)defaultEntity {
46   return nil;
47 }
48
49 - (id)_processDOMElementNode:(id)_node {
50   WOXMLMappingEntity *entity;
51   Class        entityClass;
52   id           object;
53   NSMutableSet *childTags;
54   
55   NSAssert1([_node nodeType] == DOM_ELEMENT_NODE,
56             @"passed invalid element node: %@", _node);
57   
58   if ((entity = [self->model entityForXmlTag:[_node tagName]]) == nil) {
59     /* missing entity */
60     entity = [self defaultEntity];
61   }
62   if (entity == nil)
63     return [_node textValue];
64   
65   entityClass = NSClassFromString([entity name]);
66   if (entityClass == Nil) entityClass = [NSMutableDictionary class];
67   
68   object = AUTORELEASE([[entityClass alloc] init]);
69
70   childTags = [NSMutableSet setWithCapacity:16];
71   
72   /* apply properties */
73   {
74     NSEnumerator *e;
75     WOXMLMappingProperty *prop;
76     
77     e = [[entity properties] objectEnumerator];
78     while ((prop = [e nextObject])) {
79       if (![prop isValid])
80         continue;
81       
82       if ([prop attribute]) {
83         /* an attribute property */
84         NSString *attrName;
85         NSString *value;
86         
87         attrName = [prop xmlTag];
88
89         if ((value = [_node attribute:attrName]) == nil)
90           value = [_node attribute:attrName namespaceURI:@"*"];
91         
92         if (value)
93           [object takeValue:value forKey:[prop name]];
94       }
95       else
96         [childTags addObject:[prop xmlTag]];
97     }
98   }
99   
100   /* walk children */
101   {
102     unsigned i, count;
103     id childNodes;
104     NSMutableDictionary *d;
105
106     d = [NSMutableDictionary dictionaryWithCapacity:16];
107     
108     childNodes = [_node childNodes];
109     for (i = 0, count = [childNodes count]; i < count; i++) {
110       id child;
111       
112       child = [childNodes objectAtIndex:i];
113
114       if ([child nodeType] == DOM_ELEMENT_NODE) {
115         if ([childTags containsObject:[child tagName]]) {
116           /* a property */
117           WOXMLMappingProperty *prop;
118           id o;
119           
120           prop = [entity propertyForXmlTag:[child tagName]];
121           
122           o = [self _processDOMElementNode:child];
123           if (o == nil)
124             o = [EONull null];
125
126           if ([prop forceList]) {
127             NSMutableArray *a;
128
129             a = [d objectForKey:[prop name]];
130             if (a == nil) {
131               a = [NSMutableArray arrayWithCapacity:1];
132               [d setObject:a forKey:[prop name]];
133             }
134             [a addObject:o];
135           }
136           else {
137             id old;
138             
139             if ((old = [d objectForKey:[prop name]])) {
140               if ([old isKindOfClass:[NSMutableArray class]])
141                 [old addObject:o];
142               else {
143                 NSMutableArray *a;
144
145                 a = [NSMutableArray arrayWithCapacity:2];
146                 [a addObject:old];
147                 [a addObject:o];
148                 [d setObject:a forKey:[prop name]];
149               }
150             }
151             else {
152               /* first element */
153               [d setObject:o forKey:[prop name]];
154             }
155           }
156         }
157         else {
158           /* plain content tag */
159         }
160       }
161       else {
162       }
163     }
164     [object takeValuesFromDictionary:d];
165   }
166   
167   return object;
168 }
169
170 - (id)_processDOMDocument:(id)_dom {
171   return [self _processDOMElementNode:[_dom documentElement]];
172 }
173
174 /* parsing DOM tree */
175
176 - (id)decodeRootObjectFromString:(NSString *)_str {
177   id doc;
178   
179   doc = [NGDOMDocument documentFromString:_str];
180   
181   return [self _processDOMDocument:doc];
182 }
183
184 - (id)decodeRootObjectFromData:(NSData *)_data {
185   id doc;
186   
187   doc = [NGDOMDocument documentFromData:_data];
188   
189   return [self _processDOMDocument:doc];
190 }
191 - (id)decodeRootObjectFromFileHandle:(NSFileHandle *)_fh {
192   return [self decodeRootObjectFromData:[_fh readDataToEndOfFile]];
193 }
194
195 @end /* WOXMLMapDecoder */