/*
* Copyright 2004-2005 Revolution Systems Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.revolsys.ui.html.fields;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.apache.log4j.Logger;
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;
import com.revolsys.util.HtmlUtil;
public class MultiSelectField extends Field {
private static final Logger log = Logger.getLogger(MultiSelectField.class);
private boolean hasInvalidOptions = false;
private String onChange;
private final Map optionMap = new HashMap();
private final List options = new ArrayList();
private final Map optionValueMap = new HashMap();
private final Map selectedValues = new HashMap();
private final int size = 4;
/**
* @param name
* @param required
*/
public MultiSelectField(final String name, final boolean required) {
super(name, required);
}
public void addOption(final Object value, final Object stringValue, final String label) {
addOption(value, stringValue.toString(), label);
}
public void addOption(final Object value, final String label) {
String stringValue = null;
if (value != null) {
stringValue = value.toString();
}
addOption(value, stringValue, label);
}
public void 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);
}
public void addOption(final String label) {
addOption(label, label);
}
public void addOption(final String value, final String label) {
addOption(value, value, label);
}
@Override
public boolean hasValue() {
return !this.selectedValues.isEmpty();
}
@Override
public void initialize(final Form form, final HttpServletRequest request) {
final String[] parameterValues = request.getParameterValues(getName());
if (parameterValues == null) {
setValue(Collections.EMPTY_LIST);
if (!form.hasTask()) {
final Object initialValue = getInitialValue(request);
if (initialValue != null) {
setValue(initialValue);
}
}
} else {
for (final String stringValue : parameterValues) {
final FieldValue option = (FieldValue)this.optionMap.get(stringValue);
if (option != null) {
this.selectedValues.put(option.getStringValue(), option.getValue());
} else {
this.hasInvalidOptions = true;
}
}
}
}
@Override
public boolean isValid() {
boolean valid = true;
if (!super.isValid()) {
valid = false;
} else if (hasValue()) {
if (this.hasInvalidOptions) {
addValidationError("Invalid Value");
valid = false;
}
if (valid) {
if (this.selectedValues.isEmpty()) {
setValue(Collections.EMPTY_LIST);
} else {
setValue(new ArrayList(this.selectedValues.values()));
}
}
}
return valid;
}
@Override
public void serializeElement(final XmlWriter out) {
out.startTag(HtmlElem.SELECT);
out.attribute(HtmlAttr.NAME, getName());
out.attribute(HtmlAttr.MULTIPLE, "multiple");
out.attribute(HtmlAttr.CLASS, "form-control input-sm");
out.attribute(HtmlAttr.SIZE, String.valueOf(this.size));
if (this.onChange != null) {
out.attribute(HtmlAttr.ON_CHANGE, this.onChange);
}
serializeOptions(out);
out.endTag(HtmlElem.SELECT);
out.startTag(HtmlElem.DIV);
out.attribute(HtmlAttr.CLASS, "fieldActions");
final String baseUrl = "javascript:setMutliSelectAllSelected('" + getForm().getName() + "','"
+ getName() + "'";
HtmlUtil.serializeA(out, null, baseUrl + ",true)", "select all");
HtmlUtil.serializeA(out, null, baseUrl + ",false)", "select none");
out.endTag(HtmlElem.DIV);
}
private void serializeOptions(final XmlWriter out) {
for (final Iterator optionIter = this.options.iterator(); optionIter.hasNext();) {
final FieldValue option = (FieldValue)optionIter.next();
out.startTag(HtmlElem.OPTION);
if (this.selectedValues.containsKey(option.getStringValue())) {
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 setOnChange(final String onChange) {
this.onChange = onChange;
}
@Override
public void setValue(final Object object) {
this.selectedValues.clear();
final List valueList = (List)object;
super.setValue(valueList);
if (valueList != null) {
for (final Iterator values = valueList.iterator(); values.hasNext();) {
final Object value = values.next();
final FieldValue option = (FieldValue)this.optionValueMap.get(value);
if (option != null) {
this.selectedValues.put(option.getStringValue(), option.getValue());
}
}
}
}
}