com.xpn.xwiki.objects.classes.ListClass.java Source code

Java tutorial

Introduction

Here is the source code for com.xpn.xwiki.objects.classes.ListClass.java

Source

/*
 * 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.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.ecs.xhtml.input;
import org.apache.ecs.xhtml.option;
import org.apache.ecs.xhtml.select;
import org.dom4j.Element;

import com.xpn.xwiki.XWikiContext;
import com.xpn.xwiki.objects.BaseCollection;
import com.xpn.xwiki.objects.BaseProperty;
import com.xpn.xwiki.objects.DBStringListProperty;
import com.xpn.xwiki.objects.ListProperty;
import com.xpn.xwiki.objects.StringListProperty;
import com.xpn.xwiki.objects.StringProperty;
import com.xpn.xwiki.objects.meta.PropertyMetaClass;
import com.xpn.xwiki.plugin.query.XWikiCriteria;
import com.xpn.xwiki.plugin.query.XWikiQuery;

public abstract class ListClass extends PropertyClass {

    public ListClass(String name, String prettyname, PropertyMetaClass wclass) {
        super(name, prettyname, wclass);
        setRelationalStorage(false);
        setDisplayType("select");
        setMultiSelect(false);
        setSize(1);
        setSeparator(" ");
        setCache(false);
    }

    public ListClass(PropertyMetaClass wclass) {
        this("list", "List", wclass);
    }

    public ListClass() {
        this(null);
    }

    public String getSeparators() {
        String separators = getStringValue("separators");
        if (separators == null || separators.equals("")) {
            separators = "|,";
        }
        return separators;
    }

    public void setSeparators(String separators) {
        setStringValue("separators", separators);
    }

    public String getDisplayType() {
        return getStringValue("displayType");
    }

    public void setDisplayType(String type) {
        setStringValue("displayType", type);
    }

    public String getSort() {
        return getStringValue("sort");
    }

    public void setSort(String sort) {
        setStringValue("sort", sort);
    }

    public int getSize() {
        return getIntValue("size");
    }

    public void setSize(int size) {
        setIntValue("size", size);
    }

    public boolean isCache() {
        return (getIntValue("cache") == 1);
    }

    public void setCache(boolean cache) {
        setIntValue("cache", cache ? 1 : 0);
    }

    public boolean isMultiSelect() {
        return (getIntValue("multiSelect") == 1);
    }

    public void setMultiSelect(boolean multiSelect) {
        setIntValue("multiSelect", multiSelect ? 1 : 0);
    }

    public boolean isRelationalStorage() {
        return (getIntValue("relationalStorage") == 1);
    }

    public void setRelationalStorage(boolean storage) {
        setIntValue("relationalStorage", storage ? 1 : 0);
    }

    public boolean isPicker() {
        return (getIntValue("picker") == 1);
    }

    public void setPicker(boolean picker) {
        setIntValue("picker", picker ? 1 : 0);
    }

    public String getSeparator() {
        return getStringValue("separator");
    }

    public void setSeparator(String separator) {
        setStringValue("separator", separator);
    }

    public static List<String> getListFromString(String value) {
        return getListFromString(value, "|", true);
    }

    public static List<String> getListFromString(String value, String separators, boolean withMap) {
        List<String> list = new ArrayList<String>();
        if (value == null) {
            return list;
        }
        if (separators == null) {
            separators = "|";
        }

        String val = value;
        if (separators.length() == 1) {
            val = StringUtils.replace(val, "\\" + separators, "%PIPE%");
        }

        String[] result = StringUtils.split(val, separators);
        String item = "";
        for (int i = 0; i < result.length; i++) {
            String element = StringUtils.replace(result[i], "%PIPE%", separators);
            if (withMap && (element.indexOf('=') != -1)) {
                item = StringUtils.split(element, "=")[0];
            } else {
                item = element;
            }
            if (!item.trim().equals("")) {
                list.add(item);
            }
        }
        return list;
    }

    public static Map<String, ListItem> getMapFromString(String value) {
        Map<String, ListItem> map = new HashMap<String, ListItem>();
        if (value == null) {
            return map;
        }

        String val = StringUtils.replace(value, "\\|", "%PIPE%");
        String[] result = StringUtils.split(val, "|");
        for (int i = 0; i < result.length; i++) {
            String element = StringUtils.replace(result[i], "%PIPE%", "|");
            if (element.indexOf('=') != -1) {
                String[] data = StringUtils.split(element, "=");
                map.put(data[0], new ListItem(data[0], data[1]));
            } else {
                map.put(element, new ListItem(element, element));
            }
        }
        return map;
    }

    @Override
    public BaseProperty newProperty() {
        BaseProperty lprop;

        if (isRelationalStorage() && isMultiSelect()) {
            lprop = new DBStringListProperty();
        } else if (isMultiSelect()) {
            lprop = new StringListProperty();
        } else {
            lprop = new StringProperty();
        }

        return lprop;
    }

    @Override
    public BaseProperty fromString(String value) {
        BaseProperty prop = newProperty();
        if (isMultiSelect()) {
            ((ListProperty) prop).setList(getListFromString(value, getSeparators(), false));
        } else {
            prop.setValue(value);
        }
        return prop;
    }

    @Override
    public BaseProperty fromStringArray(String[] strings) {
        if (!isMultiSelect()) {
            return fromString(strings[0]);
        }
        BaseProperty prop = newProperty();
        if (prop instanceof StringProperty) {
            return fromString(strings[0]);
        }

        List<String> list = new ArrayList<String>();
        ((ListProperty) prop).setList(list);

        if (strings.length == 0) {
            return prop;
        }

        if ((strings.length == 1) && (getDisplayType().equals("input") || isMultiSelect())) {
            ((ListProperty) prop).setList(getListFromString(strings[0], getSeparators(), false));
            return prop;
        }

        // If Multiselect and multiple results
        for (int i = 0; i < strings.length; i++) {
            String item = strings[i];
            if (!item.trim().equals("")) {
                list.add(item);
            }
        }
        return prop;
    }

    @Override
    public BaseProperty newPropertyfromXML(Element ppcel) {
        if (!isMultiSelect()) {
            return super.newPropertyfromXML(ppcel);
        }

        @SuppressWarnings("unchecked")
        List<Element> elist = ppcel.elements("value");
        BaseProperty lprop = newProperty();

        if (lprop instanceof ListProperty) {
            List<String> llist = ((ListProperty) lprop).getList();
            for (int i = 0; i < elist.size(); i++) {
                Element el = elist.get(i);
                llist.add(el.getText());
            }
        } else {
            for (int i = 0; i < elist.size(); i++) {
                Element el = elist.get(i);
                ((StringProperty) lprop).setValue(el.getText());
            }
        }
        return lprop;
    }

    /**
     * Search for an internationalizable display text for the current value. The search process is:
     * <ol>
     * <li>let V = the internal value of the option, used as the "value" attribute of the <option> element, 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 option_<fieldName>_<V> exists, return it as D</li>
     * <li>else, if a message with the key option_<V> exists, return it as D</li>
     * <li>else, D can be specified in the values parameter of the property by using V=D</li>
     * <li>else return V</li>
     * </ol>
     * 
     * @param value The internal value.
     * @param name The name of the ListProperty.
     * @param map The value=name mapping specified in the "values" parameter of the property.
     * @param context The request context.
     * @return The text that should be displayed, representing a human-understandable name for the internal value.
     */
    protected String getDisplayValue(String value, String name, Map<String, ListItem> map, XWikiContext context) {
        ListItem item = map.get(value);
        String displayValue;
        if (item == null) {
            displayValue = value;
        } else {
            displayValue = item.getValue();
        }
        if ((context == null) || (context.getWiki() == null)) {
            return displayValue;
        }
        String msgname = getFieldFullName() + "_" + value;
        String newresult = context.getMessageTool().get(msgname);
        if (msgname.equals(newresult)) {
            msgname = "option_" + name + "_" + value;
            newresult = context.getMessageTool().get(msgname);
            if (msgname.equals(newresult)) {
                msgname = "option_" + value;
                newresult = context.getMessageTool().get(msgname);
                if (msgname.equals(newresult)) {
                    return displayValue;
                }
            }
        }
        return newresult;
    }

    /**
     * Search for an internationalizable display text for the current value. The value can be either a simple string, or
     * a value=name pair selected from the database.
     * 
     * @see #getDisplayValue(String, String, Map, XWikiContext)
     * @param rawvalue The internal value, or a value=name pair.
     * @param name The name of the ListProperty.
     * @param map The value=name mapping specified in the "values" parameter of the property.
     * @param context The request context.
     * @return The text that should be displayed, representing a human-understandable name for the internal value.
     */
    protected String getDisplayValue(Object rawvalue, String name, Map<String, ListItem> map,
            XWikiContext context) {
        if (rawvalue == null) {
            return "";
        }
        if (rawvalue instanceof Object[]) {
            return ((Object[]) rawvalue)[1].toString();
        }
        return getDisplayValue(rawvalue.toString(), name, map, context);
    }

    /**
     * If the list is populated with value=name pairs selected from the database, then return only the value. Otherwise,
     * it is a simple value.
     * 
     * @param rawvalue
     * @return The list value
     */
    protected String getElementValue(Object rawvalue) {
        if (rawvalue == null) {
            return "";
        }
        if (rawvalue instanceof Object[]) {
            return ((Object[]) rawvalue)[0].toString();
        }
        return rawvalue.toString();
    }

    @Override
    public void displayHidden(StringBuffer buffer, String name, String prefix, BaseCollection object,
            XWikiContext context) {
        input input = new input();
        BaseProperty prop = (BaseProperty) object.safeget(name);
        if (prop != null) {
            input.setValue(prop.toFormString());
        }

        input.setType("hidden");
        input.setName(prefix + name);
        input.setID(prefix + name);
        buffer.append(input.toString());
    }

    @Override
    public void displayView(StringBuffer buffer, String name, String prefix, BaseCollection object,
            XWikiContext context) {
        List<String> selectlist;
        String separator = getSeparator();
        BaseProperty prop = (BaseProperty) object.safeget(name);
        Map<String, ListItem> map = getMap(context);

        // Skip unset values.
        if (prop == null) {
            return;
        }

        if (prop instanceof ListProperty) {
            selectlist = ((ListProperty) prop).getList();
            List<String> newlist = new ArrayList<String>();
            for (String value : selectlist) {
                newlist.add(getDisplayValue(value, name, map, context));
            }
            buffer.append(StringUtils.join(newlist, separator));
        } else {
            buffer.append(getDisplayValue(prop.getValue(), name, map, context));
        }
    }

    @Override
    public void displayEdit(StringBuffer buffer, String name, String prefix, BaseCollection object,
            XWikiContext context) {
        if (getDisplayType().equals("input")) {
            input input = new input();
            BaseProperty prop = (BaseProperty) object.safeget(name);
            if (prop != null) {
                input.setValue(prop.toFormString());
            }
            input.setType("text");
            input.setSize(getSize());
            input.setName(prefix + name);
            input.setID(prefix + name);
            input.setDisabled(isDisabled());
            buffer.append(input.toString());
        } else if (getDisplayType().equals("radio") || getDisplayType().equals("checkbox")) {
            displayRadioEdit(buffer, name, prefix, object, context);
        } else {
            displaySelectEdit(buffer, name, prefix, object, context);
        }

        if (!getDisplayType().equals("input")) {
            org.apache.ecs.xhtml.input hidden = new input(input.hidden, prefix + name, "");
            buffer.append(hidden);
        }
    }

    protected void displayRadioEdit(StringBuffer buffer, String name, String prefix, BaseCollection object,
            XWikiContext context) {
        List<String> list = getList(context);
        Map<String, ListItem> map = getMap(context);
        List<String> selectlist;

        BaseProperty prop = (BaseProperty) object.safeget(name);
        if (prop == null) {
            selectlist = new ArrayList<String>();
        } else if (prop instanceof ListProperty) {
            selectlist = ((ListProperty) prop).getList();
        } else {
            selectlist = new ArrayList<String>();
            selectlist.add(String.valueOf(prop.getValue()));
        }

        // TODO: add elements that are in the values but not in the predefined list..
        for (String item : selectlist) {
            if (!list.contains(item)) {
                list.add(item);
            }
        }

        // Add options from Set
        int count = 0;
        for (Object rawvalue : list) {
            String value = getElementValue(rawvalue);
            input radio = new input(
                    (getDisplayType().equals("radio") && !isMultiSelect()) ? input.radio : input.checkbox,
                    prefix + name, value);
            radio.setID("xwiki-form-" + name + "-" + count);
            radio.setDisabled(isDisabled());

            if (selectlist.contains(value)) {
                radio.setChecked(true);
            }
            radio.addElement(getDisplayValue(rawvalue, name, map, context));

            buffer.append("<label class=\"xwiki-form-listclass\" for=\"xwiki-form-" + name + "-" + count++ + "\">");
            buffer.append(radio.toString());
            buffer.append("</label>");
        }

        org.apache.ecs.xhtml.input hidden = new input(input.hidden, prefix + name, "");
        buffer.append(hidden);
    }

    protected class MapComparator implements Comparator<String> {
        protected Map<String, ListItem> map;

        public MapComparator(Map<String, ListItem> map) {
            this.map = map;
        }

        public int compare(String o1, String o2) {
            ListItem s1 = this.map.get(o1);
            ListItem s2 = this.map.get(o2);

            if ((s1 == null) && (s2 == null)) {
                return 0;
            }

            if (s1 == null) {
                return -1;
            }

            if (s2 == null) {
                return 1;
            }

            return s1.getValue().compareTo(s2.getValue());
        }
    }

    protected void displaySelectEdit(StringBuffer buffer, String name, String prefix, BaseCollection object,
            XWikiContext context) {
        select select = new select(prefix + name, 1);
        select.setMultiple(isMultiSelect());
        select.setSize(getSize());
        select.setName(prefix + name);
        select.setID(prefix + name);
        select.setDisabled(isDisabled());

        List<String> list = getList(context);
        Map<String, ListItem> map = getMap(context);

        String sort = getSort();
        if (!"none".equals(sort)) {
            if ("id".equals(sort)) {
                Collections.sort(list);
            }
            if ("value".equals(sort)) {
                Collections.sort(list, new MapComparator(map));
            }
        }

        List<String> selectlist;

        BaseProperty prop = (BaseProperty) object.safeget(name);
        if (prop == null) {
            selectlist = new ArrayList<String>();
        } else if (prop instanceof ListProperty) {
            selectlist = ((ListProperty) prop).getList();
        } else {
            selectlist = new ArrayList<String>();
            selectlist.add(String.valueOf(prop.getValue()));
        }

        // TODO: add elements that are in the values but not in the predefined list..
        for (String item : selectlist) {
            if (!list.contains(item)) {
                list.add(item);
            }
        }

        // Add options from Set
        for (String rawvalue : list) {
            String value = getElementValue(rawvalue);
            String display = getDisplayValue(rawvalue, name, map, context);
            option option = new option(display, value);
            option.addElement(display);
            if (selectlist.contains(value)) {
                option.setSelected(true);
            }
            select.addElement(option);
        }

        buffer.append(select.toString());
    }

    public abstract List<String> getList(XWikiContext context);

    public abstract Map<String, ListItem> getMap(XWikiContext context);

    @Override
    public String displaySearch(String name, String prefix, XWikiCriteria criteria, XWikiContext context) {
        if (getDisplayType().equals("input")) {
            return super.displaySearch(name, prefix, criteria, context);
        } else if (getDisplayType().equals("radio") || getDisplayType().equals("checkbox")) {
            return displayRadioSearch(name, prefix, criteria, context);
        } else {
            return displaySelectSearch(name, prefix, criteria, context);
        }
    }

    protected String displayRadioSearch(String name, String prefix, XWikiCriteria criteria, XWikiContext context) {
        StringBuffer buffer = new StringBuffer();
        List<String> list = getList(context);
        List<String> selectlist = new ArrayList<String>();

        /*
         * BaseProperty prop = (BaseProperty)object.safeget(name); if (prop==null) { selectlist = new ArrayList(); }
         * else if ((prop instanceof ListProperty)||(prop instanceof DBStringListProperty)) { selectlist = (List)
         * prop.getValue(); } else { selectlist = new ArrayList(); selectlist.add(prop.getValue()); }
         */

        // Add options from Set
        for (Iterator<String> it = list.iterator(); it.hasNext();) {
            String rawvalue = it.next();
            String value = getElementValue(rawvalue);
            String display = getDisplayValue(rawvalue, name, getMap(context), context);
            input radio = new input(getDisplayType().equals("radio") ? input.radio : input.checkbox, prefix + name,
                    value);

            if (selectlist.contains(value)) {
                radio.setChecked(true);
            }
            radio.addElement(display);
            buffer.append(radio.toString());
            if (it.hasNext()) {
                buffer.append("<br/>");
            }
        }
        return buffer.toString();
    }

    protected String displaySelectSearch(String name, String prefix, XWikiCriteria criteria, XWikiContext context) {
        select select = new select(prefix + name, 1);
        select.setMultiple(true);
        select.setSize(5);
        select.setName(prefix + name);
        select.setID(prefix + name);

        List<String> list = getList(context);
        String fieldFullName = getFieldFullName();
        String[] selectArray = ((String[]) criteria.getParameter(fieldFullName));
        List<String> selectlist = (selectArray != null) ? Arrays.asList(selectArray) : new ArrayList<String>();

        /*
         * BaseProperty prop = (BaseProperty)object.safeget(name); if (prop==null) { selectlist = new ArrayList(); }
         * else if ((prop instanceof ListProperty)||(prop instanceof DBStringListProperty)) { selectlist = (List)
         * prop.getValue(); } else { selectlist = new ArrayList(); selectlist.add(prop.getValue()); }
         */

        // Add options from Set
        for (String rawvalue : list) {
            String value = getElementValue(rawvalue);
            String display = getDisplayValue(rawvalue, name, getMap(context), context);
            option option = new option(display, value);
            option.addElement(display);
            if (selectlist.contains(value)) {
                option.setSelected(true);
            }
            select.addElement(option);
        }

        return select.toString();
    }

    @Override
    public void makeQuery(Map<String, Object> map, String prefix, XWikiCriteria query, List<String> criteriaList) {
        Object values = map.get(prefix);
        if ((values == null) || (values.equals(""))) {
            return;
        }

        // if multiselect
        // :category member of obj.category
        // otherwise 
        // :category = obj.category
        String separator = isMultiSelect() ? " member of " : " = ";

        if (values instanceof String) {
            // general comparison '=' - tests at least one value =
            criteriaList.add("'" + values.toString() + "'" + separator + getFullQueryPropertyName());
        } else {
            String[] valuesarray = (String[]) values;
            String[] criteriaarray = new String[valuesarray.length];
            for (int i = 0; i < valuesarray.length; i++) {
                criteriaarray[i] = "'" + valuesarray[i] + "'" + separator + getFullQueryPropertyName();
            }
            criteriaList.add("(" + StringUtils.join(criteriaarray, " or ") + ")");
        }
        return;
    }

    @Override
    public void fromSearchMap(XWikiQuery query, Map<String, String[]> map) {
        String[] data = map.get("");
        if (data != null) {
            query.setParam(getObject().getName() + "_" + getName(), data);
        }
    }
}