1 
2 /* Interface for NSKeyValueCoding for GNUStep
3    Copyright (C) 2000 Free Software Foundation, Inc.
4 
5    Written by:  Richard Frith-Macdonald <rfm@gnu.org>
6    Date:	2000
7 
8    This file is part of the GNUstep Base Library.
9 
10    This library is free software; you can redistribute it and/or
11    modify it under the terms of the GNU Lesser General Public
12    License as published by the Free Software Foundation; either
13    version 2 of the License, or (at your option) any later version.
14 
15    This library is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    Lesser General Public License for more details.
19 
20    You should have received a copy of the GNU Lesser General Public
21    License along with this library; if not, write to the Free
22    Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23    Boston, MA 02110 USA.
24    */
25 
26 #ifndef __NSKeyValueCoding_h_GNUSTEP_BASE_INCLUDE
27 #define __NSKeyValueCoding_h_GNUSTEP_BASE_INCLUDE
28 #import	<GNUstepBase/GSVersionMacros.h>
29 
30 #if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
31 
32 #import	<Foundation/NSObject.h>
33 
34 #if	defined(__cplusplus)
35 extern "C" {
36 #endif
37 
38 @class NSArray;
39 @class NSMutableArray;
40 @class NSSet;
41 @class NSMutableSet;
42 @class NSDictionary;
43 @class NSError;
44 @class NSString;
45 
46 /** An exception for an unknown key in [NSObject(NSKeyValueCoding)]. */
47 GS_EXPORT NSString* const NSUndefinedKeyException;
48 
49 /**
50  * <p>This describes an informal protocol for <em>key-value coding</em>, a
51  * mechanism whereby the fields of an object may be accessed and set using
52  * generic methods in conjunction with string keys rather than field-specific
53  * methods.  Key-based access loses compile-time validity checking, but can be
54  * convenient in certain kinds of situations.</p>
55  *
56  * <p>The basic methods are implemented as a category of the [NSObject] class,
57  * but other classes override those default implementations to perform more
58  * specific operations.</p>
59  */
60 @interface NSObject (NSKeyValueCoding)
61 
62 /**
63  * Controls whether the NSKeyValueCoding methods may attempt to
64  * access instance variables directly.
65  * NSObject's implementation returns YES.
66  */
67 + (BOOL) accessInstanceVariablesDirectly;
68 
69 /**
70  * Controls whether -storedValueForKey: and -takeStoredValue:forKey: may use
71  * the stored accessor mechanism.  If not the calls get redirected to
72  * -valueForKey: and -takeValue:forKey: effectively changing the search order
73  * of private/public accessor methods and instance variables.
74  * NSObject's implementation returns YES.
75  */
76 + (BOOL) useStoredAccessor;
77 
78 /**
79  * Returns a dictionary built from values obtained for the specified keys.<br />
80  * By default this is derived by calling -valueForKey: for each key.
81  * Any nil values obtained are represented by an [NSNull] instance.
82  */
83 - (NSDictionary*) dictionaryWithValuesForKeys: (NSArray*)keys;
84 
85 /**
86  * Deprecated ... use -valueForUndefinedKey: instead.
87  */
88 - (id) handleQueryWithUnboundKey: (NSString*)aKey;
89 
90 /**
91  * Deprecated, use -setValue:forUndefinedKey: instead.
92  */
93 - (void) handleTakeValue: (id)anObject forUnboundKey: (NSString*)aKey;
94 
95 /**
96  * Returns a mutable array value for a given key. This method:
97  * <list>
98  *  <item>Searches the receiver for methods matching the patterns
99  *   insertObject:in&lt;Key&gt;AtIndex: and
100  *   removeObjectFrom&lt;Key&gt;AtIndex:. If both
101  *   methods are found, each message sent to the proxy array will result in the
102  *   invocation of one or more of these methods. If
103  *   replaceObjectIn&lt;Key&gt;AtIndex:withObject:
104  *   is also found in the receiver it
105  *   will be used when appropriate for better performance.</item>
106  *  <item>If the set of methods is not found, searches the receiver for a the
107  *   method set&lt;Key&gt;:. Each message sent to the proxy array will result in
108  *   the invocation of set&lt;Key&gt;:</item>
109  *  <item>If the previous do not match, and accessInstanceVariablesDirectly
110  *   returns YES, searches for an instance variable matching _&lt;key&gt; or
111  *   &lt;key&gt; (in that order). If the instance variable is found,
112  *   messages sent
113  *   to the proxy object will be forwarded to the instance variable.</item>
114  *  <item>If none of the previous are found, raises an NSUndefinedKeyException
115  *  </item>
116  * </list>
117  */
118 - (NSMutableArray*) mutableArrayValueForKey: (NSString*)aKey;
119 
120 /**
121  * Returns a mutable array value for the given key path.
122  */
123 - (NSMutableArray*) mutableArrayValueForKeyPath: (NSString*)aKey;
124 
125 /**
126  * Returns a mutable set value for a given key. This method:
127  * <list>
128  *  <item>Searches the receiver for methods matching the patterns
129  *   add&lt;Key&gt;Object:, remove&lt;Key&gt;Object:,
130  *   add&lt;Key&gt;:, and remove&lt;Key&gt;:, which
131  *   correspond to the NSMutableSet methods addObject:, removeObject:,
132  *   unionSet:, and minusSet:, respectively. If at least one addition
133  *   and one removal method are found, each message sent to the proxy set
134  *   will result in the invocation of one or more of these methods. If
135  *   intersect&lt;Key&gt;: or set&lt;Key&gt;:
136  *   is also found in the receiver, the method(s)
137  *   will be used when appropriate for better performance.</item>
138  *  <item>If the set of methods is not found, searches the receiver for a the
139  *   method set&lt;Key&gt;:. Each message sent to the proxy set will result in
140  *   the invocation of set&lt;Key&gt;:</item>
141  *  <item>If the previous do not match, and accessInstanceVariablesDirectly
142  *   returns YES, searches for an instance variable matching _&lt;key&gt; or
143  *   &lt;key&gt; (in that order). If the instance variable is found,
144  *   messages sent
145  *   to the proxy object will be forwarded to the instance variable.</item>
146  *  <item>If none of the previous are found, raises an NSUndefinedKeyException
147  *  </item>
148  * </list>
149  */
150 - (NSMutableSet*) mutableSetValueForKey: (NSString *)aKey;
151 
152 /**
153  * Returns a mutable set value for the given key path.
154  */
155 - (NSMutableSet*) mutableSetValueForKeyPath: (NSString*)aKey;
156 
157 /**
158  * This method is invoked by the NSKeyValueCoding mechanism when an attempt
159  * is made to set an null value for a scalar attribute.  This implementation
160  * raises an NSInvalidArgument exception.  Subclasses my override this method
161  * to do custom handling. (E.g. setting the value to the equivalent of 0.)
162  */
163 - (void) setNilValueForKey: (NSString*)aKey;
164 
165 /**
166  * Sets the value if the attribute associated with the key in the receiver.
167  * The object is converted to a scalar attribute where applicable (and
168  * -setNilValueForKey: is called if a nil value is supplied).
169  * Tries to use a standard accessor of the form setKey: where 'Key' is the
170  * supplied argument with the first letter converted to uppercase.<br />
171  * If the receiver's class allows +accessInstanceVariablesDirectly
172  * it continues with instance variables:
173  * <list>
174  *  <item>_key</item>
175  *  <item>_isKey</item>
176  *  <item>key</item>
177  *  <item>isKey</item>
178  * </list>
179  * Invokes -setValue:forUndefinedKey: if no accessor mechanism can be found
180  * and raises NSInvalidArgumentException if the accessor method doesn't take
181  * exactly one argument or the type is unsupported (e.g. structs).
182  * If the receiver expects a scalar value and the value supplied
183  * is the NSNull instance or nil, this method invokes
184  * -setNilValueForKey: .
185  */
186 - (void) setValue: (id)anObject forKey: (NSString*)aKey;
187 
188 /**
189  * Retrieves the object returned by invoking -valueForKey:
190  * on the receiver with the first key component supplied by the key path.
191  * Then invokes -setValue:forKeyPath: recursively on the
192  * returned object with rest of the key path.
193  * The key components are delimited by '.'.
194  * If the key path doesn't contain any '.', this method simply
195  * invokes -setValue:forKey:.
196  */
197 - (void) setValue: (id)anObject forKeyPath: (NSString*)aKey;
198 
199 /**
200  * Invoked when -setValue:forKey: / -takeStoredValue:forKey: are called with
201  * a key which can't be associated with an accessor method or instance
202  * variable.  Subclasses may override this method to add custom handling.
203  * NSObject raises an NSUndefinedKeyException, with a userInfo dictionary
204  * containing NSTargetObjectUserInfoKey with the receiver an
205  * NSUnknownUserInfoKey with the supplied key entries.<br />
206  * Called when the key passed to -setValue:forKey: cannot be used.
207  */
208 - (void) setValue: (id)anObject forUndefinedKey: (NSString*)aKey;
209 
210 /**
211  * Uses -setValue:forKey: to place the values from aDictionary in the
212  * receiver.
213  */
214 - (void) setValuesForKeysWithDictionary: (NSDictionary*)aDictionary;
215 
216 /**
217  * Returns the value associated with the supplied key as an object.
218  * Scalar attributes are converted to corresponding objects.
219  * Uses private accessors in favor of the public ones, if the receiver's
220  * class allows +useStoredAccessor.  Otherwise this method invokes
221  * -valueForKey:.
222  * The search order is:<br/>
223  * Private accessor methods:
224  * <list>
225  *  <item>_getKey</item>
226  *  <item>_key</item>
227  * </list>
228  * If the receiver's class allows +accessInstanceVariablesDirectly
229  * it continues with instance variables:
230  * <list>
231  *  <item>_key</item>
232  *  <item>key</item>
233  * </list>
234  * Public accessor methods:
235  * <list>
236  *  <item>getKey</item>
237  *  <item>key</item>
238  * </list>
239  * Invokes -handleTakeValue:forUnboundKey: if no accessor mechanism can be
240  * found and raises NSInvalidArgumentException if the accessor method takes
241  * takes any arguments or the type is unsupported (e.g. structs).
242  */
243 - (id) storedValueForKey: (NSString*)aKey;
244 
245 /**
246  * Sets the value associated with the supplied in the receiver.
247  * The object is converted to the scalar attribute where applicable.
248  * Uses the private accessors in favor of the public ones, if the
249  * receiver's class allows +useStoredAccessor .
250  * Otherwise this method invokes -takeValue:forKey: .
251  * The search order is:<br/>
252  * Private accessor methods:
253  * <list>
254  *  <item>_setKey:</item>
255  * </list>
256  * If the receiver's class allows accessInstanceVariablesDirectly
257  * it continues with instance variables:
258  * <list>
259  *  <item>_key</item>
260  *  <item>key</item>
261  * </list>
262  * Public accessor methods:
263  * <list>
264  *  <item>setKey:</item>
265  * </list>
266  * Invokes -handleTakeValue:forUnboundKey:
267  * if no accessor mechanism can be found
268  * and raises NSInvalidArgumentException if the accessor method doesn't take
269  * exactly one argument or the type is unsupported (e.g. structs).
270  * If the receiver expects a scalar value and the value supplied
271  * is the NSNull instance or nil, this method invokes
272  * -unableToSetNilForKey: .
273  */
274 - (void) takeStoredValue: (id)anObject forKey: (NSString*)aKey;
275 
276 /**
277  * Iterates over the dictionary invoking -takeStoredValue:forKey:
278  * on the receiver for each key-value pair, converting NSNull to nil.
279  */
280 - (void) takeStoredValuesFromDictionary: (NSDictionary*)aDictionary;
281 
282 /**
283  * Sets the value if the attribute associated with the key in the receiver.
284  * The object is converted to a scalar attribute where applicable.
285  * Uses the public accessors in favor of the private ones.
286  * The search order is:<br/>
287  * Accessor methods:
288  * <list>
289  *  <item>setKey:</item>
290  *  <item>_setKey:</item>
291  * </list>
292  * If the receiver's class allows +accessInstanceVariablesDirectly
293  * it continues with instance variables:
294  * <list>
295  *  <item>key</item>
296  *  <item>_key</item>
297  * </list>
298  * Invokes -handleTakeValue:forUnboundKey:
299  * if no accessor mechanism can be found
300  * and raises NSInvalidArgumentException if the accessor method doesn't take
301  * exactly one argument or the type is unsupported (e.g. structs).
302  * If the receiver expects a scalar value and the value supplied
303  * is the NSNull instance or nil, this method invokes
304  * -unableToSetNilForKey: .<br />
305  * Deprecated ... use -setValue:forKey: instead.
306  */
307 - (void) takeValue: (id)anObject forKey: (NSString*)aKey;
308 
309 /**
310  * Retrieves the object returned by invoking -valueForKey:
311  * on the receiver with the first key component supplied by the key path.
312  * Then invokes -takeValue:forKeyPath: recursively on the
313  * returned object with rest of the key path.
314  * The key components are delimited by '.'.
315  * If the key path doesn't contain any '.', this method simply
316  * invokes -takeValue:forKey:.<br />
317  * Deprecated ... use -setValue:forKeyPath: instead.
318  */
319 - (void) takeValue: (id)anObject forKeyPath: (NSString*)aKey;
320 
321 /**
322  * Iterates over the dictionary invoking -takeValue:forKey:
323  * on the receiver for each key-value pair, converting NSNull to nil.<br />
324  * Deprecated ... use -setValuesForKeysWithDictionary: instead.
325  */
326 - (void) takeValuesFromDictionary: (NSDictionary*)aDictionary;
327 
328 /**
329  * Deprecated ... use -setNilValueForKey: instead.
330  */
331 - (void) unableToSetNilForKey: (NSString*)aKey;
332 
333 
334 /**
335  * Returns a boolean indicating whether the object pointed to by aValue
336  * is valid for setting as an attribute of the receiver using the name
337  * aKey.  On success (YES response) it may return a new value to be used
338  * in aValue.  On failure (NO response) it may return an error in anError.<br />
339  * The method works by calling a method of the receiver whose name is of
340  * the form validateKey:error: if the receiver has implemented such a
341  * method, otherwise it simply returns YES.
342  */
343 - (BOOL) validateValue: (id*)aValue
344 		forKey: (NSString*)aKey
345 		 error: (out NSError**)anError;
346 
347 /**
348  * Returns the result of calling -validateValue:forKey:error: on the receiver
349  * using aPath to determine the key value in the same manner as the
350  * -valueForKeyPath: method.
351  */
352 - (BOOL) validateValue: (id*)aValue
353 	    forKeyPath: (NSString*)aKey
354 		 error: (out NSError**)anError;
355 
356 /**
357  * Returns the value associated with the supplied key as an object.
358  * Scalar attributes are converted to corresponding objects.<br />
359  * The search order is:<br/>
360  * Accessor methods:
361  * <list>
362  *  <item>getKey</item>
363  *  <item>key</item>
364  * </list>
365  * If the receiver's class allows +accessInstanceVariablesDirectly
366  * it continues with private accessors:
367  * <list>
368  *  <item>_getKey</item>
369  *  <item>_key</item>
370  * </list>
371  * and then instance variables:
372  * <list>
373  *  <item>key</item>
374  *  <item>_key</item>
375  * </list>
376  * Invokes -setValue:forUndefinedKey:
377  * if no accessor mechanism can be found
378  * and raises NSInvalidArgumentException if the accessor method takes
379  * any arguments or the type is unsupported (e.g. structs).
380  */
381 - (id) valueForKey: (NSString*)aKey;
382 
383 /**
384  * Returns the object returned by invoking -valueForKeyPath:
385  * recursively on the object returned by invoking -valueForKey:
386  * on the receiver with the first key component supplied by the key path.
387  * The key components are delimited by '.'.
388  * If the key path doesn't contain any '.', this method simply
389  * invokes -valueForKey: .
390  */
391 - (id) valueForKeyPath: (NSString*)aKey;
392 
393 /**
394  * Invoked when -valueForKey: / -storedValueForKey: are called with a key,
395  * which can't be associated with an accessor method or instance variable.
396  * Subclasses may override this method to add custom handling.  NSObject
397  * raises an NSUndefinedKeyException, with a userInfo dictionary containing
398  * NSTargetObjectUserInfoKey with the receiver an NSUnknownUserInfoKey with
399  * the supplied key entries.<br />
400  */
401 - (id) valueForUndefinedKey: (NSString*)aKey;
402 
403 /**
404  * Iterates over the array sending the receiver -valueForKey:
405  * for each object in the array and inserting the result in a dictionary.
406  * All nil values returned by -valueForKey: are replaced by the
407  * NSNull instance in the dictionary.
408  */
409 - (NSDictionary*) valuesForKeys: (NSArray*)keys;
410 
411 @end
412 
413 #if	defined(__cplusplus)
414 }
415 #endif
416 
417 #endif	/* GS_API_MACOSX */
418 
419 #endif
420 
421