]> err.no Git - scalable-opengroupware.org/blob - SOPE/NGCards/CardGroup.m
git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1178 d1b88da0-ebda-0310...
[scalable-opengroupware.org] / SOPE / NGCards / CardGroup.m
1 /* CardGroup.m - this file is part of SOPE
2  *
3  * Copyright (C) 2006 Inverse groupe conseil
4  *
5  * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
6  *
7  * This file is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2, or (at your option)
10  * any later version.
11  *
12  * This file is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; see the file COPYING.  If not, write to
19  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #import <Foundation/NSArray.h>
24 #import <Foundation/NSDictionary.h>
25 #import <Foundation/NSString.h>
26 #import <SaxObjC/SaxXMLReader.h>
27 #import <SaxObjC/SaxXMLReaderFactory.h>
28
29 #import "NGCardsSaxHandler.h"
30 #import "NSArray+NGCards.h"
31
32 #import "CardGroup.h"
33
34 static id<NSObject,SaxXMLReader> parser = nil;
35 static NGCardsSaxHandler *sax = nil;
36
37 @implementation CardGroup
38
39 + (id<NSObject,SaxXMLReader>) cardParser
40 {
41   if (!sax)
42     sax = [NGCardsSaxHandler new];
43   
44   if (!parser)
45     {
46 #if 1
47       parser = [[SaxXMLReaderFactory standardXMLReaderFactory]
48                  createXMLReaderWithName: @"VSCardSaxDriver"];
49       [parser retain];
50 #else
51       parser =
52         [[[SaxXMLReaderFactory standardXMLReaderFactory] 
53            createXMLReaderForMimeType:@"text/x-vcard"] retain];
54 #endif
55       if (parser)
56         {
57           [parser setContentHandler:sax];
58           [parser setErrorHandler:sax];
59         }
60       else
61         NSLog(@"ERROR(%s): did not find a parser for text/x-vcard!",
62               __PRETTY_FUNCTION__);
63     }
64   
65   return parser;
66 }
67
68 + (NSArray *) parseFromSource: (id) source
69 {
70   static id <NSObject,SaxXMLReader> cardParser;
71   NSMutableArray *cardGroups;
72   NSEnumerator *cards;
73   CardGroup *currentCard;
74
75   cardParser = [self cardParser];
76   [sax setTopElementClass: [self class]];
77
78   if (parser)
79     {
80       cardGroups = [NSMutableArray new];
81       [cardGroups autorelease];
82       
83       [parser parseFromSource: source];
84       cards = [[sax cards] objectEnumerator];
85
86       currentCard = [cards nextObject];
87       while (currentCard)
88         {
89           [cardGroups addObject: currentCard];
90           currentCard = [cards nextObject];
91         }
92     }
93   else
94     cardGroups = nil;
95
96   return cardGroups;
97 }
98
99 + (id) parseSingleFromSource: (id) source
100 {
101   NSArray *cards;
102   CardGroup *card;
103
104   cards = [self parseFromSource: source];
105   if (cards && [cards count])
106     card = [cards objectAtIndex: 0];
107   else
108     card = nil;
109
110   return card;
111 }
112
113 + (id) groupWithTag: (NSString *) aTag
114 {
115   return [self elementWithTag: aTag];
116 }
117
118 + (id) groupWithTag: (NSString *) aTag
119            children: (NSArray *) someChildren
120 {
121   id newGroup;
122
123   newGroup = [self elementWithTag: aTag];
124   [newGroup addChildren: someChildren];
125
126   return newGroup;
127 }
128
129 - (id) init
130 {
131   if ((self = [super init]))
132     {
133       children = [NSMutableArray new];
134     }
135
136   return self;
137 }
138
139 - (void) dealloc
140 {
141   [children release];
142   [super dealloc];
143 }
144
145 - (Class) classForTag: (NSString *) tagClass
146 {
147   NSLog (@"class '%@': '%@'", NSStringFromClass([self class]),
148          tagClass);
149
150   return nil;
151 }
152
153 - (void) addChild: (CardElement *) aChild
154 {
155   Class mappedClass;
156   NSString *childTag;
157   CardElement *newChild;
158
159   childTag = [aChild tag];
160   newChild = nil;
161   mappedClass = [self classForTag: [childTag uppercaseString]];
162   if (mappedClass)
163     {
164       if (![aChild isKindOfClass: mappedClass])
165         {
166           NSLog (@"warning: new child to entity '%@': '%@' converted to '%@'",
167                  tag, childTag, NSStringFromClass(mappedClass));
168           if ([aChild isKindOfClass: [CardGroup class]])
169             newChild = [(CardGroup *) aChild groupWithClass: mappedClass];
170           else
171             newChild = [aChild elementWithClass: mappedClass];
172         }
173     }
174   else
175     NSLog (@"warning: no mapped class for tag '%@'",
176            childTag);
177
178   if (!newChild)
179     newChild = aChild;
180   [children addObject: newChild];
181   [newChild setParent: self];
182 }
183
184 - (CardElement *) uniqueChildWithTag: (NSString *) aTag
185 {
186   NSArray *existing;
187   Class elementClass;
188   CardElement *uniqueChild;
189
190   existing = [self childrenWithTag: aTag];
191   if ([existing count] > 0)
192     uniqueChild = [existing objectAtIndex: 0];
193   else
194     {
195       elementClass = [self classForTag: [aTag uppercaseString]];
196       if (!elementClass)
197         elementClass = [CardElement class];
198
199       uniqueChild = [elementClass new];
200       [uniqueChild autorelease];
201       [uniqueChild setTag: aTag];
202       [self addChild: uniqueChild];
203     }
204
205   return uniqueChild;
206 }
207
208 - (void) setUniqueChild: (CardElement *) aChild
209 {
210   CardElement *currentChild;
211   NSString *childTag;
212   NSEnumerator *existing;
213
214   childTag = [aChild tag];
215   existing = [[self childrenWithTag: childTag] objectEnumerator];
216
217   currentChild = [existing nextObject];
218   while (currentChild)
219     {
220       [children removeObject: currentChild];
221       currentChild = [existing nextObject];
222     }
223
224   [self addChild: aChild];
225 }
226
227 - (CardElement *) firstChildWithTag: (NSString *) aTag;
228 {
229   Class mappedClass;
230   CardElement *child, *mappedChild;
231   NSArray *existing;
232
233   existing = [self childrenWithTag: aTag];
234   if ([existing count])
235     {
236       child = [existing objectAtIndex: 0];
237       mappedClass = [self classForTag: [aTag uppercaseString]];
238       if (mappedClass)
239         {
240           if ([child isKindOfClass: [CardGroup class]])
241             mappedChild = [(CardGroup *) child groupWithClass: mappedClass];
242           else
243             mappedChild = [child elementWithClass: mappedClass];
244         }
245       else
246         mappedChild = child;
247     }
248   else
249     mappedChild = nil;
250
251   return mappedChild;
252 }
253
254 - (void) addChildren: (NSArray *) someChildren
255 {
256   CardElement *currentChild;
257   NSEnumerator *newChildren;
258
259   newChildren = [someChildren objectEnumerator];
260   currentChild = [newChildren nextObject];
261   while (currentChild)
262     {
263       [self addChild: currentChild];
264       currentChild = [newChildren nextObject];
265     }
266 }
267
268 - (NSArray *) children
269 {
270   return children;
271 }
272
273 - (NSArray *) childrenWithTag: (NSString *) aTag
274 {
275   return [children cardElementsWithTag: aTag];
276 }
277
278 - (NSArray *) childrenWithAttribute: (NSString *) anAttribute
279                         havingValue: (NSString *) aValue
280 {
281   return [children cardElementsWithAttribute: anAttribute
282                    havingValue: aValue];
283 }
284
285 - (NSArray *) childrenWithTag: (NSString *) aTag
286                  andAttribute: (NSString *) anAttribute
287                   havingValue: (NSString *) aValue
288 {
289   NSArray *elements;
290
291   elements = [self childrenWithTag: aTag];
292
293   return [elements cardElementsWithAttribute: anAttribute
294                    havingValue: aValue];
295 }
296
297 - (NSArray *) childrenGroupWithTag: (NSString *) aTag
298                          withChild: (NSString *) aChild
299                  havingSimpleValue: (NSString *) aValue
300 {
301   NSEnumerator *allElements;
302   NSMutableArray *elements;
303   CardGroup *element;
304   NSString *value;
305
306   elements = [NSMutableArray new];
307   [elements autorelease];
308
309   allElements = [[self childrenWithTag: aTag] objectEnumerator];
310   element = [allElements nextObject];
311   while (element)
312     {
313       if ([element isKindOfClass: [CardGroup class]])
314         {
315           value = [[element uniqueChildWithTag: aChild] value: 0];
316           if ([value isEqualToString: aValue])
317             [elements addObject: element];
318         }
319       element = [allElements nextObject];
320     }
321
322   return elements;
323 }
324
325 #warning should be renamed to elementWithClass...
326 - (CardGroup *) groupWithClass: (Class) groupClass
327 {
328   CardGroup *newGroup;
329
330   if ([self isKindOfClass: groupClass])
331     newGroup = self;
332   else
333     {
334       newGroup = (CardGroup *) [self elementWithClass: groupClass];
335       [newGroup setChildrenAsCopy: children];
336     }
337
338   return newGroup;
339 }
340
341 - (void) setChildrenAsCopy: (NSMutableArray *) someChildren
342 {
343   [children release];
344   children = someChildren;
345   [children retain];
346 }
347
348 - (void) addChildWithTag: (NSString *) aTag
349                    types: (NSArray *) someTypes
350              singleValue: (NSString *) aValue
351 {
352   CardElement *newChild;
353   NSEnumerator *types;
354   NSString *type;
355
356   newChild = [CardElement simpleElementWithTag: aTag value: aValue];
357   types = [someTypes objectEnumerator];
358   type = [types nextObject];
359   while (type)
360     {
361       [newChild addType: type];
362       type = [types nextObject];
363     }
364
365   [self addChild: newChild];
366 }
367
368 - (NSString *) description
369 {
370   NSMutableString *str;
371   unsigned int count, max;
372
373   str = [NSMutableString stringWithCapacity:64];
374   [str appendFormat:@"<%p[%@]:%@",
375        self, NSStringFromClass([self class]), [self tag]];
376   max = [children count];
377   if (max > 0)
378     {
379       [str appendFormat: @"\n  %d children: {\n", [children count]];
380       for (count = 0; count < max; count++)
381         [str appendFormat: @"  %@\n",
382              [[children objectAtIndex: count] description]];
383       [str appendFormat: @"}"];
384     }
385   [str appendString:@">"];
386
387   return str;
388 }
389
390 - (void) replaceThisElement: (CardElement *) oldElement
391                 withThisOne: (CardElement *) newElement
392 {
393   unsigned int index;
394
395   index = [children indexOfObject: oldElement];
396   if (index != NSNotFound)
397     [children replaceObjectAtIndex: index withObject: newElement];
398 }
399
400 - (id) copyWithZone: (NSZone *) aZone
401 {
402   CardGroup *new;
403
404   new = [super copyWithZone: aZone];
405   [new setChildrenAsCopy: [children copyWithZone: aZone]];
406
407   return new;
408 }
409
410 @end