/* 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()); } } }