]> err.no Git - scalable-opengroupware.org/blob - SOPE/NGCards/CardElement.m
git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1112 d1b88da0-ebda-0310...
[scalable-opengroupware.org] / SOPE / NGCards / CardElement.m
1 /* CardElement.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/NSRange.h>
26 #import <Foundation/NSString.h>
27
28 #import "NSArray+NGCards.h"
29 #import "NSDictionary+NGCards.h"
30 #import "CardVersitRenderer.h"
31
32 #import "CardElement.h"
33 #import "CardGroup.h"
34
35 @implementation CardElement
36
37 + (id) elementWithTag: (NSString *) aTag
38 {
39   id newElement;
40
41   newElement = [self new];
42   [newElement autorelease];
43   [newElement setTag: aTag];
44
45   return newElement;
46 }
47
48 + (id) simpleElementWithTag: (NSString *) aTag
49                       value: (NSString *) aValue
50 {
51   id newElement;
52
53   newElement = [self elementWithTag: aTag];
54   [newElement addValue: aValue];
55
56   return newElement;
57 }
58
59 + (id) simpleElementWithTag: (NSString *) aTag
60                  singleType: (NSString *) aType
61                       value: (NSString *) aValue
62 {
63   id newElement;
64
65   newElement = [self simpleElementWithTag: aTag
66                      value: aValue];
67   [newElement addType: aType];
68
69   return newElement;
70 }
71
72 + (id) elementWithTag: (NSString *) aTag
73            attributes: (NSDictionary *) someAttributes
74                values: (NSArray *) someValues
75 {
76   id newElement;
77
78   newElement = [self new];
79   [newElement autorelease];
80   [newElement setTag: aTag];
81   [newElement addAttributes: someAttributes];
82   [newElement addValues: someValues];
83
84   return newElement;
85 }
86
87 - (id) init
88 {
89   if ((self = [super init]))
90     {
91       parent = nil;
92       tag = nil;
93       group = nil;
94       values = [NSMutableArray new];
95       attributes = [NSMutableDictionary new];
96     }
97
98   return self;
99 }
100
101 - (void) dealloc
102 {
103   if (tag)
104     [tag release];
105   [values release];
106   [attributes release];
107   [super dealloc];
108 }
109
110 - (void) setParent: (CardGroup *) aParent
111 {
112   parent = aParent;
113 }
114
115 - (CardGroup *) parent
116 {
117   return parent;
118 }
119
120 - (void) setTag: (NSString *) aTag
121 {
122   if (tag)
123     [tag release];
124   tag = aTag;
125   if (tag)
126     [tag retain];
127 }
128
129 - (void) setGroup: (NSString *) aGroup
130 {
131   if (group)
132     [group release];
133   group = aGroup;
134   if (group)
135     [group retain];
136 }
137
138 - (NSString *) group
139 {
140   return group;
141 }
142
143 - (void) addValue: (NSString *) aValue
144 {
145   [values addObject: aValue];
146 }
147
148 - (void) addValues: (NSArray *) someValues
149 {
150   [values addObjectsFromArray: someValues];
151 }
152
153 - (void) addAttribute: (NSString *) anAttribute
154                 value: (NSString *) aType
155 {
156   NSMutableArray *attrValues;
157
158   attrValues = [attributes objectForCaseInsensitiveKey: anAttribute];
159   if (!attrValues)
160     {
161       attrValues = [NSMutableArray new];
162       [attrValues autorelease];
163       [attributes setObject: attrValues forKey: anAttribute];
164     }
165
166   [attrValues addObject: aType];
167 }
168
169 - (void) removeValue: (NSString *) aValue
170        fromAttribute: (NSString *) anAttribute
171 {
172   NSMutableArray *attrValues;
173   NSString *currentValue;
174
175   attrValues = [attributes objectForCaseInsensitiveKey: anAttribute];
176   if (attrValues)
177     {
178       currentValue = [attrValues valueForCaseInsensitiveString: aValue];
179       while (currentValue)
180         {
181           [attrValues removeObject: currentValue];
182           currentValue = [attrValues valueForCaseInsensitiveString: aValue];
183         }
184     }
185 }
186
187 - (void) addAttributes: (NSDictionary *) someAttributes
188 {
189   NSEnumerator *keys;
190   NSString *currentKey;
191   NSMutableArray *oldValues;
192   NSArray *newValues;
193
194   keys = [[someAttributes allKeys] objectEnumerator];
195   currentKey = [keys nextObject];
196   while (currentKey)
197     {
198       oldValues = [attributes objectForCaseInsensitiveKey: currentKey];
199       newValues = [someAttributes objectForKey: currentKey];
200       if (oldValues)
201         [oldValues addObjectsFromArray: newValues];
202       else
203         [attributes setObject: newValues forKey: currentKey];
204       currentKey = [keys nextObject];
205     }
206 }
207
208 - (void) addType: (NSString *) aType
209 {
210   [self addAttribute: @"type" value: aType];
211 }
212
213 - (NSString *) tag
214 {
215   return tag;
216 }
217
218 - (NSArray *) values
219 {
220   return values;
221 }
222
223 - (NSDictionary *) attributes
224 {
225   return attributes;
226 }
227
228 - (BOOL) hasAttribute: (NSString *) anAttribute
229           havingValue: (NSString *) aValue
230 {
231   NSArray *attribute;
232
233   attribute = [attributes objectForCaseInsensitiveKey: anAttribute];
234
235   return (attribute && [attribute hasCaseInsensitiveString: aValue]);
236 }
237
238 - (void) setValue: (unsigned int) anInt
239                to: (NSString *) aValue
240 {
241   while ([values count] <= anInt)
242     [self addValue: @""];
243   [values replaceObjectAtIndex: anInt withObject: aValue];
244 }
245
246 - (NSString *) value: (unsigned int) anInt
247 {
248   NSString *value;
249
250   if ([values count] <= anInt)
251     value = @"";
252   else
253     value = [values objectAtIndex: anInt];
254
255   return value;
256 }
257
258 - (unsigned int) _namedValue: (NSString *) aValueName
259 {
260   NSString *prefix, *value;
261   unsigned int count, max, result;
262
263   result = NSNotFound;
264
265   prefix = [NSString stringWithFormat: @"%@=", [aValueName uppercaseString]];
266   max = [values count];
267   count = 0;
268
269   while (result == NSNotFound && count < max)
270     {
271       value = [[values objectAtIndex: count] uppercaseString];
272       if ([value hasPrefix: prefix])
273         result = count;
274       else
275         count++;
276     }
277
278   return result;
279 }
280
281 - (void) setNamedValue: (NSString *) aValueName
282                     to: (NSString *) aValue
283 {
284   NSString *newValue;
285   unsigned int index;
286
287   newValue = [NSString stringWithFormat: @"%@=%@",
288                        [aValueName uppercaseString],
289                        aValue];
290   index = [self _namedValue: aValueName];
291   if (index == NSNotFound)
292     [self addValue: newValue];
293   else
294     {
295       if (aValue)
296         [self setValue: index to: newValue];
297       else
298         [values removeObjectAtIndex: index];
299     }
300 }
301
302 - (NSString *) namedValue: (NSString *) aValueName
303 {
304   unsigned int index;
305   NSRange equalSign;
306   NSString *value;
307
308   index = [self _namedValue: aValueName];
309   if (index == NSNotFound)
310     value = @"";
311   else
312     {
313       value = [values objectAtIndex: index];
314       equalSign = [value rangeOfString: @"="];
315       if (equalSign.location != NSNotFound)
316         value = [value substringFromIndex: equalSign.location + 1];
317     }
318
319   return value;
320 }
321
322 - (void) setValue: (unsigned int) anInt
323       ofAttribute: (NSString *) anAttribute
324                to: (NSString *) aValue
325 {
326   NSMutableArray *attrValues;
327
328   attrValues = [attributes objectForCaseInsensitiveKey: anAttribute];
329   if (!attrValues)
330     {
331       attrValues = [NSMutableArray new];
332       [attrValues autorelease];
333       [attributes setObject: attrValues forKey: anAttribute];
334     }
335
336   while ([attrValues count] <= anInt)
337     [attrValues addObject: @""];
338   [attrValues replaceObjectAtIndex: anInt
339               withObject: aValue];
340 }
341
342 - (NSString *) value: (unsigned int) anInt
343          ofAttribute: (NSString *) anAttribute
344 {
345   NSArray *attrValues;
346   NSString *value;
347
348   attrValues = [attributes objectForCaseInsensitiveKey: anAttribute];
349   if (attrValues && [attrValues count] > anInt)
350     value = [attrValues objectAtIndex: anInt];
351   else
352     value = @"";
353
354   return value;
355 }
356
357 - (NSString *) description
358 {
359   NSArray *attrs;
360   NSMutableString *str;
361   unsigned int count, max;
362   NSString *attr;
363
364   str = [NSMutableString stringWithCapacity:64];
365   [str appendFormat:@"<%p[%@]:", self, NSStringFromClass([self class])];
366   if (group)
367     [str appendFormat: @"%@ (group: %@)\n", tag, group];
368   else
369     [str appendFormat: @"%@\n", tag, group];
370
371   attrs = [attributes allKeys];
372   max = [attrs count];
373   if (max > 0)
374     {
375       [str appendFormat: @"\n  %d attributes: {\n", [attrs count]];
376       for (count = 0; count < max; count++)
377         {
378           attr = [attrs objectAtIndex: count];
379           [str appendFormat: @"  %@: %@\n",
380                attr, [attributes objectForKey: attr]];
381         }
382       [str appendFormat: @"}"];
383     }
384
385   max = [values count];
386   if (max > 0)
387     {
388       [str appendFormat: @"\n  %d values: {\n", [values count]];
389       for (count = 0; count < max; count++)
390         [str appendFormat: @"  %@\n", [values objectAtIndex: count]];
391       [str appendFormat: @"}"];
392     }
393
394   [str appendString:@">"];
395
396   return str;
397 }
398
399 - (BOOL) isVoid
400 {
401   BOOL result;
402   NSString *value;
403   NSEnumerator *enu;
404
405   result = YES;
406
407   enu = [values objectEnumerator];
408   value = [enu nextObject];
409   while (value && result)
410     {
411       result = ([value length] == 0);
412       value = [enu nextObject];
413     }
414
415   return result;
416 }
417
418 - (NSString *) versitString
419 {
420   NSString *string;
421   CardVersitRenderer *renderer;
422
423   renderer = [CardVersitRenderer new];
424   string = [renderer render: self];
425   [renderer release];
426
427   if ([string hasSuffix: @"\r\n"])
428     string = [string substringToIndex: [string length] - 2];
429
430   return string;
431 }
432
433 - (CardElement *) elementWithClass: (Class) elementClass
434 {
435   CardElement *newElement;
436
437   if ([self isKindOfClass: elementClass])
438     newElement = self;
439   else
440     {
441       newElement = [elementClass new];
442       [newElement autorelease];
443       [newElement setTag: tag];
444       [newElement setValuesAsCopy: values];
445       [newElement setAttributesAsCopy: attributes];
446       if (group)
447         [newElement setGroup: group];
448       if (parent)
449         {
450           [newElement setParent: parent];
451           [parent replaceThisElement: self
452                   withThisOne: newElement];
453         }
454     }
455
456   return newElement;
457 }
458
459 - (void) setValuesAsCopy: (NSMutableArray *) someValues
460 {
461   [values release];
462   values = someValues;
463   [values retain];
464 }
465
466 - (void) setAttributesAsCopy: (NSMutableDictionary *) someAttributes
467 {
468   [attributes release];
469   attributes = someAttributes;
470   [attributes retain];
471 }
472
473 - (CardGroup *) searchParentOfClass: (Class) parentClass
474 {
475   CardGroup *current;
476   CardGroup *found;
477
478   found = nil;
479   current = parent;
480   while (current && !found)
481     if ([current isKindOfClass: parentClass])
482       found = current;
483     else
484       current = [current parent];
485
486   return found;
487 }
488
489 /* NSCopying */
490
491 - (id) copyWithZone: (NSZone *) aZone
492 {
493   CardElement *new;
494
495   new = [[self class] new];
496   [new setTag: [tag copyWithZone: aZone]];
497   [new setGroup: [group copyWithZone: aZone]];
498   [new setParent: parent];
499   [new setValuesAsCopy: [values copyWithZone: aZone]];
500   [new setAttributesAsCopy: [attributes copyWithZone: aZone]];
501
502   return new;
503 }
504
505 @end