org.opencms.widgets.CmsSelectWidgetOption Maven / Gradle / Ivy
Show all versions of opencms-core Show documentation
/*
* This library is part of OpenCms -
* the Open Source Content Management System
*
* Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
*
* This library 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 library 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.
*
* For further information about Alkacon Software GmbH & Co. KG, please see the
* company website: http://www.alkacon.com
*
* For further information about OpenCms, please see the
* project website: http://www.opencms.org
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.opencms.widgets;
import org.opencms.main.CmsLog;
import org.opencms.util.CmsStringUtil;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.apache.commons.logging.Log;
/**
* An option of a select type widget.
*
* If options are passed from XML content schema definitions as widget configuration options,
* the following syntax is used for defining the option values:
*
* value='{text}' default='{true|false}' option='{text}' help='{text}|{more option definitions}
*
* For example:
*
* value='value1' default='true' option='option1' help='help1'|value='value2' option='option2' help='help2'
*
* The elements default
, option
and help
are all optional, only a
* value
must be present in the input.
* There should be only one default
set to true
* in the input, if more than one is detected, only the first default
found is actually used.
* If no option
is given, the value of option
defaults to the value of the given value
.
* If no help
is given, the default is null
.
*
* Shortcut syntax options:
*
* If you don't specify the value
key, the value is assumed to start at the first position of an
* option definition. In this case the value must not be surrounded by the '
chars.
* Example: value='some value' default='true'
can also be written as some value default='true'
.
*
* Only if you use the short value definition as described above, a default value can be marked with a *
* at the end of the value definition.
* Example: value='some value' default='true'
can also be written as some value*
.
*
* Only if you use the short value definition as described above, you can also append the option
* to the value
using a :
. In this case no '
must surround the option
.
* Please keep in mind that in this case the value
* itself can not longer contain a :
char, since it would then be interpreted as a delimiter.
* Example: value='some value' option='some option'
can also be written as some value:some option
.
*
* Any combinations of the above described shortcuts are allowed in the configuration option String.
* Here are some more examples of valid configuration option Strings:
*
* 1*|2|3|4|5|6|7
* 1 default='true'|2|3|4|5|6|7
* value='1' default='true'|value='2'|value='3'
* value='1'|2*|value='3'
* 1*:option text|2|3|4
* 1* option='option text' help='some'|2|3|4
*
* Please note: If an entry in the configuration String is malformed, this error is silently ignored (but written
* to the log channel of this class at INFO
level.
*
* @since 6.0.0
*/
public class CmsSelectWidgetOption {
/** Optional shortcut default marker. */
private static final char DEFAULT_MARKER = '*';
/** Delimiter between option sets. */
private static final char INPUT_DELIMITER = '|';
/** Key prefix for the 'default'. */
private static final String KEY_DEFAULT = "default='";
/** Key prefix for the 'help' text. */
private static final String KEY_HELP = "help='";
/** Key prefix for the 'option' text. */
private static final String KEY_OPTION = "option='";
/** Key prefix for the 'value'. */
private static final String KEY_VALUE = "value='";
/** The log object for this class. */
private static final Log LOG = CmsLog.getLog(CmsSelectWidgetOption.class);
/** Optional shortcut option delimiter. */
private static final char OPTION_DELIMITER = ':';
/** Indicates if this is the default value of the selection. */
private boolean m_default;
/** The hashcode of this object. */
private int m_hashcode;
/** The (optional) help text of this select option. */
private String m_help;
/** The (optional) display text of this select option. */
private String m_option;
/** The value of this select option. */
private String m_value;
/**
* Creates a new select option for the given value.
*
* @param value the value of this select option
*/
public CmsSelectWidgetOption(String value) {
this(value, false, null, null);
}
/**
* Creates a new select option form the given values.
*
* @param value the value of this select option
* @param isDefault indicates if this is the default value of the selection (default is false
)
*/
public CmsSelectWidgetOption(String value, boolean isDefault) {
this(value, isDefault, null, null);
}
/**
* Creates a new select option form the given values.
*
* @param value the value of this select option
* @param isDefault indicates if this is the default value of the selection (default is false
)
* @param optionText the (optional) display text of this select option
*/
public CmsSelectWidgetOption(String value, boolean isDefault, String optionText) {
this(value, isDefault, optionText, null);
}
/**
* Creates a new select option form the given values.
*
* @param value the value of this select option
* @param isDefault indicates if this is the default value of the selection (default is false
)
* @param optionText the (optional) display text of this select option
* @param helpText the (optional) help text of this select option
*/
public CmsSelectWidgetOption(String value, boolean isDefault, String optionText, String helpText) {
m_default = isDefault;
m_value = value;
m_option = optionText;
m_help = helpText;
}
/**
* Returns a select widget configuration String created from the given list of select options.
*
* If an element found in the given list is not of type
* {@link CmsSelectWidgetOption}
, it is ignored.
*
* @param options the list of select options to create the configuration String for
*
* @return a select widget configuration String created from the given list of select options
*/
public static String createConfigurationString(List options) {
if ((options == null) || (options.size() == 0)) {
return "";
}
StringBuffer result = new StringBuffer(256);
boolean first = true;
for (int i = 0; i < options.size(); i++) {
CmsSelectWidgetOption o = options.get(i);
if (!first) {
result.append(CmsSelectWidgetOption.INPUT_DELIMITER);
} else {
first = false;
}
result.append(o.toString().replace("|", "\\|"));
}
return result.toString();
}
/**
* Returns the default option from the given list of select options,
* or null
in case there is no default option in the given list.
*
* If an element found in the given list is not of type
* {@link CmsSelectWidgetOption}
, this is ignored.
*
* @param options the list of select options to get the default from
*
* @return the default option from the given list of select options, or null
in case there is no default option
*/
public static CmsSelectWidgetOption getDefaultOption(List options) {
if ((options == null) || (options.size() == 0)) {
return null;
}
for (int i = 0; i < options.size(); i++) {
Object o = options.get(i);
if (o instanceof CmsSelectWidgetOption) {
CmsSelectWidgetOption option = (CmsSelectWidgetOption)o;
if (option.isDefault()) {
return option;
}
}
}
return null;
}
/**
* Returns a list of default options from the given list of select options.
*
* If an element found in the given list is not of type
* {@link CmsSelectWidgetOption}
, this is ignored.
*
* @param options the list of select options to get the default from
*
* @return a list of {@link CmsSelectWidgetOption}
objects
*/
public static List getDefaultOptions(List options) {
List defaults = new ArrayList();
if ((options == null) || (options.size() == 0)) {
return defaults;
}
for (int i = 0; i < options.size(); i++) {
Object o = options.get(i);
if (o instanceof CmsSelectWidgetOption) {
CmsSelectWidgetOption option = (CmsSelectWidgetOption)o;
if (option.isDefault()) {
defaults.add(option);
}
}
}
return defaults;
}
/**
* Parses a widget configuration String for select option values.
*
* If the input is null
or empty, a {@link Collections#EMPTY_LIST}
* is returned.
*
* Please note: No exception is thrown in case the input is malformed, all malformed entries are silently ignored.
*
* @param input the widget input string to parse
*
* @return a List of {@link CmsSelectWidgetOption}
elements
*/
public static List parseOptions(String input) {
if (CmsStringUtil.isEmptyOrWhitespaceOnly(input)) {
// default result for empty input
return Collections.emptyList();
}
// cut along the delimiter
String[] parts = splitOptions(input);
List result = new ArrayList(parts.length);
// indicates if a default of 'true' was already set in this result list
boolean foundDefault = false;
for (int i = 0; i < parts.length; i++) {
String part = parts[i].trim();
if (part.length() == 0) {
// skip empty parts
continue;
}
try {
part = part.replace("\\|", "|");
String value = null;
String option = null;
String help = null;
boolean isDefault = false;
int posValue = part.indexOf(KEY_VALUE);
int posDefault = part.indexOf(KEY_DEFAULT);
int posOption = part.indexOf(KEY_OPTION);
int posHelp = part.indexOf(KEY_HELP);
boolean shortValue = false;
if (posValue < 0) {
// shortcut syntax, value key must be at first position
if ((posDefault == 0) || (posOption == 0) || (posHelp == 0)) {
// malformed part - no value given
throw new CmsWidgetException(
Messages.get().container(Messages.ERR_MALFORMED_SELECT_OPTIONS_1, input));
}
posValue = 0;
shortValue = true;
}
// a 'value' must be always present
int end = part.length();
// check where the 'value' ends
if (posHelp > posValue) {
end = posHelp;
}
if ((posDefault > posValue) && (posDefault < end)) {
end = posDefault;
}
if ((posOption > posValue) && (posOption < end)) {
end = posOption;
}
if (shortValue) {
// no explicit setting using the key, value must be at the first position
value = part.substring(0, end).trim();
} else {
value = part.substring((posValue + KEY_VALUE.length()) - 1, end).trim();
// cut of trailing '
value = value.substring(1, value.length() - 1);
}
boolean shortOption = false;
// check if the option is appended using the ':' shortcut
if ((shortValue) && (posOption < 0)) {
int pos = value.indexOf(OPTION_DELIMITER);
if (pos >= 0) {
// shortcut syntax is used
posOption = pos;
shortOption = true;
value = value.substring(0, pos);
}
}
if (posDefault >= 0) {
// there was an explicit 'default' setting using the key, check where it ends
end = part.length();
if (posHelp > posDefault) {
end = posHelp;
}
if ((posOption > posDefault) && (posOption < end)) {
end = posOption;
}
if ((posValue > posDefault) && (posValue < end)) {
end = posValue;
}
String sub = part.substring(posDefault + KEY_DEFAULT.length(), end).trim();
// cut of trailing '
sub = sub.substring(0, sub.length() - 1);
isDefault = Boolean.valueOf(sub).booleanValue();
} else {
// check for shortcut syntax, value must end with a '*'
if ((value != null) && (value.charAt(value.length() - 1) == DEFAULT_MARKER)) {
isDefault = true;
value = value.substring(0, value.length() - 1);
}
}
if (posOption >= 0) {
// an 'option' setting is available, check where it ends
end = part.length();
if (posHelp > posOption) {
end = posHelp;
}
if ((posDefault > posOption) && (posDefault < end)) {
end = posDefault;
}
if ((posValue > posOption) && (posValue < end)) {
end = posValue;
}
if (shortOption) {
// shortcut syntax used for option with ':' appended to value
option = part.substring(posOption + 1, end).trim();
} else {
option = part.substring((posOption + KEY_OPTION.length()) - 1, end).trim();
// cut of trailing '
option = option.substring(1, option.length() - 1);
}
}
if (posHelp >= 0) {
// a 'help' setting is available, check where it ends
end = part.length();
if (posOption > posHelp) {
end = posOption;
}
if ((posDefault > posHelp) && (posDefault < end)) {
end = posDefault;
}
if ((posValue > posHelp) && (posValue < end)) {
end = posValue;
}
help = part.substring((posHelp + KEY_HELP.length()) - 1, end).trim();
// cut of trailing '
help = help.substring(1, help.length() - 1);
}
// check if there was already a 'true' default, if so all other entries are 'false'
if (foundDefault) {
isDefault = false;
} else if (isDefault) {
foundDefault = true;
}
result.add(new CmsSelectWidgetOption(value, isDefault, option, help));
} catch (Exception e) {
if (LOG.isInfoEnabled()) {
LOG.info(Messages.get().getBundle().key(Messages.ERR_MALFORMED_SELECT_OPTIONS_1, input));
}
}
}
return result;
}
/**
* Splits the options string at every unescaped input delimiter, i.e., every unescaped "|".
* @param input the options string
* @return the array with the various options
*/
public static String[] splitOptions(String input) {
//Note that we use a regex matching all "|" characters not prefixed by "\"
//Since we define a regex for matching, the input delimiter "|" needs to be escaped, as well as "\",
//which is even double-escaped - one escaping is due to the String, one due to the regex.
return input.split("(?
*
* @return the (optional) help text of this select option
*/
public String getHelp() {
return m_help;
}
/**
* Returns the option text of this select option.
*
* If this has not been set, the result of {@link #getValue()}
is returned,
* there will always be a result other than null
returned.
*
* @return the option text of this select option
*/
public String getOption() {
if (m_option == null) {
return getValue();
}
return m_option;
}
/**
* Returns the value of this select option.
*
* @return the value of this select option
*/
public String getValue() {
return m_value;
}
/**
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
if (m_hashcode == 0) {
StringBuffer hash = new StringBuffer(128);
hash.append(m_value);
hash.append('|');
hash.append(m_default);
hash.append('|');
hash.append(m_option);
hash.append('|');
hash.append(m_help);
m_hashcode = hash.toString().hashCode();
}
return m_hashcode;
}
/**
* Returns true
if this is the default value of the selection.
*
* @return true
if this is the default value of the selection
*/
public boolean isDefault() {
return m_default;
}
/**
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
StringBuffer result = new StringBuffer(128);
result.append(KEY_VALUE);
result.append(m_value);
result.append('\'');
if (m_default) {
result.append(' ');
result.append(KEY_DEFAULT);
result.append(m_default);
result.append('\'');
}
if (m_option != null) {
result.append(' ');
result.append(KEY_OPTION);
result.append(m_option);
result.append('\'');
}
if (m_help != null) {
result.append(' ');
result.append(KEY_HELP);
result.append(m_help);
result.append('\'');
}
return result.toString();
}
}