1 /* CardGroup.m - this file is part of SOPE
3 * Copyright (C) 2006 Inverse groupe conseil
5 * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
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)
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.
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.
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>
29 #import "NGCardsSaxHandler.h"
30 #import "NSArray+NGCards.h"
34 static id<NSObject,SaxXMLReader> parser = nil;
35 static NGCardsSaxHandler *sax = nil;
37 @implementation CardGroup
39 + (id<NSObject,SaxXMLReader>) cardParser
42 sax = [NGCardsSaxHandler new];
47 parser = [[SaxXMLReaderFactory standardXMLReaderFactory]
48 createXMLReaderWithName: @"VSCardSaxDriver"];
52 [[[SaxXMLReaderFactory standardXMLReaderFactory]
53 createXMLReaderForMimeType:@"text/x-vcard"] retain];
57 [parser setContentHandler:sax];
58 [parser setErrorHandler:sax];
61 NSLog(@"ERROR(%s): did not find a parser for text/x-vcard!",
68 + (NSArray *) parseFromSource: (id) source
70 static id <NSObject,SaxXMLReader> cardParser;
71 NSMutableArray *cardGroups;
73 CardGroup *currentCard;
75 cardParser = [self cardParser];
76 [sax setTopElementClass: [self class]];
80 cardGroups = [NSMutableArray new];
81 [cardGroups autorelease];
83 [parser parseFromSource: source];
84 cards = [[sax cards] objectEnumerator];
86 currentCard = [cards nextObject];
89 [cardGroups addObject: currentCard];
90 currentCard = [cards nextObject];
99 + (id) parseSingleFromSource: (id) source
104 cards = [self parseFromSource: source];
105 if (cards && [cards count])
106 card = [cards objectAtIndex: 0];
113 + (id) groupWithTag: (NSString *) aTag
117 newGroup = [self new];
118 [newGroup autorelease];
119 [newGroup setTag: aTag];
124 + (id) groupWithTag: (NSString *) aTag
125 children: (NSArray *) someChildren
129 newGroup = [self new];
130 [newGroup autorelease];
131 [newGroup setTag: aTag];
132 [newGroup addChildren: someChildren];
139 if ((self = [super init]))
141 children = [NSMutableArray new];
153 - (Class) classForTag: (NSString *) tagClass
155 NSLog (@"class '%@': '%@'", NSStringFromClass([self class]),
161 - (void) addChild: (CardElement *) aChild
165 CardElement *newChild;
167 childTag = [aChild tag];
169 mappedClass = [self classForTag: [childTag uppercaseString]];
172 if (![aChild isKindOfClass: mappedClass])
174 NSLog (@"warning: new child to entity '%@': '%@' converted to '%@'",
175 tag, childTag, NSStringFromClass(mappedClass));
176 if ([aChild isKindOfClass: [CardGroup class]])
177 newChild = [(CardGroup *) aChild groupWithClass: mappedClass];
179 newChild = [aChild elementWithClass: mappedClass];
183 NSLog (@"warning: no mapped class for tag '%@'",
188 [children addObject: newChild];
189 [newChild setParent: self];
192 - (CardElement *) uniqueChildWithTag: (NSString *) aTag
196 CardElement *uniqueChild;
198 existing = [self childrenWithTag: aTag];
199 if ([existing count] > 0)
200 uniqueChild = [existing objectAtIndex: 0];
203 elementClass = [self classForTag: [aTag uppercaseString]];
205 elementClass = [CardElement class];
207 uniqueChild = [elementClass new];
208 [uniqueChild autorelease];
209 [uniqueChild setTag: aTag];
210 [self addChild: uniqueChild];
216 - (void) setUniqueChild: (CardElement *) aChild
218 CardElement *currentChild;
220 NSEnumerator *existing;
222 childTag = [aChild tag];
223 existing = [[self childrenWithTag: childTag] objectEnumerator];
225 currentChild = [existing nextObject];
228 [children removeObject: currentChild];
229 currentChild = [existing nextObject];
232 [self addChild: aChild];
235 - (CardElement *) firstChildWithTag: (NSString *) aTag;
238 CardElement *child, *mappedChild;
241 existing = [self childrenWithTag: aTag];
242 if ([existing count])
244 child = [existing objectAtIndex: 0];
245 mappedClass = [self classForTag: [aTag uppercaseString]];
248 if ([child isKindOfClass: [CardGroup class]])
249 mappedChild = [(CardGroup *) child groupWithClass: mappedClass];
251 mappedChild = [child elementWithClass: mappedClass];
262 - (void) addChildren: (NSArray *) someChildren
264 CardElement *currentChild;
265 NSEnumerator *newChildren;
267 newChildren = [someChildren objectEnumerator];
268 currentChild = [newChildren nextObject];
271 [self addChild: currentChild];
272 currentChild = [newChildren nextObject];
276 - (NSArray *) children
281 - (NSArray *) childrenWithTag: (NSString *) aTag
283 return [children cardElementsWithTag: aTag];
286 - (NSArray *) childrenWithAttribute: (NSString *) anAttribute
287 havingValue: (NSString *) aValue
289 return [children cardElementsWithAttribute: anAttribute
290 havingValue: aValue];
293 - (NSArray *) childrenWithTag: (NSString *) aTag
294 andAttribute: (NSString *) anAttribute
295 havingValue: (NSString *) aValue
299 elements = [self childrenWithTag: aTag];
301 return [elements cardElementsWithAttribute: anAttribute
302 havingValue: aValue];
305 - (NSArray *) childrenGroupWithTag: (NSString *) aTag
306 withChild: (NSString *) aChild
307 havingSimpleValue: (NSString *) aValue
309 NSEnumerator *allElements;
310 NSMutableArray *elements;
314 elements = [NSMutableArray new];
315 [elements autorelease];
317 allElements = [[self childrenWithTag: aTag] objectEnumerator];
318 element = [allElements nextObject];
321 if ([element isKindOfClass: [CardGroup class]])
323 value = [[element uniqueChildWithTag: aChild] value: 0];
324 if ([value isEqualToString: aValue])
325 [elements addObject: element];
327 element = [allElements nextObject];
333 #warning should be renamed to elementWithClass...
334 - (CardGroup *) groupWithClass: (Class) groupClass
338 if ([self isKindOfClass: groupClass])
342 newGroup = (CardGroup *) [self elementWithClass: groupClass];
343 [newGroup setChildrenAsCopy: children];
349 - (void) setChildrenAsCopy: (NSMutableArray *) someChildren
352 children = someChildren;
356 - (void) addChildWithTag: (NSString *) aTag
357 types: (NSArray *) someTypes
358 singleValue: (NSString *) aValue
360 CardElement *newChild;
364 newChild = [CardElement simpleElementWithTag: aTag value: aValue];
365 types = [someTypes objectEnumerator];
366 type = [types nextObject];
369 [newChild addType: type];
370 type = [types nextObject];
373 [self addChild: newChild];
376 - (NSString *) description
378 NSMutableString *str;
379 unsigned int count, max;
381 str = [NSMutableString stringWithCapacity:64];
382 [str appendFormat:@"<%p[%@]:%@",
383 self, NSStringFromClass([self class]), [self tag]];
384 max = [children count];
387 [str appendFormat: @"\n %d children: {\n", [children count]];
388 for (count = 0; count < max; count++)
389 [str appendFormat: @" %@\n",
390 [[children objectAtIndex: count] description]];
391 [str appendFormat: @"}"];
393 [str appendString:@">"];
398 - (void) replaceThisElement: (CardElement *) oldElement
399 withThisOne: (CardElement *) newElement
403 index = [children indexOfObject: oldElement];
404 if (index != NSNotFound)
405 [children replaceObjectAtIndex: index withObject: newElement];
408 - (id) copyWithZone: (NSZone *) aZone
412 new = [super copyWithZone: aZone];
413 [new setChildrenAsCopy: [children copyWithZone: aZone]];