package fr.openwide.core.wicket.more.markup.html.select2;
import java.util.Collection;
import org.apache.wicket.markup.html.form.AbstractTextComponent;
import org.apache.wicket.markup.html.form.FormComponent;
import org.apache.wicket.markup.html.form.ListMultipleChoice;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.IObjectClassAwareModel;
import org.apache.wicket.util.convert.ConversionException;
import org.retzlaff.select2.AbstractSelect2Choice;
import org.retzlaff.select2.ISelect2AjaxAdapter;
import fr.openwide.core.wicket.more.model.BindingModel;
/**
* @deprecated Use {@link GenericSelect2DropDownMultipleChoice} instead: it's got a generic constructor that allows
* you to pass any kind of collection model ({@code IModel<Set<T>>},
* {@code IModel<SortedSet<T>>}, {@code IModel<List<T>>}, ...)
*/
@Deprecated
public abstract class AbstractSelect2MultipleChoice<C extends Collection<T>, T> extends AbstractSelect2Choice<C, T> {
private static final long serialVersionUID = -4183760466356487637L;
protected static final String SELECT2_VALUE_SEPARATOR = ",";
protected AbstractSelect2MultipleChoice(String id, IModel<C> model, ISelect2AjaxAdapter<T> adapter) {
super(id, model, adapter, true);
}
protected abstract C newEmptyImplementation();
@Override
protected Collection<T> getModelObjects() {
Collection<T> collection = getModelObject();
if (collection == null) {
return newEmptyImplementation();
}
return collection;
}
@Override
public void updateModel() {
C convertedInput = getConvertedInput();
modelChanging();
getModel().setObject(convertedInput);
modelChanged();
}
/**
* @see ListMultipleChoice#getModelValue()
*/
@Override
protected String getModelValue() {
Collection<T> collection = getModelObject();
if (collection == null || collection.isEmpty()) {
return "";
}
StringBuilder sb = new StringBuilder();
for (T object : collection) {
sb.append(getAdapter().getChoiceId(object)).append(SELECT2_VALUE_SEPARATOR);
}
sb.setLength(sb.length() - 1); // trailing comma
return sb.toString();
}
/**
* Workaround.<br>
* When the underlying model is a {@link IObjectClassAwareModel} (a {@link BindingModel} for example),
* the {@link AbstractTextComponent#resolveType()} method will be able to determine the model type.<br>
* As a consequence, the {@link FormComponent#convertInput()} method will totally ignore {@link Select2SingleChoice#convertValue(String[]))},
* which is quite annoying since this is the method that makes use of {@link ISelect2AjaxAdapter#getChoice(String)}...<br>
* That's why we have to force the use of {@link #convertValue(String[])}.
*/
@Override
public void convertInput() {
try {
setConvertedInput(convertValue(getInputAsArray()));
} catch (ConversionException e) {
error(newValidationError(e));
}
}
/**
* @see ListMultipleChoice#convertValue().
*/
@Override
protected C convertValue(final String[] value) {
if (value == null || value.length == 0 || value[0] == null || (value.length == 1 && value[0] == "")) {
return newEmptyImplementation();
}
C collection = newEmptyImplementation();
String[] ids = value[0].split(SELECT2_VALUE_SEPARATOR);
for (String id : ids) {
collection.add(getAdapter().getChoice(id));
}
return collection;
}
}