package fr.openwide.core.wicket.more.markup.html.template.js.jquery.plugins.itemit; import java.util.List; import java.util.Locale; import org.apache.wicket.behavior.AttributeAppender; import org.apache.wicket.markup.head.IHeaderResponse; import org.apache.wicket.markup.head.JavaScriptHeaderItem; import org.apache.wicket.markup.head.OnDomReadyHeaderItem; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.form.FormComponentPanel; import org.apache.wicket.markup.html.list.ListItem; import org.apache.wicket.markup.html.list.ListView; import org.apache.wicket.model.IModel; import org.apache.wicket.util.convert.ConversionException; import org.wicketstuff.wiquery.core.javascript.JsStatement; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.Lists; public abstract class ItemItField<F, J> extends FormComponentPanel<List<F>> { private static final long serialVersionUID = -9155020419420538737L; private static final Logger LOGGER = LoggerFactory.getLogger(ItemItField.class); private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); private AjaxItemItBehavior<F, J> completeBehavior; private ItemIt itemIt; public abstract List<F> getValues(String term); public abstract J newAutocompleteJson(Integer index, F item, Locale locale); public abstract F convertValue(J value); public abstract Class<J> getJsonType(); public ItemItField(String id, IModel<List<F>> selectedItemListModel) { this(id, selectedItemListModel, null); } public ItemItField(String id, IModel<List<F>> selectedItemListModel, ItemIt itemIt) { super(id, selectedItemListModel); if (itemIt == null) { this.itemIt = new ItemIt(); } else { this.itemIt = itemIt; } add(new ListView<F>("itemList", selectedItemListModel) { private static final long serialVersionUID = 1L; @Override protected void populateItem(ListItem<F> item) { WebMarkupContainer field = new WebMarkupContainer("item"); field.add(new AttributeAppender("value", new JsonModel(item.getModel()))); field.add(new AttributeAppender("name", new InputNameModel())); item.add(field); } }); completeBehavior = new AjaxItemItBehavior<F, J>() { private static final long serialVersionUID = 1L; @Override public List<F> getValues(String term) { return ItemItField.this.getValues(term); } @Override public J newAutocompleteJson(Integer index, F item, Locale locale) { return ItemItField.this.newAutocompleteJson(index, item, locale); } @Override public Class<?> getJsonType() { return ItemItField.this.getJsonType(); } }; add(completeBehavior); } @Override protected List<F> convertValue(String[] values) throws ConversionException { if (values == null) { return Lists.newArrayList(); } else { List<F> convertedValues = Lists.newArrayList(); for (String value : values) { try { J convertedValue = OBJECT_MAPPER.readValue(value, getJsonType()); convertedValues.add(convertValue(convertedValue)); } catch (Exception e) { throw new ConversionException(e); } } return convertedValues; } } @Override public void onBeforeRender() { itemIt.setInternalJsonSource(completeBehavior.getCallbackUrl().toString()); itemIt.setFieldName(getInputName()); super.onBeforeRender(); } @Override public void renderHead(IHeaderResponse response) { super.renderHead(response); response.render(JavaScriptHeaderItem.forReference(ItemItJavascriptResourceReference.get())); JsStatement statement = statement(); if (statement != null) { response.render(OnDomReadyHeaderItem.forScript(statement().render())); } } protected JsStatement statement() { return new JsStatement().$(this).chain(itemIt); } public class InputNameModel implements IModel<String> { private static final long serialVersionUID = -3856892968691396356L; @Override public void detach() { // nothing } @Override public String getObject() { return getInputName(); } @Override public void setObject(String value) { throw new IllegalStateException("Not supported"); } } public class JsonModel implements IModel<String> { private static final long serialVersionUID = 6384538050831419296L; private IModel<F> objectModel; public JsonModel(IModel<F> objectModel) { super(); this.objectModel = objectModel; } @Override public void detach() { if (this.objectModel != null) { this.objectModel.detach(); } } @Override public String getObject() { if (objectModel != null) { try { return OBJECT_MAPPER.writeValueAsString(newAutocompleteJson(null, objectModel.getObject(), getLocale())); } catch (Exception e) { LOGGER.error("Unable to serialize the model object", e); throw new IllegalStateException("Unable to serialize the model object", e); } } else { return ""; } } @Override public void setObject(String object) { } } protected ItemIt getItemItOptions() { return itemIt; } }