2 Copyright (C) 2000-2004 SKYRIX Software AG
4 This file is part of OpenGroupware.org.
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
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.
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
23 #include <NGObjWeb/WOComponent.h>
24 #include <NGObjWeb/WOAssociation.h>
27 @implementation WOComponent(OptimizedSynching)
30 optimized component synchronization. Uses extensive runtime caching.
33 static Class lastEnumClass = Nil;
34 static id (*nextKey)(id, SEL);
35 static Class lastWocDictClass = Nil;
36 static id (*wocObjForKey)(id, SEL, id);
40 #define CHK_ENUM_CACHE \
41 if (lastEnumClass != *(Class *)keys) {\
42 lastEnumClass = *(Class *)keys;\
43 nextKey = (void*)[keys methodForSelector:@selector(nextObject)];\
46 #define CHK_WOCDICT_CACHE \
47 if (lastWocDictClass != *(Class *)self->wocBindings) {\
48 lastWocDictClass = *(Class *)self->wocBindings;\
49 wocObjForKey = (void*)[self->wocBindings methodForSelector:@selector(objectForKey:)];\
54 #define CHK_ENUM_CACHE \
55 if (lastEnumClass != *(Class *)keys) {\
56 lastEnumClass = *(Class *)keys;\
58 method_get_imp(class_get_instance_method(*(Class *)keys, \
59 @selector(nextObject)));\
62 #define CHK_WOCDICT_CACHE \
63 if (lastWocDictClass != *(Class *)self->wocBindings) {\
64 lastWocDictClass = *(Class *)self->wocBindings;\
65 wocObjForKey = (void*)\
66 method_get_imp(class_get_instance_method(*(Class *)self->wocBindings, \
67 @selector(objectForKey:)));\
72 void WOComponent_syncFromParent(WOComponent *self, WOComponent *_parent) {
75 void (*takeValue)(id, SEL, id, NSString *);
77 if ((keys = [self->wocBindings keyEnumerator]) == nil)
83 takeValue = (void *)[self methodForSelector:@selector(takeValue:forKey:)];
85 takeValue = (void*)method_get_imp(class_get_instance_method(self->isa,
86 @selector(takeValue:forKey:)));
89 while ((key = nextKey(keys, @selector(nextObject)))) {
90 static Class lastAssocClass = Nil; // THREAD
91 static id (*valInComp)(id, SEL, WOComponent *);
92 register WOAssociation *binding;
95 binding = wocObjForKey(self->wocBindings, @selector(objectForKey:), key);
97 if (*(Class *)binding != lastAssocClass) {
98 lastAssocClass = *(Class *)binding;
101 [binding methodForSelector:@selector(valueInComponent:)];
104 method_get_imp(class_get_instance_method(*(Class *)binding,
105 @selector(valueInComponent:)));
109 // TODO: this is somewhat inefficient because -valueInComponent: does
110 // value=>object coercion and then takeValue:forKey: does the
111 // reverse coercion. We could improve performance for base values
112 // if we implement takeValue:forKey: on our own and just pass over
113 // the raw value (ie [self setIntA:[assoc intValueComponent:self]])
115 value = valInComp(binding, @selector(valueInComponent:), _parent);
117 // TODO: this is a bit problematic in bool contexts if the input
118 // parameter is a string because ObjC doesn't know about bool
119 // and will evaluate the string as a char value
120 // (this is common if you use const:mykey="YES" in WOx)
121 takeValue(self, @selector(takeValue:forKey:), value, key);
125 void WOComponent_syncToParent(WOComponent *self, WOComponent *_parent) {
128 id (*getValue)(id, SEL, NSString *);
130 if ((keys = [self->wocBindings keyEnumerator]) == nil)
137 getValue = (void *)[self methodForSelector:@selector(valueForKey:)];
139 getValue = (void*)method_get_imp(class_get_instance_method(self->isa,
140 @selector(valueForKey:)));
143 while ((key = nextKey(keys, @selector(nextObject)))) {
144 static Class lastAssocClass = Nil;
145 static BOOL (*isSettable)(id, SEL);
146 static void (*setValInComp)(id, SEL, id, WOComponent *);
147 register WOAssociation *binding;
150 binding = wocObjForKey(self->wocBindings, @selector(objectForKey:), key);
152 if (*(Class *)binding != lastAssocClass) {
153 lastAssocClass = *(Class *)binding;
157 (void*)[binding methodForSelector:@selector(isValueSettable)];
159 (void*)[binding methodForSelector:@selector(setValue:inComponent:)];
162 method_get_imp(class_get_instance_method(*(Class *)binding,
163 @selector(isValueSettable)));
164 setValInComp = (void*)
165 method_get_imp(class_get_instance_method(*(Class *)binding,
166 @selector(setValue:inComponent:)));
170 if (!isSettable(binding, @selector(isValueSettable)))
173 value = getValue(self, @selector(valueForKey:), key);
175 setValInComp(binding, @selector(setValue:inComponent:), value, _parent);
179 @end /* WOComponent(OptimizedSynching) */