4 Copyright (C) 1996 Free Software Foundation, Inc.
6 Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
9 This file is part of the GNUstep Database Library.
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.
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.
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.
28 #import "EOExpressionArray.h"
29 #import "EOAttribute.h"
31 #import "EORelationship.h"
33 @implementation EOExpressionArray
37 self->array = [[NSMutableArray allocWithZone:[self zone]] init];
41 - (id)initWithPrefix:(NSString *)_prefix
42 infix:(NSString *)_infix
43 suffix:(NSString *)_suffix
46 ASSIGN(self->prefix, _prefix);
47 ASSIGN(self->infix, _infix);
48 ASSIGN(self->suffix, _suffix);
50 self->array = [[NSMutableArray allocWithZone:[self zone]] init];
56 RELEASE(self->prefix);
58 RELEASE(self->suffix);
62 - (BOOL)referencesObject:(id)anObject {
63 return [self indexOfObject:anObject] != NSNotFound;
66 - (NSString *)expressionValueForContext:(id<EOExpressionContext>)ctx {
67 if(ctx && [self count] &&
68 [[self objectAtIndex:0] isKindOfClass:[EORelationship class]])
69 return [ctx expressionValueForAttributePath:self->array];
77 result = [NSMutableString stringWithCapacity:256];
78 sel = @selector(appendString:);
79 imp = [result methodForSelector:sel];
82 [result appendString:self->prefix];
87 o = [self objectAtIndex:0];
89 (*imp)(result, sel, [o expressionValueForContext:ctx]);
90 for (i = 1 ; i < count; i++) {
92 (*imp)(result, sel, self->infix);
94 o = [self objectAtIndex:i];
95 (*imp)(result, sel, [o expressionValueForContext:ctx]);
100 [result appendString:self->suffix];
106 - (void)setPrefix:(NSString *)_prefix {
107 ASSIGN(self->prefix, _prefix);
109 - (void)setInfix:(NSString *)_infix {
110 ASSIGN(self->infix, _infix);
112 - (void)setSuffix:(NSString *)_suffix {
113 ASSIGN(self->suffix, _suffix);
116 - (NSString *)prefix {
119 - (NSString *)infix {
122 - (NSString *)suffix {
126 + (EOExpressionArray *)parseExpression:(NSString *)expression
127 entity:(EOEntity *)entity
128 replacePropertyReferences:(BOOL)replacePropertyReferences
130 return [EOExpressionArray parseExpression:expression
132 replacePropertyReferences:
133 replacePropertyReferences
134 relationshipPaths:nil];
137 + (EOExpressionArray *)parseExpression:(NSString *)expression
138 entity:(EOEntity *)entity
139 replacePropertyReferences:(BOOL)replacePropertyReferences
140 relationshipPaths:(NSMutableArray *)relationshipPaths
142 EOExpressionArray *exprArray;
143 unsigned char buf[[expression cStringLength] + 4]; // TODO: not too good
144 const unsigned char *s, *start;
146 NSAutoreleasePool *pool;
148 exprArray = [[EOExpressionArray new] autorelease];
149 pool = [[NSAutoreleasePool alloc] init];
150 [expression getCString:(char *)buf];
153 /* Divide the expression string in alternating substrings that obey the
154 following simple grammar:
156 I = [a-zA-Z0-9@_#]([a-zA-Z0-9@_.#$])+
157 O = \'.*\' | \".*\" | [^a-zA-Z0-9@_#]+
158 S -> I S | O S | nothing
161 /* Determines an I token. */
162 if(isalnum((int)*s) || *s == '@' || *s == '_' || *s == '#') {
165 if(!isalnum((int)*s) && *s != '@' && *s != '_'
166 && *s != '.' && *s != '#' && *s != '$')
169 objectToken = [NSString stringWithCString:(char *)start
170 length:(unsigned)(s - start)];
171 if (replacePropertyReferences) {
172 id property = [entity propertyNamed:objectToken];
174 if ([objectToken isNameOfARelationshipPath] &&
176 [relationshipPaths addObject:
177 [entity relationshipsNamed:
180 objectToken = property;
183 [exprArray addObject:objectToken];
186 /* Determines an O token. */
188 for(; *s && !isalnum((int)*s) && *s != '@' && *s != '_' && *s != '#';
190 if(*s == '\'' || *s == '"') {
191 unsigned char quote = *s;
197 s++; /* Skip the escaped characters */
199 [NSException raise:@"SyntaxErrorException"
200 format:@"unterminated character string"];
205 objectToken = [NSString stringWithCString:(char *)start
206 length:(unsigned)(s - start)];
207 [exprArray addObject:objectToken];
215 /* NSMutableCopying */
217 - (id)copyWithZone:(NSZone *)_zone {
218 return [self mutableCopyWithZone:_zone];
220 - (id)mutableCopyWithZone:(NSZone *)_zone {
221 EOExpressionArray *new;
223 new = [[EOExpressionArray allocWithZone:_zone]
224 initWithPrefix:self->prefix
226 suffix:self->suffix];
227 RELEASE(new->array); new->array = nil;
228 new->array = [self->array mutableCopyWithZone:_zone];
233 /* NSArray compatibility */
235 - (void)addObjectsFromExpressionArray:(EOExpressionArray *)_array {
236 [self->array addObjectsFromArray:_array->array];
239 - (void)insertObject:(id)_obj atIndex:(unsigned int)_idx {
240 [self->array insertObject:_obj atIndex:_idx];
242 - (void)addObjectsFromArray:(NSArray *)_array {
243 [self->array addObjectsFromArray:_array];
246 - (void)addObject:(id)_object {
247 [self->array addObject:_object];
250 - (unsigned int)indexOfObject:(id)_object {
251 return [self->array indexOfObject:_object];
254 - (id)objectAtIndex:(unsigned int)_idx {
255 return [self->array objectAtIndex:_idx];
258 return [self->array lastObject];
260 - (unsigned int)count {
261 return [self->array count];
264 - (NSEnumerator *)objectEnumerator {
265 return [self->array objectEnumerator];
267 - (NSEnumerator *)reverseObjectEnumerator {
268 return [self->array reverseObjectEnumerator];
271 - (NSString *)description {
274 ms = [NSMutableString stringWithCapacity:128];
275 [ms appendFormat:@"<0x%08X[%@]:", self, NSStringFromClass([self class])];
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];
282 [ms appendString:@">"];
286 @end /* EOExpressionArray */
288 @implementation NSObject(EOExpression)
290 - (NSString *)expressionValueForContext:(id<EOExpressionContext>)ctx {
291 if([self respondsToSelector:@selector(stringValue)])
292 return [(id)self stringValue];
294 return [self description];
297 @end /* NSObject(EOExpression) */
299 @implementation NSString(EOExpression)
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.
307 - (NSString *)expressionValueForContext:(id<EOExpressionContext>)ctx {
311 @end /* NSString(EOExpression) */