Source code: com/webobjects/woextensions/WOToOneRelationship.java
1 /*
2 * WOToOneRelationship.java
3 * © Copyright 2001 Apple Computer, Inc. All rights reserved.
4 * This a modified version.
5 * Original license: http://www.opensource.apple.com/apsl/
6 */
7
8 package com.webobjects.woextensions;
9
10 import com.webobjects.appserver.*;
11 import com.webobjects.foundation.*;
12 import com.webobjects.eocontrol.*;
13 import com.webobjects.eoaccess.*;
14
15 import java.util.Enumeration;
16
17 public class WOToOneRelationship extends WOComponent {
18 // ** passed-in (required)
19 protected String _sourceEntityName;
20 protected String _relationshipKey;
21 protected Object _sourceObject;
22 // ** passed-in (optional)
23 protected String _destinationDisplayKey;
24 protected EODatabaseDataSource _dataSource;
25 protected String _uiStyle;
26 protected boolean _isMandatory;
27
28 // ** internal
29 protected Object theCurrentItem;
30 protected NSArray _privateList;
31 protected Object _privateSelection;
32
33 public static String _noneString = "- none -";
34
35
36 public WOToOneRelationship(WOContext aContext) {
37 super(aContext);
38 }
39
40 public boolean isStateless() {
41 return true;
42 }
43
44 public String sourceEntityName()
45 {
46 return _sourceEntityName;
47 }
48
49 public void setSourceEntityName(String aValue) {
50 _sourceEntityName = aValue;
51 }
52
53 public String relationshipKey()
54 {
55 return _relationshipKey;
56 }
57
58 public void setRelationshipKey(String aValue) {
59 _relationshipKey = aValue;
60 }
61
62 public Object sourceObject()
63 {
64 return _sourceObject;
65 }
66
67 public void setSourceObject(Object aValue) {
68 _sourceObject = aValue;
69 }
70
71 public String destinationDisplayKey()
72 {
73 return _destinationDisplayKey;
74 }
75
76 public void setDestinationDisplayKey(String aValue) {
77 _destinationDisplayKey = aValue;
78 }
79
80 public EODatabaseDataSource dataSource()
81 {
82 return _dataSource;
83 }
84
85 public void setDataSource(EODatabaseDataSource aValue) {
86 _dataSource = aValue;
87 }
88
89 public String uiStyle()
90 {
91 return _uiStyle;
92 }
93
94 public void setUiStyle(String aValue) {
95 _uiStyle = aValue;
96 }
97
98 protected boolean isMandatory()
99 {
100 return _isMandatory;
101 }
102
103 public void setIsMandatory(Object aValue) {
104 try {
105 _isMandatory = _WOJExtensionsUtil.booleanValue(aValue);
106 } catch (Throwable e) {
107 String error = "WOToOneRelationship (setIsMandatory) - unable to set isMandatory value "+e.getMessage();
108 NSLog.err.appendln(error);
109 }
110 }
111
112 //////////////////////////////////////////////////
113 // The following are used internally/privately
114 //////////////////////////////////////////////////
115 public Object theCurrentItem()
116 {
117 return theCurrentItem;
118 }
119
120 public void setTheCurrentItem(Object aValue) {
121 theCurrentItem = aValue;
122 }
123
124 protected NSArray _privateList()
125 {
126 return _privateList;
127 }
128
129 public void set_privateList(NSArray aValue)
130 {
131 _privateList = aValue;
132 }
133
134 public Object _privateSelection()
135 {
136 return _privateSelection;
137 }
138
139 public void set_privateSelection(Object aValue) {
140 _privateSelection = aValue;
141 }
142
143 protected void _invalidateCaches() {
144 // In order for this to behave like an element, all instance
145 // variables need to be flushed when this component sleeps
146 // so that it will pull via association.
147 setSourceEntityName(null);
148 setRelationshipKey(null);
149 setSourceObject(null);
150 setDataSource(null);
151 setDestinationDisplayKey(null);
152 setUiStyle(null);
153 setIsMandatory(null);
154 setTheCurrentItem(null);
155 set_privateList(null);
156 set_privateSelection(null);
157 }
158
159 public void reset() {
160 _invalidateCaches();
161 }
162
163 ///////////////////////
164 // Internal Accessors
165 ///////////////////////
166 protected Object _localSourceObject()
167 {
168 if (null==sourceObject()) {
169 setSourceObject(valueForBinding("sourceObject"));
170 if (null==sourceObject()) {
171 throw new IllegalStateException("<"+getClass().getName()+" sourceObject binding required. sourceObject value is nil or missing>");
172 }
173 }
174 return sourceObject();
175 }
176
177
178 protected boolean _localIsMandatory() {
179 if (!isMandatory()) {
180 Object aValue = valueForBinding("isMandatory");
181 setIsMandatory(aValue);
182 }
183 return isMandatory();
184 }
185
186 protected String _localSourceEntityName() {
187 if (null==sourceEntityName()) {
188 setSourceEntityName((String) _WOJExtensionsUtil.valueForBindingOrNull("sourceEntityName",this));
189 if (null==sourceEntityName()) {
190 throw new IllegalStateException("<"+getClass().getName()+" sourceEntityName binding required. sourceEntityName value is nil or missing>");
191 }
192 }
193 return sourceEntityName();
194 }
195
196 protected String _localRelationshipKey()
197 {
198 if (null==relationshipKey()) {
199 setRelationshipKey((String) _WOJExtensionsUtil.valueForBindingOrNull("relationshipKey",this));
200 if (null==relationshipKey()) {
201 throw new IllegalStateException("<"+getClass().getName()+" relationshipKey binding required. relationshipKey value is nil or missing>");
202 }
203 }
204 return relationshipKey();
205 }
206
207 protected String _localDestinationDisplayKey() {
208 String destinationDisplayKey = destinationDisplayKey();
209 if (null==destinationDisplayKey) {
210 setDestinationDisplayKey( (String) _WOJExtensionsUtil.valueForBindingOrNull("destinationDisplayKey",this));
211 if (null==destinationDisplayKey()) {
212 setDestinationDisplayKey("userPresentableDescription");
213 }
214 return destinationDisplayKey();
215 } else
216 return destinationDisplayKey;
217 }
218
219
220 public EOEntity entityWithEntityAndKeyPath(EOEntity entity, String keyPath) {
221 NSArray keys= NSArray.componentsSeparatedByString(keyPath, ".");
222 Enumeration keysEnumerator = keys.objectEnumerator();
223 String key=null;
224 EOEntity result=entity;
225 while (keysEnumerator.hasMoreElements()) {
226 key = (String)keysEnumerator.nextElement();
227 result = result.relationshipNamed(key).destinationEntity();
228 }
229 return result;
230 }
231
232 protected EODataSource _localDataSource() {
233
234 if (null==dataSource()) {
235 setDataSource((EODatabaseDataSource) _WOJExtensionsUtil.valueForBindingOrNull("dataSource",this));
236 if (null==dataSource()) {
237 String anEntityName = _localSourceEntityName();
238 EOModelGroup aModelGroup = EOModelGroup.defaultGroup();
239 EOEntity anEntity = aModelGroup.entityNamed(anEntityName);
240
241 if (anEntity == null) {
242 throw new IllegalStateException("<" + getClass().getName() + " could not find entity named " + anEntityName + ">");
243 }
244
245 EOEntity destinationEntity = entityWithEntityAndKeyPath(anEntity, _localRelationshipKey());
246 Object _source = _localSourceObject();
247 EOEditingContext anEditingContext = null;
248 if (_source instanceof EOEnterpriseObject) {
249 anEditingContext = ((EOEnterpriseObject)_source).editingContext();
250 }
251 if (anEditingContext == null) {
252 anEditingContext = session().defaultEditingContext() ;
253 }
254 EODatabaseDataSource aDatabaseDataSource = new EODatabaseDataSource(anEditingContext, destinationEntity.name());
255 setDataSource(aDatabaseDataSource);
256 }
257 }
258
259 return dataSource();
260 }
261
262 protected Object _localUiStyle() {
263 if (null== uiStyle()) {
264 setUiStyle((String) _WOJExtensionsUtil.valueForBindingOrNull("uiStyle",this));
265 // if still no value let's determine one
266 if (null==uiStyle()) {
267 int aSize = theList().count();
268 if (aSize < 5) {
269 setUiStyle("radio");
270 }
271 if ((aSize >= 5) && (aSize < 20)) {
272 setUiStyle("popup");
273 }
274 if (aSize >= 20) {
275 setUiStyle("browser");
276 }
277 }
278 }
279 return uiStyle();
280 }
281
282 /*
283 * -updateSourceObject does the real work here updating
284 * the relationship (or setting the keys for a query).
285 */
286
287 public void updateSourceObject(Object anEO) {
288 String masterKey = _localRelationshipKey();
289 Object aSourceObject = _localSourceObject();
290 boolean isDictionary = (aSourceObject instanceof NSMutableDictionary);
291 NSMutableDictionary _dictionary = (isDictionary) ? (NSMutableDictionary)aSourceObject : null;
292 EOEnterpriseObject _eo = !(isDictionary) ? (EOEnterpriseObject)aSourceObject : null;
293
294 if (anEO != null) {
295
296 if (isDictionary) {
297 _dictionary.setObjectForKey(anEO, masterKey);
298 }
299 else if (_eo.valueForKey(masterKey) != anEO) {
300 _eo.addObjectToBothSidesOfRelationshipWithKey((EOEnterpriseObject) anEO, masterKey);
301 }
302
303 }
304 else { // remove
305
306 if (isDictionary) {
307 _dictionary.removeObjectForKey(masterKey);
308 }
309 else if (_eo.valueForKey(masterKey) != null) {
310 _eo.removeObjectFromBothSidesOfRelationshipWithKey((EOEnterpriseObject) _eo.valueForKey(masterKey), masterKey);
311 }
312
313 }
314
315 }
316
317 ////////////////////////////////////
318 // Accessed through HTML and WOD
319 ////////////////////////////////////
320
321 /*
322 * -selection and -setSelection: are called by WOF when
323 * syncing up the contents of this component. These are
324 * accessed only through the declarations.
325 */
326
327 public void setSelection(Object anEO) {
328 Object aValue = null;
329
330 // deal with array when ui is browser
331 if ((anEO!=null) && (anEO instanceof NSArray)) {
332 NSArray anEOArray = (NSArray)anEO;
333 if (anEOArray.count() == 0) {
334 anEO = null;
335 } else {
336 anEO = anEOArray.objectAtIndex(0);
337 }
338 }
339
340 if (anEO==_noneString) {
341 aValue = null;
342 } else {
343 aValue = anEO;
344 }
345
346 set_privateSelection(aValue);
347 // this set method needs to trigger the setSourceObject:
348 // it's the only way our value will get back into the parent
349 updateSourceObject(aValue);
350 }
351
352 public Object selection() {
353 if (_privateSelection()==null) {
354 set_privateSelection( NSKeyValueCoding.Utility.valueForKey(_localSourceObject(), _localRelationshipKey()));
355 }
356 // deal with isMandatory
357 if ((_privateSelection()==null) && !_localIsMandatory()) {
358 setSelection(_noneString);
359 }
360 return _privateSelection();
361 }
362
363 public NSArray theList() {
364 NSMutableArray aSortedArray;
365 NSArray anUnsortedArray;
366 if (_privateList()==null) {
367 EODataSource aDataSource = _localDataSource();
368 anUnsortedArray = aDataSource.fetchObjects();
369 // 81398 sort contents
370 aSortedArray = new NSMutableArray(anUnsortedArray);
371 try {
372 _WOJExtensionsUtil._sortEOsUsingSingleKey(aSortedArray, _localDestinationDisplayKey());
373 } catch (NSComparator.ComparisonException e) {
374 throw NSForwardException._runtimeExceptionForThrowable(e);
375 }
376
377 if (!_localIsMandatory()) {
378 aSortedArray.insertObjectAtIndex(_noneString, 0);
379 }
380 set_privateList(aSortedArray);
381 }
382 return _privateList();
383 }
384
385 public void setTheList(NSArray aValue) {
386 }
387
388 public Object theCurrentValue() {
389 // handle the case where it's the - none - string
390 if (theCurrentItem==_noneString) {
391 return theCurrentItem;
392 }
393 return NSKeyValueCoding.Utility.valueForKey(theCurrentItem , _localDestinationDisplayKey());
394
395 }
396
397 public boolean isRadio() {
398 if (_localUiStyle().equals("radio")) {
399 return true;
400 }
401 return false;
402 }
403
404 public boolean isPopup() {
405 if (_localUiStyle().equals("popup")) {
406 return true;
407 }
408 return false;
409 }
410
411 public boolean isBrowser() {
412 if (_localUiStyle().equals("browser")) {
413 return true;
414 }
415 return false;
416 }
417 }