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 - (void) addChildren: (NSArray *) someChildren
237 CardElement *currentChild;
238 NSEnumerator *newChildren;
240 newChildren = [someChildren objectEnumerator];
241 currentChild = [newChildren nextObject];
244 [self addChild: currentChild];
245 currentChild = [newChildren nextObject];
249 - (NSArray *) children
254 - (NSArray *) childrenWithTag: (NSString *) aTag
256 return [children cardElementsWithTag: aTag];
259 - (NSArray *) childrenWithAttribute: (NSString *) anAttribute
260 havingValue: (NSString *) aValue
262 return [children cardElementsWithAttribute: anAttribute
263 havingValue: aValue];
266 - (NSArray *) childrenWithTag: (NSString *) aTag
267 andAttribute: (NSString *) anAttribute
268 havingValue: (NSString *) aValue
272 elements = [self childrenWithTag: aTag];
274 return [elements cardElementsWithAttribute: anAttribute
275 havingValue: aValue];
278 - (NSArray *) childrenGroupWithTag: (NSString *) aTag
279 withChild: (NSString *) aChild
280 havingSimpleValue: (NSString *) aValue
282 NSEnumerator *allElements;
283 NSMutableArray *elements;
287 elements = [NSMutableArray new];
288 [elements autorelease];
290 allElements = [[self childrenWithTag: aTag] objectEnumerator];
291 element = [allElements nextObject];
294 if ([element isKindOfClass: [CardGroup class]])
296 value = [[element uniqueChildWithTag: aChild] value: 0];
297 if ([value isEqualToString: aValue])
298 [elements addObject: element];
300 element = [allElements nextObject];
306 #warning should be renamed to elementWithClass...
307 - (CardGroup *) groupWithClass: (Class) groupClass
311 if ([self isKindOfClass: groupClass])
315 newGroup = (CardGroup *) [self elementWithClass: groupClass];
316 [newGroup setChildrenAsCopy: children];
322 - (void) setChildrenAsCopy: (NSMutableArray *) someChildren
325 children = someChildren;
329 - (void) addChildWithTag: (NSString *) aTag
330 types: (NSArray *) someTypes
331 singleValue: (NSString *) aValue
333 CardElement *newChild;
337 newChild = [CardElement simpleElementWithTag: aTag value: aValue];
338 types = [someTypes objectEnumerator];
339 type = [types nextObject];
342 [newChild addType: type];
343 type = [types nextObject];
346 [self addChild: newChild];
349 - (NSString *) description
351 NSMutableString *str;
352 unsigned int count, max;
354 str = [NSMutableString stringWithCapacity:64];
355 [str appendFormat:@"<%p[%@]:%@",
356 self, NSStringFromClass([self class]), [self tag]];
357 max = [children count];
360 [str appendFormat: @"\n %d children: {\n", [children count]];
361 for (count = 0; count < max; count++)
362 [str appendFormat: @" %@\n",
363 [[children objectAtIndex: count] description]];
364 [str appendFormat: @"}"];
366 [str appendString:@">"];
371 - (void) replaceThisElement: (CardElement *) oldElement
372 withThisOne: (CardElement *) newElement
376 index = [children indexOfObject: oldElement];
377 if (index != NSNotFound)
378 [children replaceObjectAtIndex: index withObject: newElement];
381 - (id) copyWithZone: (NSZone *) aZone
385 new = [super copyWithZone: aZone];
386 [new setChildrenAsCopy: [children copyWithZone: aZone]];