/* * See the NOTICE file distributed with this work for additional * information regarding copyright ownership. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package com.xpn.xwiki.objects.classes; import java.util.regex.Pattern; import org.apache.commons.lang3.StringUtils; import org.apache.ecs.xhtml.div; import org.apache.ecs.xhtml.input; import org.apache.ecs.xhtml.label; import org.apache.ecs.xhtml.option; import org.apache.ecs.xhtml.select; import org.xwiki.xml.XMLUtils; import com.xpn.xwiki.XWikiContext; import com.xpn.xwiki.internal.xml.XMLAttributeValueFilter; import com.xpn.xwiki.objects.BaseCollection; import com.xpn.xwiki.objects.BaseProperty; import com.xpn.xwiki.objects.IntegerProperty; import com.xpn.xwiki.objects.meta.PropertyMetaClass; public class BooleanClass extends PropertyClass { private static final String XCLASSNAME = "boolean"; /** Other string values that might be used to represent "true" values. */ private static final Pattern TRUE_PATTERN = Pattern.compile("yes|true", Pattern.CASE_INSENSITIVE); /** Other string values that might be used to represent "false" values. */ private static final Pattern FALSE_PATTERN = Pattern.compile("no|false", Pattern.CASE_INSENSITIVE); public BooleanClass(PropertyMetaClass wclass) { super(XCLASSNAME, "Boolean", wclass); } public BooleanClass() { this(null); setDisplayFormType("select"); } public void setDisplayType(String type) { setStringValue("displayType", type); } public String getDisplayType() { String dtype = getStringValue("displayType"); if ((dtype == null) || (dtype.equals(""))) { return "yesno"; } return dtype; } public String getDisplayFormType() { String dtype = getStringValue("displayFormType"); if ((dtype == null) || (dtype.equals(""))) { return "radio"; } return dtype; } public void setDisplayFormType(String type) { setStringValue("displayFormType", type); } public void setDefaultValue(int dvalue) { setIntValue("defaultValue", dvalue); } public int getDefaultValue() { return getIntValue("defaultValue", -1); } @Override public BaseProperty fromString(String value) { BaseProperty property = newProperty(); Number nvalue = null; if (StringUtils.isNotEmpty(value)) { if (StringUtils.isNumeric(value)) { nvalue = Integer.valueOf(value); } else if (TRUE_PATTERN.matcher(value).matches()) { nvalue = 1; } else if (FALSE_PATTERN.matcher(value).matches()) { nvalue = 0; } } // We don't return null if there's no value, since the BooleanProperty really works that way property.setValue(nvalue); return property; } @Override public BaseProperty newProperty() { BaseProperty property = new IntegerProperty(); property.setName(getName()); return property; } @Override public void displayView(StringBuffer buffer, String name, String prefix, BaseCollection object, XWikiContext context) { IntegerProperty prop = (IntegerProperty) object.safeget(name); if (prop == null) { return; } Integer iValue = (Integer) prop.getValue(); if (iValue != null) { int value = iValue.intValue(); buffer.append(getDisplayValue(context, value)); } } @Override public void displayEdit(StringBuffer buffer, String name, String prefix, BaseCollection object, XWikiContext context) { String displayFormType = getDisplayFormType(); if (getDisplayType().equals("checkbox")) { displayFormType = "checkbox"; } if (displayFormType.equals("checkbox")) { displayCheckboxEdit(buffer, name, prefix, object, context); } else if (displayFormType.equals("select")) { displaySelectEdit(buffer, name, prefix, object, context); } else { displayRadioEdit(buffer, name, prefix, object, context); } } public void displaySelectEdit(StringBuffer buffer, String name, String prefix, BaseCollection object, XWikiContext context) { select select = new select(prefix + name, 1); select.setAttributeFilter(new XMLAttributeValueFilter()); select.setName(prefix + name); select.setID(prefix + name); select.setDisabled(isDisabled()); String String0 = getDisplayValue(context, 0); String String1 = getDisplayValue(context, 1); int nb1 = 1; int nb2 = 2; option[] options; if (getDefaultValue() == -1) { options = new option[] { new option("---", ""), new option(String1, "1"), new option(String0, "0") }; options[0].addElement("---"); options[1].addElement(XMLUtils.escape(String1)); options[2].addElement(XMLUtils.escape(String0)); } else { options = new option[] { new option(String1, "1"), new option(String0, "0") }; options[0].addElement(XMLUtils.escape(String1)); options[1].addElement(XMLUtils.escape(String0)); nb1 = 0; nb2 = 1; } for (option option : options) { option.setAttributeFilter(new XMLAttributeValueFilter()); } try { IntegerProperty prop = (IntegerProperty) object.safeget(name); Integer ivalue = (prop == null) ? null : (Integer) prop.getValue(); if (ivalue != null) { int value = ivalue.intValue(); if (value == 1) { options[nb1].setSelected(true); } else if (value == 0) { options[nb2].setSelected(true); } } else { int value = getDefaultValue(); if (value == 1) { options[nb1].setSelected(true); } else if (value == 0) { options[nb2].setSelected(true); } else if (value == -1) { options[0].setSelected(true); } } } catch (Exception e) { // This should not happen e.printStackTrace(); } select.addElement(options); buffer.append(select.toString()); } public void displayRadioEdit(StringBuffer buffer, String name, String prefix, BaseCollection object, XWikiContext context) { String StringNone = getDisplayValue(context, 2); String StringTrue = getDisplayValue(context, 1); String StringFalse = getDisplayValue(context, 0); div[] inputs; input radioNone = new input(input.radio, prefix + name, ""); radioNone.setAttributeFilter(new XMLAttributeValueFilter()); input radioTrue = new input(input.radio, prefix + name, "1"); radioTrue.setAttributeFilter(new XMLAttributeValueFilter()); input radioFalse = new input(input.radio, prefix + name, "0"); radioFalse.setAttributeFilter(new XMLAttributeValueFilter()); radioNone.setDisabled(isDisabled()); radioTrue.setDisabled(isDisabled()); radioFalse.setDisabled(isDisabled()); label labelNone = new label(); label labelTrue = new label(); label labelFalse = new label(); div divNone = new div(); div divTrue = new div(); div divFalse = new div(); labelNone.addElement(radioNone); labelNone.addElement(StringNone); divNone.addElement(labelNone); labelTrue.addElement(radioTrue); labelTrue.addElement(StringTrue); divTrue.addElement(labelTrue); labelFalse.addElement(radioFalse); labelFalse.addElement(StringFalse); divFalse.addElement(labelFalse); radioNone.setID(prefix + name + "_none"); labelNone.setFor(prefix + name + "_none"); radioTrue.setID(prefix + name); labelTrue.setFor(prefix + name); radioFalse.setID(prefix + name + "_false"); labelFalse.setFor(prefix + name + "_false"); if (getDefaultValue() == -1) { inputs = new div[] { divNone, divTrue, divFalse }; } else { inputs = new div[] { divTrue, divFalse }; } try { IntegerProperty prop = (IntegerProperty) object.safeget(name); Integer ivalue = (prop == null) ? null : (Integer) prop.getValue(); if (ivalue != null) { int value = ivalue.intValue(); if (value == 1) { radioTrue.setChecked(true); } else if (value == 0) { radioFalse.setChecked(true); } } else { int value = getDefaultValue(); if (value == 1) { radioTrue.setChecked(true); } else if (value == 0) { radioFalse.setChecked(true); } else if (value == -1) { radioNone.setChecked(true); } } } catch (Exception e) { // This should not happen e.printStackTrace(); } for (div input : inputs) { buffer.append(input.toString()); } } public void displayCheckboxEdit(StringBuffer buffer, String name, String prefix, BaseCollection object, XWikiContext context) { org.apache.ecs.xhtml.input check = new input(input.checkbox, prefix + name, 1); check.setAttributeFilter(new XMLAttributeValueFilter()); check.setID(prefix + name); check.setDisabled(isDisabled()); // If the (visible) checkbox is unchecked, it will not post anything back so the hidden input by the same // name will post back 0 and the save function will save the first entry it finds. org.apache.ecs.xhtml.input checkNo = new input(input.hidden, prefix + name, 0); checkNo.setAttributeFilter(new XMLAttributeValueFilter()); try { IntegerProperty prop = (IntegerProperty) object.safeget(name); if (prop != null) { Integer ivalue = (Integer) prop.getValue(); if (ivalue != null) { int value = ivalue.intValue(); if (value == 1) { check.setChecked(true); } else if (value == 0) { check.setChecked(false); } } else { int value = getDefaultValue(); if (value == 1) { check.setChecked(true); } else { check.setChecked(false); } } } } catch (Exception e) { // This should not happen e.printStackTrace(); } buffer.append(check.toString()); buffer.append(checkNo.toString()); } /** * Search for an internationalizable display text for the current value. The search process is: * <ol> * <li>let V = the internal value of the option, 0 1 or 2, T = the value of the displayType meta-property, and D = * the displayed value</li> * <li>if a message with the key <fieldFullName>_<V> exists, return it as D</li> * <li>else, if a message with the key <T>_<V> exists, return it as D</li> * <li>else return V if V is 0 or 1, or --- if V is 2 (undecided)</li> * </ol> * * @param context The request context. * @param value The internal value. * @return The text that should be displayed, representing a human-understandable name for the internal value. */ private String getDisplayValue(XWikiContext context, int value) { try { // <classname>_<property>_<value> String key = getFieldFullName() + "_" + value; String result = localizePlain(key); if (result == null) { // <display type>_<value> key = getDisplayType() + "_" + value; result = localizePlain(key); if (result == null) { // Just return the value if (value == 2) { result = "---"; } else { result = "" + value; } } } return result; } catch (Exception e) { e.printStackTrace(); return "" + value; } } }