/*
* Copyright (C) NetStruxr, Inc. All rights reserved.
*
* This software is published under the terms of the NetStruxr
* Public Software License version 0.5, a copy of which has been
* included with this distribution in the LICENSE.NPL file. */
package er.extensions.components;
import java.util.Enumeration;
import java.util.Vector;
import com.webobjects.appserver.WOContext;
import com.webobjects.appserver.WOResponse;
import com.webobjects.eocontrol.EOEnterpriseObject;
import com.webobjects.foundation.NSArray;
import com.webobjects.foundation.NSLog;
import com.webobjects.foundation.NSMutableArray;
import com.webobjects.foundation.NSRange;
import com.webobjects.foundation.NSSet;
import er.extensions.foundation.ERXArrayUtilities;
/**
* Works around a webscript bug.
*
* @binding list
* @binding item
* @binding selections
* @binding maxColumns
* @binding goingVertically" defaults="Boolean
* @binding contentCellOtherTagString
* @binding sortKey
* @binding width
* @binding cellAlign
* @binding cellVAlign
* @binding cellpadding
* @binding cellspacing
* @binding cellWidth
* @binding cellClass
* @binding relationshipName
* @binding relationshipOwner
* @binding tableOtherTagString
* @binding id optional ID for element wrapping checkbox matrix
* @binding itemID optional ID for each checkbox element
* @binding disabled
*/
public class ERXCheckboxMatrix extends ERXNonSynchronizingComponent {
/**
* 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;
private static final Integer DEFAULT_PADDING = Integer.valueOf(0);
private static final Integer DEFAULT_SPACING = Integer.valueOf(0);
public ERXCheckboxMatrix(WOContext aContext) {
super(aContext);
}
protected NSArray _selections;
protected Object currentItem;
public int index;
public String wrapperElementID;
@Override
public boolean isStateless() { return true; }
@Override
public void reset() {
invalidateCaches();
}
public String onClick(boolean onOff) {
return "ERXCheckboxMatrix.checkAll(this.form, '" + wrapperElementID + "'," + (onOff ? "true" : "false") + ")";
}
public String selectOnClick() {
return onClick(true);
}
public String deselectOnClick() {
return onClick(false);
}
public Object currentItem() {
setValueForBinding(currentItem, "item");
return currentItem;
}
public void setCurrentItem(Object anItem) {
currentItem = anItem;
setValueForBinding(currentItem, "item");
}
public EOEnterpriseObject relationshipOwner() {
return (EOEnterpriseObject)valueForBinding("relationshipOwner");
}
public String relationshipName() {
Object o = valueForBinding("relationshipName");
return o == null ? null : o.toString();
}
public NSArray selections() {
if (_selections==null) {
_selections = (NSArray)valueForBinding("selections");
}
return _selections;
}
public void setSelections(Vector v) {
NSRange r = new NSRange(0, v.size());
setSelections(new NSArray(v, r, true));
}
@Override
public void takeValueForKey(Object value, String key)
{
try {
super.takeValueForKey(value, key);
} catch (java.lang.IllegalArgumentException e) {
if (value instanceof Vector) {
//convert the vector
NSRange r = new NSRange(0, ((Vector)value).size());
NSMutableArray a = new NSMutableArray((Vector)value, r, true);
super.takeValueForKey(a, key);
NSLog.out.appendln("done");
} else {
throw e;
}
}
}
public void setSelections(NSArray aFormValuesArray) {
if(aFormValuesArray!=null && !disabled()){
// ** This is where we accept the formValues. Kind of weird.
NSMutableArray aSelectionsArray = new NSMutableArray();
Enumeration anIndexEnumerator = aFormValuesArray.objectEnumerator();
NSArray anItemList = maybeSortedList();
int anItemCount = anItemList.count();
while (anIndexEnumerator.hasMoreElements()) {
int anIndex = Integer.parseInt((String)anIndexEnumerator.nextElement());
if (anIndex != -1 && anIndex < anItemCount) {
Object anObject = anItemList.objectAtIndex(anIndex);
aSelectionsArray.addObject(anObject);
} else {
// ** serious problem here. Raise an exception?
}
}
// dt: this can be used with a subset as array for the checkboxes.
if (relationshipName() != null && relationshipName().length() > 0 && relationshipOwner() != null) {
NSSet objectsToRemove = new NSSet(_selections).setBySubtractingSet(new NSSet(aSelectionsArray));
NSSet objectsToAdd = new NSSet(aSelectionsArray).setBySubtractingSet(new NSSet(_selections));
EOEnterpriseObject owner = relationshipOwner();
String relname = relationshipName();
for (Enumeration e = objectsToRemove.objectEnumerator(); e.hasMoreElements();) {
EOEnterpriseObject eo = (EOEnterpriseObject)e.nextElement();
owner.removeObjectFromBothSidesOfRelationshipWithKey(eo, relname);
}
for (Enumeration e = objectsToAdd.objectEnumerator(); e.hasMoreElements();) {
EOEnterpriseObject eo = (EOEnterpriseObject)e.nextElement();
owner.addObjectToBothSidesOfRelationshipWithKey(eo, relname);
}
} else {
setValueForBinding(aSelectionsArray, "selections");
}
_selections = null;
}
}
public String otherTagStringForCheckBox() {
boolean isDisabled = disabled();
boolean isChecked = selections() != null && selections().containsObject(currentItem);
return (isDisabled ? "disabled" : "") + (isDisabled && isChecked? " " : "") + (isChecked ? "checked" : "");
}
private boolean disabled() {
return booleanValueForBinding("disabled", false);
}
public void invalidateCaches() {
_selections=null;
currentItem=null;
index=0;
wrapperElementID=null;
}
@Override
public void sleep() {
invalidateCaches();
}
@Override
public void appendToResponse(WOResponse aResponse, WOContext aContext) {
// ** By setting these to nil, we allow the dictionary to change after the action and before the next cycle of this component (if the component is on a page which is recycled)
invalidateCaches();
super.appendToResponse(aResponse, aContext);
}
public NSArray maybeSortedList() {
if (hasBinding("sortKey")) {
String sortKey = (String)valueForBinding("sortKey");
if(sortKey != null && sortKey.length() > 0) {
NSMutableArray sortedList = new NSMutableArray((NSArray)valueForBinding("list"));
ERXArrayUtilities.sortArrayWithKey(sortedList,sortKey);
return sortedList;
}
}
return (NSArray)valueForBinding("list");
}
public boolean isListEmpty() {
NSArray anItemList = (NSArray)valueForBinding("list");
return (anItemList == null || anItemList.count() == 0);
}
public Object cellpadding() {
Object v = valueForBinding("cellpadding");
if(v != null)
return v;
return DEFAULT_PADDING;
}
public Object cellspacing() {
Object v = valueForBinding("cellspacing");
if(v != null)
return v;
return DEFAULT_SPACING;
}
}