]> err.no Git - sope/blob - sope-appserver/NGObjWeb/SoObjects/SoClass.m
fixed OGo bug #888
[sope] / sope-appserver / NGObjWeb / SoObjects / SoClass.m
1 /*
2   Copyright (C) 2002-2004 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 // $Id$
22
23 #include "SoClass.h"
24 #include "SoClassSecurityInfo.h"
25 #include "common.h"
26
27 #if APPLE_RUNTIME || NeXT_RUNTIME
28 @interface NSObject(Miss)
29 - (void)subclassResponsibility:(SEL)cmd;
30 @end
31 #endif
32
33 @implementation SoClass
34
35 static BOOL debugOn = NO;
36
37 - (id)initWithSoSuperClass:(SoClass *)_soClass {
38   if ((self = [super init])) {
39     self->soSuperClass = [_soClass retain];
40     self->slots        = [[NSMutableDictionary alloc] init];
41   }
42   return self;
43 }
44 - (id)init {
45   return [self initWithSoSuperClass:nil];
46 }
47
48 - (void)dealloc {
49   [self->security     release];
50   [self->slots        release];
51   [self->soSuperClass release];
52   [super dealloc];
53 }
54
55 /* hierachy */
56
57 - (SoClass *)soSuperClass {
58   return self->soSuperClass;
59 }
60
61 /* keys (traverse hierarchy) */
62
63 - (BOOL)hasKey:(NSString *)_key inContext:(id)_ctx {
64   if ([self valueForSlot:_key] != nil)
65     return YES;
66   
67   return [self->soSuperClass hasKey:_key inContext:_ctx];
68 }
69
70 - (id)lookupKey:(NSString *)_key inContext:(id)_ctx {
71   id value;
72   
73   if ((value = [self valueForSlot:_key]))
74     return value;
75   
76   return [self->soSuperClass lookupKey:_key inContext:_ctx];
77 }
78
79 - (NSArray *)allKeys {
80   SoClass *soClass;
81   NSMutableSet *keys;
82   
83   keys = [NSMutableSet setWithCapacity:64];
84   for (soClass = self; soClass != nil; soClass = [soClass soSuperClass])
85     [keys addObjectsFromArray:[soClass slotNames]];
86   return [keys allObjects];
87 }
88
89 /* slots (only works on the exact class) */
90
91 - (void)setValue:(id)_value forSlot:(NSString *)_key {
92   if (debugOn)
93     [self logWithFormat:@"set value for slot '%@': %@", _key, _value];
94
95   if ([_key length] == 0) {
96     [self logWithFormat:@"attempt to set value for invalid slot '%@'", _key];
97     return;
98   }
99   [self->slots setObject:(_value ? _value : [NSNull null]) forKey:_key];
100 }
101 - (id)valueForSlot:(NSString *)_key {
102   id value;
103   
104   value = [self->slots objectForKey:_key];
105   if (debugOn)
106     [self logWithFormat:@"queried value for slot '%@': %@", _key, value];
107   return value;
108 }
109 - (NSArray *)slotNames {
110   return self->slots ?  [self->slots allKeys] : [NSArray array];
111 }
112
113 /* security */
114
115 - (SoClassSecurityInfo *)soClassSecurityInfo {
116   if (self->security == nil)
117     self->security = [[SoClassSecurityInfo alloc] initWithSoClass:self];
118   return self->security;
119 }
120
121 - (NSException *)validateKey:(NSString *)_key inContext:(id)_ctx {
122   /* 
123      nil means: access fully granted 
124      
125      IMPORTANT: to properly support acquisition, this method must return
126      nil on keys which should be acquired (since validateKey is called before
127      the lookup is performed) !
128   */
129   NSString *r;
130   
131   r = [NSString stringWithFormat:@"tried to access private key %@", _key];
132   return [NSException exceptionWithName:@"KeyDenied" reason:r userInfo:nil];
133 }
134
135 /* factory */
136
137 - (id)instantiateObject {
138   [self subclassResponsibility:_cmd];
139   return nil;
140 }
141
142 - (NSClassDescription *)soClassDescription {
143   return nil;
144 }
145
146 - (NSString *)className {
147   return nil;
148 }
149
150 /* NSCopying */
151
152 - (id)copyWithZone:(NSZone *)_zone {
153   /* 
154     This is required on OSX because the class is used as a dict-key in
155     OFSFactoryRegistry.
156   */
157   return [self retain];
158 }
159
160 /* description */
161
162 - (NSString *)description {
163   NSMutableString *ms;
164   
165   ms = [NSMutableString stringWithCapacity:64];
166   [ms appendFormat:@"<0x%08X[%@]:", self,
167         NSStringFromClass((Class)*(void**)self)];
168   
169   if (self->soSuperClass)
170     [ms appendFormat:@" super=0x%08X", self->soSuperClass];
171   else
172     [ms appendString:@" root"];
173   
174   if ([self->slots count] > 0) {
175     [ms appendFormat:@" slots=%@", 
176           [[self->slots allKeys] componentsJoinedByString:@","]];
177   }
178   
179   [ms appendString:@">"];
180   return ms;
181 }
182
183 @end /* SoClass */