package er.ajax.mootools;
import java.util.NoSuchElementException;
import com.webobjects.appserver.WOActionResults;
import com.webobjects.appserver.WOContext;
import com.webobjects.appserver.WORequest;
import com.webobjects.appserver.WOResponse;
import com.webobjects.eocontrol.EOKeyValueQualifier;
import com.webobjects.eocontrol.EOQualifier;
import com.webobjects.foundation.NSArray;
import com.webobjects.foundation.NSDictionary;
import com.webobjects.foundation.NSKeyValueCodingAdditions;
import com.webobjects.foundation.NSMutableArray;
import com.webobjects.foundation.NSMutableDictionary;
import com.webobjects.foundation.NSRange;
import er.ajax.AjaxComponent;
import er.ajax.AjaxOption;
import er.ajax.AjaxUtils;
public class MTAjaxSortableList extends AjaxComponent {
private static final long serialVersionUID = 1L;
private String _id;
private String _actionUrl;
private String _sortOrderKeyName;
private String _var;
public MTAjaxSortableList(WOContext context) {
super(context);
}
@Override
public void appendToResponse(WOResponse response, WOContext context) {
_actionUrl = AjaxUtils.ajaxComponentActionUrl(context);
_id = hasBinding("id") ? (String) valueForBinding("id") : safeElementID();
_var = hasBinding("var") ? (String) valueForBinding("var") : safeElementID();
_sortOrderKeyName = safeElementID();
super.appendToResponse(response, context);
}
public String listElementName() {
return valueForStringBinding("listElementName", "ul");
}
public String listItemElementName() {
return valueForStringBinding("listItemElementName", "li");
}
public String listItemID(String itemID) {
String listID = (String) valueForBinding("id");
String listItemIDWithoutIndex = listID + "_" + itemID;
return listItemIDWithoutIndex;
}
public String listItemID() {
Object item = valueForBinding("item");
String listItemIDKeyPath = (String) valueForBinding("listItemIDKeyPath");
String itemID = String.valueOf(NSKeyValueCodingAdditions.Utility.valueForKeyPath(item, listItemIDKeyPath));
String listItemID = listItemID(itemID);
return listItemID;
}
@Override
protected void addRequiredWebResources(WOResponse res) {
MTAjaxUtils.addScriptResourceInHead(context(), res, "MooTools", MTAjaxUtils.MOOTOOLS_CORE_JS);
MTAjaxUtils.addScriptResourceInHead(context(), res, "MooTools", MTAjaxUtils.MOOTOOLS_MORE_JS);
}
@Override
public WOActionResults handleRequest(WORequest request, WOContext context) {
if(!canGetValueForBinding("list")) {
throw new IllegalArgumentException("You must specify a readable 'list'.");
}
if (!canGetValueForBinding("listItemIDKeyPath")) {
throw new IllegalArgumentException("You must specify 'listItemIDKeyPath' if you specify 'list'.");
}
String listItemIDKeyPath = (String) valueForBinding("listItemIDKeyPath");
Object listItemIDArrayObj = request.formValues().objectForKey(_sortOrderKeyName + "[]");
NSArray<String> listItemIDArray;
if (listItemIDArrayObj instanceof NSArray) {
listItemIDArray = (NSArray<String>) listItemIDArrayObj;
}
else if (listItemIDArrayObj instanceof String) {
String listItemIDStr = (String) listItemIDArrayObj;
listItemIDArray = new NSArray(listItemIDStr);
}
else {
throw new IllegalArgumentException("Unknown list item ID array " + listItemIDArrayObj);
}
NSArray list = (NSArray) valueForBinding("list");
boolean mutableList = (list instanceof NSMutableArray);
NSMutableArray reorderedList;
if(mutableList) {
reorderedList = (NSMutableArray) list;
} else {
reorderedList = new NSMutableArray();
}
int startIndex = 0;
if(canGetValueForBinding("startIndex")) {
Number startIndexNumber = (Number) valueForBinding("startIndex");
startIndex = startIndexNumber.intValue();
if(!mutableList) {
for(int i = 0; i < startIndex; i++) {
reorderedList.addObject(list.objectAtIndex(i));
}
}
}
int listItemIDCount = listItemIDArray.count();
for(int listItemIDIndex = 0; listItemIDIndex < listItemIDCount; listItemIDIndex++) {
String itemID = listItemIDArray.objectAtIndex(listItemIDIndex);
NSRange itemPageRange;
if(mutableList) {
itemPageRange = new NSRange(startIndex + listItemIDIndex, listItemIDCount - listItemIDIndex);
} else {
itemPageRange = new NSRange(startIndex, listItemIDCount);
}
NSArray itemPageArray = list.subarrayWithRange(itemPageRange);
EOQualifier itemIDQualifier = new EOKeyValueQualifier(listItemIDKeyPath, EOQualifier.QualifierOperatorEqual, itemID);
NSArray matchingItems = EOQualifier.filteredArrayWithQualifier(itemPageArray, itemIDQualifier);
if(matchingItems.count() == 0) {
throw new NoSuchElementException("There was no item that matched the ID '" + itemID + "' in " + list + ".");
} else if(matchingItems.count() > 1) {
throw new IllegalStateException("There was more than one item that matched the ID '" + itemID + "' in " + list + ".");
}
Object replacingItem = matchingItems.objectAtIndex(0);
if(mutableList) {
int replacedItemIndex = itemPageRange.location();
Object replacedItem = reorderedList.objectAtIndex(replacedItemIndex);
if(replacedItem != replacingItem) {
int replacingItemIndex = replacedItemIndex + itemPageArray.indexOfObject(replacingItem);
reorderedList.replaceObjectAtIndex(replacingItem, replacedItemIndex);
reorderedList.replaceObjectAtIndex(replacedItem, replacingItemIndex);
}
} else {
reorderedList.addObject(replacingItem);
}
if(! mutableList) {
int listCount = list.count();
for(int i = startIndex + reorderedList.count(); i < listCount; i++) {
reorderedList.addObject(list.objectAtIndex(i));
}
setValueForBinding(reorderedList, "list");
}
if(canGetValueForBinding("action")) {
WOActionResults results = (WOActionResults) valueForBinding("action");
if(results != null) {
System.out.println("Not quite sure what to do with non-null results yet ...");
}
}
}
return null;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public NSDictionary createAjaxOptions() {
NSMutableArray ajaxOptionsArray = new NSMutableArray();
ajaxOptionsArray.addObject(new AjaxOption("clone", AjaxOption.BOOLEAN));
ajaxOptionsArray.addObject(new AjaxOption("constrain", AjaxOption.BOOLEAN));
ajaxOptionsArray.addObject(new AjaxOption("handle", AjaxOption.STRING));
ajaxOptionsArray.addObject(new AjaxOption("onComplete", AjaxOption.SCRIPT));
ajaxOptionsArray.addObject(new AjaxOption("onSort", AjaxOption.SCRIPT));
ajaxOptionsArray.addObject(new AjaxOption("onStart", AjaxOption.SCRIPT));
ajaxOptionsArray.addObject(new AjaxOption("opacity", AjaxOption.NUMBER));
ajaxOptionsArray.addObject(new AjaxOption("revert", AjaxOption.STRING));
ajaxOptionsArray.addObject(new AjaxOption("snap", AjaxOption.NUMBER));
NSMutableDictionary options = AjaxOption.createAjaxOptionsDictionary(ajaxOptionsArray, this);
return options;
}
public String onComplete() {
StringBuilder onCompleteBuffer = new StringBuilder();
onCompleteBuffer.append("function(container) {");
onCompleteBuffer.append("var data = ").append(var()).append(".serialize(false, function(element, index) {\n")
.append("return '").append(_sortOrderKeyName).append("[]' + '=' + element.getProperty('id').replace('").append(_sortOrderKeyName).append("_','');}).join('&');");
onCompleteBuffer.append("var ajaxRequest = new Request({url: '").append(_actionUrl).append("'}).send( { method: 'get', data: data } );");
if(canGetValueForBinding("onComplete")) {
String onComplete = (String) valueForBinding("onComplete");
onCompleteBuffer.append(" var parentOnComplete = ")
.append(onComplete).append(';').append("parentOnUpdate(container);");
}
onCompleteBuffer.append('}');
return onCompleteBuffer.toString();
}
@Override
public boolean synchronizesVariablesWithBindings() {
return false;
}
public void setId(String id) {
_id = id;
}
public String getId() {
return _id;
}
/**
* @return the var
*/
public String var() {
return _var;
}
/**
* @param var the var to set
*/
public void setVar(String var) {
_var = var;
}
}