package com.revolsys.ui.html.fields; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import javax.servlet.http.HttpServletRequest; import com.revolsys.record.io.format.xml.XmlWriter; import com.revolsys.ui.html.form.Form; import com.revolsys.util.HtmlAttr; import com.revolsys.util.HtmlElem; public class SelectField extends Field { private Object defaultValue; private String nullValueLabel = "(None)"; private String onChange; private final Map<String, FieldValue> optionMap = new HashMap<>(); private final List<FieldValue> options = new ArrayList<>(); private final Map<Object, FieldValue> optionValueMap = new HashMap<>(); private String stringValue; public SelectField() { } public SelectField(final String name, final boolean required) { this(name, required, "(None)"); } public SelectField(final String name, final boolean required, final String nullValueLabel) { super(name, required); this.nullValueLabel = nullValueLabel; } public SelectField(final String name, final Object defaultValue, final boolean required, final Map<? extends Object, ? extends Object> options) { this(name, required); this.defaultValue = defaultValue; if (defaultValue != null) { this.stringValue = defaultValue.toString(); } for (final Entry<?, ?> entry : options.entrySet()) { final Object value = entry.getKey(); final Object label = entry.getValue(); addOption(value, label); } } public SelectField(final String name, final String defaultValue, final boolean required) { this(name, required); this.defaultValue = defaultValue; this.stringValue = defaultValue; } public SelectField addOption(final int index, final Object value, final String stringValue, final String label) { final FieldValue option = new FieldValue(value, stringValue, label); this.options.add(index, option); this.optionMap.put(stringValue, option); this.optionValueMap.put(value, option); return this; } public SelectField addOption(final Object value, final Object label) { return addOption(value, label.toString()); } public SelectField addOption(final Object value, final Object stringValue, final String label) { return addOption(value, stringValue.toString(), label); } public SelectField addOption(final Object value, final String label) { String stringValue = null; if (value != null) { stringValue = value.toString(); } return addOption(value, stringValue, label); } public SelectField addOption(final Object value, final String stringValue, final String label) { final FieldValue option = new FieldValue(value, stringValue, label); this.options.add(option); this.optionMap.put(stringValue, option); this.optionValueMap.put(value, option); return this; } public SelectField addOption(final String label) { return addOption(label, label); } public SelectField addOption(final String value, final String label) { return addOption(value, value, label); } public SelectField addOptions(final Map<Object, String> options) { for (final Entry<Object, String> entry : options.entrySet()) { final Object key = entry.getKey(); final String label = entry.getValue(); addOption(key, label); } return this; } @Override public SelectField clone() { final SelectField field = new SelectField(); field.setName(getName()); field.setDefaultValue(getDefaultValue()); field.setRequired(isRequired()); field.setReadOnly(isReadOnly()); field.setNullValueLabel(getNullValueLabel()); for (final FieldValue fieldValue : this.options) { final Object value = fieldValue.getValue(); final String stringValue = fieldValue.getStringValue(); final String label = fieldValue.getLabel(); field.addOption(value, stringValue, label); } return field; } public Object getDefaultValue() { return this.defaultValue; } public String getNullValueLabel() { return this.nullValueLabel; } public FieldValue getSelectedOption() { return this.optionMap.get(this.stringValue); } public String getStringValue() { return this.stringValue; } @Override public boolean hasValue() { return this.stringValue != null && !this.stringValue.equals(""); } @Override public void initialize(final Form form, final HttpServletRequest request) { if (!isRequired()) { addOption(0, null, null, this.nullValueLabel); } this.stringValue = request.getParameter(getName()); if (this.stringValue == null) { setValue(getInitialValue(request)); } } @Override public boolean isValid() { boolean valid = true; if (!super.isValid()) { valid = false; } else if (hasValue()) { final FieldValue option = getSelectedOption(); if (option == null) { addValidationError("Invalid Value"); valid = false; } if (valid) { setValue(option.getValue()); } } return valid; } @Override public void serializeElement(final XmlWriter out) { out.startTag(HtmlElem.SELECT); out.attribute(HtmlAttr.NAME, getName()); out.attribute(HtmlAttr.CLASS, "form-control input-sm"); if (this.onChange != null) { out.attribute(HtmlAttr.ON_CHANGE, this.onChange); } if (isRequired()) { out.attribute(HtmlAttr.REQUIRED, true); } serializeOptions(out); out.endTag(HtmlElem.SELECT); } private void serializeOptions(final XmlWriter out) { if (this.options.size() == 0) { addOption(null, "(None)"); } for (final FieldValue option : this.options) { out.startTag(HtmlElem.OPTION); if (option.getStringValue().equals(this.stringValue)) { out.attribute(HtmlAttr.SELECTED, "true"); } if (!option.getStringValue().equals(option.getLabel())) { out.attribute(HtmlAttr.VALUE, option.getStringValue()); } out.text(option.getLabel()); out.endTag(HtmlElem.OPTION); } } public void setDefaultValue(final Object defaultValue) { this.defaultValue = defaultValue; } public void setNullValueLabel(final String nullValueLabel) { this.nullValueLabel = nullValueLabel; } public void setOnChange(final String onChange) { this.onChange = onChange; } public void setOptions(final Map<Object, String> options) { this.options.clear(); this.optionMap.clear(); this.optionValueMap.clear(); for (final Entry<Object, String> entry : options.entrySet()) { final Object key = entry.getKey(); final String label = entry.getValue(); addOption(key, label); } } @Override public void setValue(final Object value) { super.setValue(value); if (value != null) { final FieldValue option = this.optionValueMap.get(value); if (option != null) { this.stringValue = option.getStringValue(); } else { super.setValue(null); this.stringValue = null; } } } }