]> err.no Git - sope/blob - sope-gdl1/GDLAccess/EOFault.m
fixed bug in GDL adaptor lookup
[sope] / sope-gdl1 / GDLAccess / EOFault.m
1 /* 
2    EOAttributeOrdering.m
3
4    Copyright (C) 1996 Free Software Foundation, Inc.
5
6    Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
7    Date: 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 // $Id: EOFault.m 1 2004-08-20 10:38:46Z znek $
28
29 #include "EOFault.h"
30 #include "EOFaultHandler.h"
31 #include "common.h"
32
33 #if NeXT_RUNTIME || APPLE_RUNTIME
34 #  include <objc/objc-class.h>
35 #endif
36
37 typedef struct {
38     Class isa;
39 } *my_objc_object;
40
41 #if GNU_RUNTIME
42 #  define object_is_instance(object) \
43       ((object!=nil)&&CLS_ISCLASS(((my_objc_object)object)->isa))
44 #else
45 #  warning TODO: implement for NeXT/Apple runtime!
46 #  define object_is_instance(object) (object!=nil?YES:NO)
47 #endif
48
49
50 /*
51  * EOFault class
52  */
53
54 @implementation EOFault
55
56 + (void)makeObjectIntoFault:(id)_object withHandler:(EOFaultHandler *)_handler {
57   [_handler setTargetClass:[_object class] extraData:((id *)_object)[1]];
58
59   ((EOFault *)_object)->isa           = self;
60   ((EOFault *)_object)->faultResolver = [_handler retain];
61 }
62
63 + (EOFaultHandler *)handlerForFault:(id)_fault {
64   if (![self isFault:_fault])
65     return nil;
66
67   return ((EOFault *)_fault)->faultResolver;
68 }
69
70 /* Fault class methods */
71
72 + (void)clearFault:(id)fault {
73   EOFault *aFault = (EOFault*)fault;
74   int refs;
75
76   /* check if fault */
77   if (aFault->isa != self)
78     return;
79     
80   /* get fault instance reference count + 1 set in creation methods */
81   refs = aFault->faultResolver->faultReferences;
82
83   /* make clear instance */
84   aFault->isa           = [aFault->faultResolver targetClass];
85   aFault->faultResolver = [aFault->faultResolver autorelease];
86   aFault->faultResolver = [aFault->faultResolver extraData];
87   
88   /*
89     set references to real instance so that
90     re-implemented retain/release mechanism take control
91   */
92   while(refs-- > 0)
93     [aFault retain];
94 }
95
96 + (BOOL)isFault:(id)fault {
97   static Class EOFaultClass = Nil;
98   Class clazz;
99
100   if (fault == nil) return NO;
101   if (EOFaultClass == Nil) EOFaultClass = [EOFault class];
102   
103   for (clazz = ((EOFault *)fault)->isa; clazz; clazz = clazz->super_class) {
104     if (clazz == EOFaultClass)
105       return YES;
106   }
107   return NO;
108 }
109 + (BOOL)isFault {
110   return NO; // no class faults
111 }
112 - (BOOL)isFault {
113   return YES;
114 }
115
116 + (Class)targetClassForFault:(id)_fault {
117   EOFault *aFault = (EOFault*)_fault;
118
119   // Check that argument is fault
120   if (aFault->isa != self)
121     return nil;
122     
123   return [aFault->faultResolver targetClass];
124 }
125
126 // Fault Instance methods
127
128 - (Class)superclass {
129 #if GNU_RUNTIME
130   return (object_is_instance(self))
131     ? [[self->faultResolver classForFault:self] superclass]
132     : class_get_super_class((Class)self);
133 #else
134 #  warning TODO: add complete implementation for NeXT/Apple runtime!
135   return [[self->faultResolver classForFault:self] superclass];
136 #endif
137 }
138
139 + (Class)class {
140   return self;
141 }
142 - (Class)class {
143   return [self->faultResolver classForFault:self];
144 }
145
146 - (BOOL)isKindOfClass:(Class)_class; {
147   return [self->faultResolver isKindOfClass:_class forFault:self];
148 }
149 - (BOOL)isMemberOfClass:(Class)_class {
150   return [self->faultResolver isMemberOfClass:_class forFault:self];
151 }
152
153 - (BOOL)conformsToProtocol:(Protocol *)_protocol {
154   return [self->faultResolver conformsToProtocol:_protocol forFault:self];
155 }
156
157 + (BOOL)respondsToSelector:(SEL)_selector {
158 #if GNU_RUNTIME
159   return class_get_instance_method(self, _selector) != NULL;
160 #else
161 #  warning TODO: add complete implementation for Apple/NeXT runtime!
162   return NO;
163 #endif
164 }
165
166 - (BOOL)respondsToSelector:(SEL)_selector {
167 #if GNU_RUNTIME
168   return (object_is_instance(self))
169     ? [self->faultResolver respondsToSelector:_selector forFault:self]
170     : class_get_class_method(self->isa, _selector) != METHOD_NULL;
171 #else
172 #  warning TODO: add complete implementation for Apple/NeXT runtime!
173   return [self->faultResolver respondsToSelector:_selector forFault:self];
174 #endif
175 }
176
177 // ******************** retain counting ********************
178
179 + (id)retain {
180   return self;
181 }
182 - (id)retain {
183   self->faultResolver->faultReferences++;
184   return self;
185 }
186
187 + (oneway void)release {
188 }
189 - (oneway void)release {
190   if (faultResolver->faultReferences <= 0)
191     [self dealloc];
192   else
193     faultResolver->faultReferences--;
194 }
195
196 + (unsigned)retainCount {
197   return 1;
198 }
199 - (unsigned)retainCount {
200   // For instance
201   return faultResolver->faultReferences+1;
202 }
203
204 + (id)autorelease {
205   return self;
206 }
207 - (id)autorelease {
208   [NSAutoreleasePool addObject:self];
209   return self;
210 }
211
212 - (NSZone *)zone {
213   return NSZoneFromPointer(self);
214 }
215
216 - (BOOL)isProxy {
217   return NO;
218 }
219 - (BOOL)isGarbageCollectable {
220   return NO;
221 }
222
223 + (void)dealloc {
224   NSLog(@"WARNING: tried to deallocate EOFault class ..");
225 }
226 - (void)dealloc {
227   [self->isa clearFault:self];
228   [self dealloc];
229 }
230
231 /* descriptions */
232
233 - (NSString *)description {
234   return [self->faultResolver descriptionForObject:self];
235 }
236 - (NSString *)descriptionWithIndent:(unsigned)level {
237   return [self description];
238 }
239 - (NSString *)stringRepresentation {
240   return [self description];
241 }
242 - (NSString *)eoShallowDescription {
243   return [self description];
244 }
245
246 - (NSString *)propertyListStringWithLocale:(NSDictionary *)_locale
247   indent:(int)_i
248 {
249   return [self description];
250 }
251
252 /* Forwarding stuff */
253
254 + (void)initialize {
255   /*
256     Must be here as initialize is called for each root class
257     without asking if it responds to it !
258   */
259 }
260
261 static inline void _resolveFault(EOFault *self) {
262   EOFaultHandler *handler;
263   
264   /* If in class */
265   if (!object_is_instance(self)) {
266     [NSException raise:@"NSInvalidArgumentException"
267                  format:@"used EOFault class in forward"];
268   }
269
270   handler = self->faultResolver;
271   [handler completeInitializationOfObject:self];
272   
273   if (self->isa == [EOFault class]) {
274     [NSException raise:@"NSInvalidArgumentException" 
275                  format:
276                    @"fault error: %@ was not cleared during fault fetching",
277                    [handler descriptionForObject:self]];
278   }
279 }
280
281 + (id)self {
282   _resolveFault(self);
283   return self;
284 }
285
286 #if 0
287
288 - (void)setObject:(id)object forKey:(id)key {
289   _resolveFault(self);
290   [self setObject:object forKey:key];
291 }
292 - (id)objectForKey:(id)key {
293   _resolveFault(self);
294   return [self objectForKey:key];
295 }
296 - (void)removeObjectForKey:(id)key {
297   _resolveFault(self);
298   [self removeObjectForKey:key];
299 }
300
301 - (void)takeValuesFromDictionary:(NSDictionary *)dictionary {
302   _resolveFault(self);
303   [self takeValuesFromDictionary:dictionary];
304 }
305 - (NSDictionary *)valuesForKeys:(NSArray *)keys {
306   _resolveFault(self);
307   return [self valuesForKeys:keys];
308 }
309 - (BOOL)takeValue:(id)object forKey:(id)key {
310   _resolveFault(self);
311   return [self takeValue:object forKey:key];
312 }
313 - (id)valueForKey:(id)key {
314   _resolveFault(self);
315   return [self valueForKey:key];
316 }
317
318 - (BOOL)kvcIsPreferredInKeyPath {
319   _resolveFault(self);
320   return YES;
321 }
322
323 #endif /* 0 */
324
325 - (NSMethodSignature *)methodSignatureForSelector:(SEL)_sel {
326   return [self->faultResolver methodSignatureForSelector:_sel forFault:self];
327 }
328
329 - (void)forwardInvocation:(NSInvocation *)_invocation {
330   if ([self->faultResolver shouldPerformInvocation:_invocation]) {
331     _resolveFault(self);
332     [_invocation invoke];
333   }
334 }
335
336 @end /* EOFault */
337
338 @implementation EOFault(RealForwarding)
339
340 #if NeXT_Foundation_LIBRARY
341
342 - (void)forwardInvocation:(NSInvocation *)_inv {
343   _resolveFault(self);
344
345   [_inv setTarget:self];
346   [_inv invoke];
347 }
348
349 #else
350
351 - (retval_t)forward:(SEL)sel:(arglist_t)args {
352 #if 1 && !defined(__APPLE__)
353   Method_t forward;
354
355   forward = class_get_instance_method(objc_lookup_class("NSObject"), _cmd);
356   return ((retval_t (*)(id, SEL, SEL, arglist_t))forward->method_imp)
357     (self, _cmd, sel, args);
358 #else
359   struct objc_method *m;
360
361   _resolveFault(self);
362     
363   if ((m = class_get_instance_method(self->isa, sel)) == NULL) {
364     NSString *r;
365
366     r = [NSString stringWithFormat:
367                     @"fault error: resolved fault does not responds to selector %s",
368                     sel_get_name(sel)];
369     [NSException raise:@"NSInvalidArgumentException" reason:r userInfo:nil];
370   }
371   return objc_msg_sendv(self, sel, args);
372 #endif
373 }
374 #endif
375
376 @end /* EOFault(RealForwarding) */