/* ListModelConverter.java
{{IS_NOTE
Purpose:
Description:
History:
Fri Dec 1 16:55:36 2006, Created by Henri Chen
}}IS_NOTE
Copyright (C) 2006 Potix Corporation. All Rights Reserved.
{{IS_RIGHT
}}IS_RIGHT
*/
package org.zkoss.zkplus.databind;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.UiException;
import org.zkoss.zul.GroupsModel;
import org.zkoss.zul.ListModel;
import org.zkoss.zul.ext.Selectable;
/**
* The {@link TypeConverter} implementation for converting collection to ListModel and vice versa. <p/>
* Since zk 6.0.1 This class doesn't handle setMultiple and Selectable, you should use corresponding new converter for different component if it has selection.
* @author Henri Chen
* @deprecated As of release 7.0.0, replace with new ZK binding.
*/
public class ListModelConverter implements TypeConverter, java.io.Serializable {
private static final long serialVersionUID = 200808191433L;
/** Convert a Set, Map, List, Object[], Enum, or other kind of BindingListModel to associated {@link BindingListModel}.
* @param val must be instanceof Set, Map, List, Object[], Enum Class, or other kind of BindingListModel implementation.
*/
@SuppressWarnings("unchecked")
public Object coerceToUi(Object val, Component comp) {
if (val == null) {
val = new ArrayList();
}
BindingListModel wrappedModel = null;
final boolean distinct = isDistinct(comp);
//since 3.1, 20080416, Henri Chen: allow custom arguments.
//model can specify distinct=false in annotation to allow handle same-object-in-multiple-items
if (val instanceof BindingListModel) {
return val;
} else if (val instanceof ListModel) { //Bug 3354086: Model attribute will not accept a ListModel
wrappedModel = new BindingListModelListModel((ListModel) val, distinct);
} else if (val instanceof Set) {
wrappedModel = new BindingListModelSet((Set) val, true);
} else if (val instanceof List) {
wrappedModel = new BindingListModelList((List) val, true, distinct);
} else if (val instanceof Map) {
wrappedModel = new BindingListModelMap((Map) val, true);
} else if (val instanceof Object[]) {
wrappedModel = new BindingListModelArray((Object[]) val, true, distinct);
} else if ((val instanceof Class) && Enum.class.isAssignableFrom((Class) val)) {
wrappedModel = new BindingListModelArray(((Class) val).getEnumConstants(), true);
} else if (val instanceof GroupsModel) { //feature#2866506: Data Binding shall support GroupsModel with Listbox/Grid
wrappedModel = new BindingGroupsListModel((GroupsModel) val);
} else {
throw new UiException(
"Expects java.util.Set, java.util.List, java.util.Map, Object[], Enum Class, GroupsModel, ListModel,or BindingListModel only. "
+ val.getClass());
}
//ZK-927 zkplus databinding1 should auto-wrapping BindingListModelXxx with setMultiple() and Selectable handled
final ListModel compModel = getComponentModel(comp);
if (compModel instanceof Selectable && wrappedModel instanceof Selectable) {
Selectable selectable = ((Selectable) compModel);
((Selectable) wrappedModel).setMultiple(selectable.isMultiple());
for (Object selected : selectable.getSelection()) {
((Selectable) wrappedModel).addToSelection(selected);
}
}
if (!(val instanceof ListModel)) {
//for the data that is not listmodel, provide a chance to post process it. see ListboxListModelConverter
wrappedModel = handleWrappedNonListModel(comp, wrappedModel);
}
return wrappedModel;
}
/**
* Gets the model of the component, the sub-class should override this method
* @since 6.0.1
*/
protected ListModel<?> getComponentModel(Component comp) {
return null;
}
/**
* Handles the wrapped non-list-model, by default it return the original one. <p/>
* The sub-class could override this method if it needs to do some post process on the wrapped model.
* @since 6.0.1
*/
protected BindingListModel<?> handleWrappedNonListModel(Component comp, BindingListModel<?> wrappedModel) {
return wrappedModel;
}
/*package*/ static boolean isDistinct(Component comp) {
Map args = (Map) comp.getAttribute(DataBinder.ARGS);
boolean distinct = true;
if (args != null) {
final String distinctstr = (String) args.get("distinct");
if (distinctstr != null) {
distinct = Boolean.valueOf(distinctstr).booleanValue();
}
}
return distinct;
}
/** Convert a {@link BindingListModel} to Set, Map, List, or BindingListModel (itself).
* @param val must be BindingListModelSet, BindingListModelList, BindingListModelMap, or other kind of BindingListModel
*/
public Object coerceToBean(Object val, Component comp) {
if (val == null) {
throw new NullPointerException("val");
}
if (val instanceof BindingListModelSet) {
return ((BindingListModelSet) val).getInnerSet();
} else if (val instanceof BindingListModelList) {
return ((BindingListModelList) val).getInnerList();
} else if (val instanceof BindingListModelMap) {
return ((BindingListModelMap) val).getInnerMap();
} else if (val instanceof BindingListModelArray) {
return ((BindingListModelArray) val).getInnerArray();
} else if (val instanceof BindingListModel) {
return val;
} else if (val instanceof BindingListModelListModel) {
return ((BindingListModelListModel) val).getInnerModel();
} else {
throw new UiException(
"Expects BindingListModelSet, BindingListModelList, BindingListModelMap, BindingListModelListModel or BindingListModel only."
+ val.getClass());
}
}
}