package er.extensions.woextensions; import org.apache.commons.lang3.ObjectUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.webobjects.appserver.WOContext; import com.webobjects.eocontrol.EOEnterpriseObject; import com.webobjects.foundation.NSArray; import com.webobjects.foundation.NSKeyValueCoding; import com.webobjects.foundation.NSMutableArray; import er.extensions.components.ERXArrayChooser; import er.extensions.eof.ERXEOControlUtilities; /** * Back port from WO 5 WOExtensions. This component is binding compatible, but not source compatible. * * @author ak */ public class WOToOneRelationship extends ERXArrayChooser { private static final Logger log = LoggerFactory.getLogger(WOToOneRelationship.class); /** * Do I need to update serialVersionUID? * See section 5.6 <cite>Type Changes Affecting Serialization</cite> on page 51 of the * <a href="http://java.sun.com/j2se/1.4/pdf/serial-spec.pdf">Java Object Serialization Spec</a> */ private static final long serialVersionUID = 1L; protected Object _selection; public WOToOneRelationship(WOContext aContext) { super(aContext); } @Override public void reset() { super.reset(); _selection = null; } @Override public void awake() { super.awake(); _selection = null; } public void updateSourceObject(Object value) { String realRelationshipKey = realRelationshipKey(); Object realSourceObject = realSourceObject(); Object currentValue = NSKeyValueCoding.Utility.valueForKey(realSourceObject, realRelationshipKey); if (ObjectUtils.notEqual(value, currentValue)) { if(realSourceObject instanceof EOEnterpriseObject) { EOEnterpriseObject eo = (EOEnterpriseObject)realSourceObject; if(value instanceof EOEnterpriseObject) { eo.addObjectToBothSidesOfRelationshipWithKey((EOEnterpriseObject)value, realRelationshipKey); } else { Object oldValue = eo.valueForKey(realRelationshipKey); if(oldValue instanceof EOEnterpriseObject) { eo.removeObjectFromBothSidesOfRelationshipWithKey((EOEnterpriseObject)oldValue, realRelationshipKey); } else { // handle attributes eo.takeValueForKey(value, realRelationshipKey); } } } else { // handle every other type of object, // we rely on NSMutableDictionary.takeValueForKey(null, someKey) will actually remove the object NSKeyValueCoding.Utility.takeValueForKey(realSourceObject, value, realRelationshipKey); } } } public void setSelection(Object value) { if ((value!=null) && (value instanceof NSArray)) { log.warn("We were passed an array but expected an EO. Compensating by choosing first element"); NSArray array = (NSArray)value; if (array.count() == 0) { value = null; } else { value = array.objectAtIndex(0); } } _selection = value; if (value==NO_SELECTION_STRING) { value = null; } updateSourceObject(value); if (hasBinding("selection") && !(sourceObject() instanceof EOEnterpriseObject)) { setValueForBinding(value, "selection"); } } @Override public NSArray currentValues() { Object current = selection(); return current == null ? NSArray.EmptyArray : new NSArray(current); } public Object selection() { if (_selection == null) { Object object = realSourceObject(); String key = realRelationshipKey(); Object selection = NSKeyValueCoding.Utility.valueForKey(object,key); if (selection != null && selection instanceof EOEnterpriseObject) { EOEnterpriseObject eo = (EOEnterpriseObject)selection; if (eo.editingContext() != editingContext()) { selection = ERXEOControlUtilities.localInstanceOfObject(editingContext(), eo); } } setSelection(selection); } // deal with isMandatory if ((_selection==null) && !isMandatory()) { setSelection(NO_SELECTION_STRING); } //If using a browser, we have to return an array. Be sure we don't stick null into an array. Object selection; if (isBrowser()) { if (_selection == null) { selection = NSArray.EmptyArray; } else { selection = new NSArray(_selection); } } else { selection = _selection; } return selection; } @Override public NSArray theList() { if (_list==null) { _list = super.theList(); if (!isMandatory()) { NSMutableArray array = _list.mutableClone(); array.insertObjectAtIndex(NO_SELECTION_STRING, 0); _list = array; } } return _list; } @Override protected boolean isSingleSelection() { return true; } }