]> err.no Git - sope/blob - sope-gdl1/GDLAccess/EOExpressionArray.m
added missing inline pathes
[sope] / sope-gdl1 / GDLAccess / EOExpressionArray.m
1 /* 
2    EOExpressionArray.m
3
4    Copyright (C) 1996 Free Software Foundation, Inc.
5
6    Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
7    Date: September 1996
8
9    This file is part of the GNUstep Database Library.
10
11    This library is free software; you can redistribute it and/or
12    modify it under the terms of the GNU Library General Public
13    License as published by the Free Software Foundation; either
14    version 2 of the License, or (at your option) any later version.
15
16    This library is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19    Library General Public License for more details.
20
21    You should have received a copy of the GNU Library General Public
22    License along with this library; see the file COPYING.LIB.
23    If not, write to the Free Software Foundation,
24    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 */
26
27 #import "common.h"
28 #import "EOExpressionArray.h"
29 #import "EOAttribute.h"
30 #import "EOEntity.h"
31 #import "EORelationship.h"
32
33 @implementation EOExpressionArray
34
35 - (id)init {
36     [super init];
37     self->array  = [[NSMutableArray allocWithZone:[self zone]] init];
38     return self;
39 }
40
41 - (id)initWithPrefix:(NSString *)_prefix
42   infix:(NSString *)_infix
43   suffix:(NSString *)_suffix
44 {
45     [super init];
46     ASSIGN(self->prefix, _prefix);
47     ASSIGN(self->infix,  _infix);
48     ASSIGN(self->suffix, _suffix);
49     RELEASE(self->array);
50     self->array = [[NSMutableArray allocWithZone:[self zone]] init];
51     return self;
52 }
53
54 - (void)dealloc {
55     RELEASE(self->array);
56     RELEASE(self->prefix);
57     RELEASE(self->infix);
58     RELEASE(self->suffix);
59     [super dealloc];
60 }
61
62 - (BOOL)referencesObject:(id)anObject {
63     return [self indexOfObject:anObject] != NSNotFound;
64 }
65
66 - (NSString *)expressionValueForContext:(id<EOExpressionContext>)ctx {
67     if(ctx && [self count] && 
68         [[self objectAtIndex:0] isKindOfClass:[EORelationship class]])
69             return [ctx expressionValueForAttributePath:self->array];
70     else {
71         int i, count;
72         id  result;
73         SEL sel;
74         IMP imp;
75
76         count  = [self count];
77         result = [NSMutableString stringWithCapacity:256];
78         sel    = @selector(appendString:);
79         imp    = [result methodForSelector:sel];
80         
81         if (self->prefix)
82             [result appendString:self->prefix];
83
84         if (count) {
85             id o;
86
87             o = [self objectAtIndex:0];
88             
89             (*imp)(result, sel, [o expressionValueForContext:ctx]);
90             for (i = 1 ; i < count; i++) {
91                 if (self->infix)
92                     (*imp)(result, sel, self->infix);
93
94                 o = [self objectAtIndex:i];
95                 (*imp)(result, sel, [o expressionValueForContext:ctx]);
96             }
97         }
98
99         if (self->suffix)
100             [result appendString:self->suffix];
101
102         return result;
103     }
104 }
105
106 - (void)setPrefix:(NSString *)_prefix {
107     ASSIGN(self->prefix, _prefix);
108 }
109 - (void)setInfix:(NSString *)_infix {
110     ASSIGN(self->infix, _infix);
111 }
112 - (void)setSuffix:(NSString *)_suffix {
113     ASSIGN(self->suffix, _suffix);
114 }
115
116 - (NSString *)prefix {
117     return self->prefix;
118 }
119 - (NSString *)infix {
120     return self->infix;
121 }
122 - (NSString *)suffix {
123     return self->suffix;
124 }
125
126 + (EOExpressionArray *)parseExpression:(NSString *)expression
127   entity:(EOEntity *)entity
128   replacePropertyReferences:(BOOL)replacePropertyReferences
129 {
130     return [EOExpressionArray parseExpression:expression
131                               entity:entity
132                               replacePropertyReferences:
133                                 replacePropertyReferences
134                               relationshipPaths:nil];
135 }
136
137 + (EOExpressionArray *)parseExpression:(NSString *)expression
138   entity:(EOEntity *)entity
139   replacePropertyReferences:(BOOL)replacePropertyReferences
140   relationshipPaths:(NSMutableArray *)relationshipPaths  
141 {
142     EOExpressionArray *exprArray;
143     unsigned char buf[[expression cStringLength] + 4]; // TODO: not too good
144     const unsigned char *s, *start;
145     id objectToken;
146     NSAutoreleasePool *pool;
147     
148     exprArray = [[EOExpressionArray new] autorelease];
149     pool = [[NSAutoreleasePool alloc] init];
150     [expression getCString:(char *)buf];
151     s = buf;
152     
153     /* Divide the expression string in alternating substrings that obey the
154        following simple grammar: 
155
156             I = [a-zA-Z0-9@_#]([a-zA-Z0-9@_.#$])+
157             O = \'.*\' | \".*\" | [^a-zA-Z0-9@_#]+
158             S -> I S | O S | nothing
159     */
160     while(*s) {
161         /* Determines an I token. */
162         if(isalnum((int)*s) || *s == '@' || *s == '_' || *s == '#') {
163             start = s;
164             for(++s; *s; s++)
165                 if(!isalnum((int)*s) && *s != '@' && *s != '_'
166                         && *s != '.' && *s != '#' && *s != '$')
167                     break;
168
169             objectToken = [NSString stringWithCString:(char *)start
170                                     length:(unsigned)(s - start)];
171             if (replacePropertyReferences) {
172                 id property = [entity propertyNamed:objectToken];
173                 if(property) {
174                     if ([objectToken isNameOfARelationshipPath] &&
175                         relationshipPaths) {
176                         [relationshipPaths addObject:
177                                                [entity relationshipsNamed:
178                                                            objectToken]];
179                     }
180                     objectToken = property;
181                 }
182             }
183             [exprArray addObject:objectToken];
184         }
185         
186         /* Determines an O token. */
187         start = s;
188         for(; *s && !isalnum((int)*s) && *s != '@' && *s != '_' && *s != '#'; 
189             s++) {
190             if(*s == '\'' || *s == '"') {
191                 unsigned char quote = *s;
192                 
193                 for(++s; *s; s++)
194                     if(*s == quote)
195                         break;
196                     else if(*s == '\\')
197                         s++; /* Skip the escaped characters */
198                 if(!*s) {
199                     [NSException raise:@"SyntaxErrorException"
200                                  format:@"unterminated character string"];
201                 }
202             }
203         }
204         if (s != start) {
205             objectToken = [NSString stringWithCString:(char *)start
206                                     length:(unsigned)(s - start)];
207             [exprArray addObject:objectToken];
208         }
209     }
210     
211     [pool release];
212     return exprArray;
213 }
214
215 /* NSMutableCopying */
216
217 - (id)copyWithZone:(NSZone *)_zone {
218     return [self mutableCopyWithZone:_zone];
219 }
220 - (id)mutableCopyWithZone:(NSZone *)_zone {
221     EOExpressionArray *new;
222
223     new = [[EOExpressionArray allocWithZone:_zone]
224                               initWithPrefix:self->prefix
225                               infix:self->infix
226                               suffix:self->suffix];
227     RELEASE(new->array); new->array = nil;
228     new->array = [self->array mutableCopyWithZone:_zone];
229
230     return new;
231 }
232
233 /* NSArray compatibility */
234
235 - (void)addObjectsFromExpressionArray:(EOExpressionArray *)_array {
236     [self->array addObjectsFromArray:_array->array];
237 }
238
239 - (void)insertObject:(id)_obj atIndex:(unsigned int)_idx {
240     [self->array insertObject:_obj atIndex:_idx];
241 }
242 - (void)addObjectsFromArray:(NSArray *)_array {
243     [self->array addObjectsFromArray:_array];
244 }
245
246 - (void)addObject:(id)_object {
247     [self->array addObject:_object];
248 }
249
250 - (unsigned int)indexOfObject:(id)_object {
251     return [self->array indexOfObject:_object];
252 }
253
254 - (id)objectAtIndex:(unsigned int)_idx {
255     return [self->array objectAtIndex:_idx];
256 }
257 - (id)lastObject {
258     return [self->array lastObject];
259 }
260 - (unsigned int)count {
261     return [self->array count];
262 }
263
264 - (NSEnumerator *)objectEnumerator {
265     return [self->array objectEnumerator];
266 }
267 - (NSEnumerator *)reverseObjectEnumerator {
268     return [self->array reverseObjectEnumerator];
269 }
270
271 - (NSString *)description {
272   NSMutableString *ms;
273
274   ms = [NSMutableString stringWithCapacity:128];
275   [ms appendFormat:@"<0x%08X[%@]:", self, NSStringFromClass([self class])];
276
277   if (self->array)  [ms appendFormat:@" array=%@", self->array];
278   if (self->prefix) [ms appendFormat:@" prefix='%@'", self->prefix];
279   if (self->infix)  [ms appendFormat:@" infix='%@'",  self->infix];
280   if (self->suffix) [ms appendFormat:@" suffix='%@'", self->suffix];
281   
282   [ms appendString:@">"];
283   return ms;
284 }
285
286 @end /* EOExpressionArray */
287
288 @implementation NSObject(EOExpression)
289
290 - (NSString *)expressionValueForContext:(id<EOExpressionContext>)ctx {
291     if([self respondsToSelector:@selector(stringValue)])
292         return [(id)self stringValue];
293
294     return [self description];
295 }
296
297 @end /* NSObject(EOExpression) */
298
299 @implementation NSString(EOExpression)
300
301 /* 
302    Avoid returning the description in case of NSString because if the string
303    contains whitespaces it will be quoted. Particular adaptors have to override
304    -formatValue:forAttribute: and they have to quote with the specific
305    database character the returned string. 
306 */
307 - (NSString *)expressionValueForContext:(id<EOExpressionContext>)ctx {
308     return self;
309 }
310
311 @end /* NSString(EOExpression) */
312
313 /*
314   Local Variables:
315   c-basic-offset: 4
316   tab-width: 8
317   End:
318 */