1/*
2  Copyright (C) 2004-2007 SKYRIX Software AG
3
4  This file is part of OpenGroupware.org.
5
6  OGo is free software; you can redistribute it and/or modify it under
7  the terms of the GNU Lesser General Public License as published by the
8  Free Software Foundation; either version 2, or (at your option) any
9  later version.
10
11  OGo is distributed in the hope that it will be useful, but WITHOUT ANY
12  WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14  License for more details.
15
16  You should have received a copy of the GNU Lesser General Public
17  License along with OGo; see the file COPYING.  If not, write to the
18  Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19  02111-1307, USA.
20*/
21
22#import <Foundation/NSValue.h>
23
24#import <NGExtensions/NSNull+misc.h>
25#import <NGExtensions/NSObject+Logs.h>
26
27#import "EOQualifier+GCS.h"
28
29#if (defined(__GNU_LIBOBJC__) && (__GNU_LIBOBJC__ >= 20100911)) || defined(APPLE_RUNTIME) || defined(__GNUSTEP_RUNTIME__)
30#  define sel_eq(__A__,__B__) sel_isEqual(__A__,__B__)
31#endif
32
33@implementation EOQualifier(GCS)
34
35- (void) _appendAndQualifier: (EOAndQualifier *) _q
36                    toString: (NSMutableString *) _ms
37{
38  // TODO: move to EOQualifier category
39  NSArray *qs;
40  unsigned i, count;
41
42  qs = [_q qualifiers];
43  if ((count = [qs count]) == 0)
44    return;
45
46  for (i = 0; i < count; i++) {
47    if (i != 0) [_ms appendString:@" AND "];
48    if (count > 1) [_ms appendString:@"("];
49    [[qs objectAtIndex:i] _gcsAppendToString: _ms];
50    if (count > 1) [_ms appendString:@")"];
51  }
52}
53- (void)_appendOrQualifier: (EOAndQualifier *) _q
54                  toString: (NSMutableString *) _ms
55{
56  // TODO: move to EOQualifier category
57  NSArray *qs;
58  unsigned i, count;
59
60  qs = [_q qualifiers];
61  if ((count = [qs count]) == 0)
62    return;
63
64  for (i = 0; i < count; i++) {
65    if (i != 0) [_ms appendString:@" OR "];
66    if (count > 1) [_ms appendString:@"("];
67    [[qs objectAtIndex:i] _gcsAppendToString: _ms];
68    if (count > 1) [_ms appendString:@")"];
69  }
70}
71
72- (void)_appendNotQualifier: (EONotQualifier *)_q
73                   toString:(NSMutableString *) _ms
74{
75  [_ms appendString:@" NOT ("];
76  [[_q qualifier] _gcsAppendToString: _ms];
77  [_ms appendString:@")"];
78}
79
80- (void) _appendKeyValueQualifier: (EOKeyValueQualifier *) _q
81                         toString: (NSMutableString *) _ms
82{
83  id val;
84  NSString *qKey, *qOperator, *qValue, *qFormat;
85  BOOL isCI;
86
87  qKey = [_q key];
88  isCI = NO;
89
90  SEL op = [_q selector];
91
92  val = [_q value];
93  if (val && [val isNotNull]) {
94    if (sel_eq(op, EOQualifierOperatorEqual))
95      qOperator = @"=";
96    else if (sel_eq(op, EOQualifierOperatorNotEqual))
97      qOperator = @"!=";
98    else if (sel_eq(op, EOQualifierOperatorLessThan))
99      qOperator = @"<";
100    else if (sel_eq(op, EOQualifierOperatorGreaterThan))
101      qOperator = @">";
102    else if (sel_eq(op, EOQualifierOperatorLessThanOrEqualTo))
103      qOperator = @"<=";
104    else if (sel_eq(op, EOQualifierOperatorGreaterThanOrEqualTo))
105      qOperator = @">=";
106    else if (sel_eq(op, EOQualifierOperatorLike))
107      qOperator = @"LIKE";
108    else if (sel_eq(op, EOQualifierOperatorCaseInsensitiveLike)) {
109      isCI = YES;
110      qOperator = @"LIKE";
111    }
112    else {
113      [self errorWithFormat:@"%s: unsupported operation for null: %@",
114	    __PRETTY_FUNCTION__, NSStringFromSelector(op)];
115      qOperator = @"=";
116    }
117
118    if ([val isKindOfClass: [NSNumber class]])
119      qValue = [val stringValue];
120    else if ([val isKindOfClass: [NSString class]]) {
121      if ([(EOKeyValueQualifier *)self formatted])
122        qValue = val;
123      else
124        qValue = [NSString stringWithFormat: @"'%@'", val];
125    }
126    else {
127      qValue = @"NULL";
128      [self errorWithFormat:@"%s: unsupported value class: %@",
129	    __PRETTY_FUNCTION__, NSStringFromClass([val class])];
130    }
131  }
132  else {
133    if (sel_eq(op, EOQualifierOperatorEqual)) {
134      qOperator = @"IS";
135      qValue = @"NULL";
136    }
137    else if (sel_eq(op, EOQualifierOperatorNotEqual)) {
138      qOperator = @"IS NOT";
139      qValue = @"NULL";
140    }
141    else {
142      qOperator = @"IS";
143      qValue = @"NULL";
144      [self errorWithFormat:@"%s: invalid operation for null: %@",
145	    __PRETTY_FUNCTION__, NSStringFromSelector(op)];
146    }
147  }
148
149  if (isCI)
150    qFormat = @"UPPER(%@) %@ UPPER(%@)";
151  else
152    qFormat = @"%@ %@ %@";
153
154  [_ms appendFormat: qFormat, qKey, qOperator, qValue];
155}
156
157- (void) _appendQualifier: (EOQualifier *) _q
158                 toString: (NSMutableString *) _ms
159{
160  if (_q == nil) return;
161
162  if ([_q isKindOfClass: [EOAndQualifier class]])
163    [self _appendAndQualifier: (id)_q
164                     toString: _ms];
165  else if ([_q isKindOfClass: [EOOrQualifier class]])
166    [self _appendOrQualifier: (id)_q
167                    toString:_ms];
168  else if ([_q isKindOfClass: [EOKeyValueQualifier class]])
169    [self _appendKeyValueQualifier: (id)_q
170                          toString:_ms];
171  else if ([_q isKindOfClass: [EONotQualifier class]])
172    [self _appendNotQualifier: (id)_q
173                     toString:_ms];
174  else
175    [self errorWithFormat:@"unknown qualifier: %@", _q];
176}
177
178- (void) _gcsAppendToString: (NSMutableString *) _ms
179{
180  [self _appendQualifier: self
181                toString: _ms];
182}
183
184@end /* EOQualifier(GCS) */
185