/*
This library is part of octools
Copyright (c) 2000-2007 Valtech A/S (http://www.valtech.dk)
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.
Alkacon OpenCms and the OpenCms logo are registered trademarks of
Alkacon Software GmbH in Germany, the USA and other countries
For further information about Alkacon Software GmbH, 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 dk.valtech.octools.tools;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.PageContext;
import org.apache.commons.logging.Log;
import org.opencms.file.CmsProperty;
import org.opencms.file.CmsPropertyDefinition;
import org.opencms.file.CmsResource;
import org.opencms.file.CmsResourceFilter;
import org.opencms.i18n.CmsEncoder;
import org.opencms.i18n.CmsMessages;
import org.opencms.jsp.CmsJspActionElement;
import org.opencms.main.CmsException;
import org.opencms.main.CmsLog;
import org.opencms.util.CmsStringUtil;
import org.opencms.workplace.I_CmsDialogHandler;
import org.opencms.workplace.commons.CmsPropertyCustom;
import org.opencms.workplace.commons.Messages;
import org.opencms.workplace.explorer.CmsNewResourceXmlPage;
import org.opencms.xml.CmsXmlException;
import org.opencms.xml.content.CmsXmlContent;
import org.opencms.xml.content.CmsXmlContentFactory;
/**
* This property dialog is shown specially by files using a template with the
* specified property "template.properties" that points to a valid
* xmlcontent-file that specifies the properties that should be edited for this
* template.
*
* @author Stefan Uldum Grinsted (stefan.grinsted@valtech.dk)
*/
public class FriendlyPropertyEditor extends CmsPropertyCustom implements I_CmsDialogHandler {
/** The log object for this class. */
private static final Log LOG = CmsLog.getLog(FriendlyPropertyEditor.class);
/** The module path. */
private static final String MODULE_PATH = "/system/modules/dk.valtech.octools/";
/** The path to the friendly property dialog */
private static final String URL_FRIENDLY_PROPERTY_DIALOG = MODULE_PATH + "dialogs/property.jsp";
/** The default parameter value. */
private static final String PARAM_DEFAULT = "";
/** The attribute name which stores the list of field-values */
private static final String ATTR_FIELDS = "__FriendlyPropertyEditor::FIELDS";
/**
* Default constructor needed for dialog handler implementation.<p>
*
* Do not use this constructor on JSP pages.<p>
*/
public FriendlyPropertyEditor() {
super(null);
}
/**
* Public constructor with JSP action element.<p>
*
* @param jsp an initialized JSP action element
*/
public FriendlyPropertyEditor(CmsJspActionElement jsp) {
super(jsp);
}
/**
* Public constructor with JSP variables.<p>
*
* @param context the JSP page context
* @param req the JSP request
* @param res the JSP response
*/
public FriendlyPropertyEditor(PageContext context, HttpServletRequest req, HttpServletResponse res) {
super(new CmsJspActionElement(context, req, res));
}
/*
*
* UTILITY FUNCTIONS
*
*/
private static class PropertyBean {
String name, value, title, type, config;
public PropertyBean(String name, String value, String title, String type, String config) {
super();
this.name = name;
this.value = value;
this.title = title;
this.type = type;
this.config = config;
}
}
private static class ListItem {
String value, caption;
boolean selected;
public ListItem(String value, String caption, boolean selected) {
super();
this.value = value;
this.caption = caption;
this.selected = selected;
}
}
/**
* Returns the property value by searching all parent folders.<p>
*
* @param propertydef the property definition
*
* @return the property value by searching all parent folders
*/
public String getDefault(String propertydef) {
try {
String parentFolder = CmsResource.getParentFolder(getParamResource());
CmsProperty property = getCms().readPropertyObject(parentFolder, propertydef, true);
String propertyValue = property.getValue();
if (!CmsStringUtil.isEmpty(propertyValue)) {
return property.getValue();
}
} catch (CmsException e) {
if (LOG.isErrorEnabled()) {
LOG.error(e);
}
}
return "";
}
/**
* @see org.opencms.workplace.I_CmsDialogHandler#getDialogUri(java.lang.String, CmsJspActionElement)
*/
public String getDialogUri(String resource, CmsJspActionElement jsp) {
String templatePropertiesUrl = getTemplatePropertiesUrl(resource, jsp);
if (templatePropertiesUrl != null) {
return URL_FRIENDLY_PROPERTY_DIALOG;
}
return super.getDialogUri(resource, jsp);
}
/**
* This figures out if the given resource has any custom properties defined and returns the url to the file if so.
*
* @param resource
* @param jsp
* @return
*/
private String getTemplatePropertiesUrl(String resource, CmsJspActionElement jsp) {
String templatePropertiesUrl = null;
String template = jsp.property("template", resource);
if (template == null) {
template = jsp.property("template-elements", resource);
}
if (template == null) {
// If no template, try and read the template.properties from the resource itself.
template = resource;
}
if (template != null && jsp.getCmsObject().existsResource(template)) {
try {
templatePropertiesUrl = jsp.getCmsObject().readPropertyObject(template, "template.properties", true).getValue();
if (templatePropertiesUrl != null && !jsp.getCmsObject().existsResource(templatePropertiesUrl)) {
templatePropertiesUrl = null;
}
} catch (CmsException e) {
LOG.error("Error trying to get the template.properties property from file " + resource, e);
}
}
return templatePropertiesUrl;
}
/**
* Returns the layout configuration files for the specified list type.<p>
*
* @param configFolder the folder to retrieve files from
* @return the layout configuration files from the specified folder
*/
@SuppressWarnings("unchecked")
private List<CmsResource> getConfigurationFiles(String configFolder) {
List<CmsResource> result = new ArrayList<CmsResource>();
try {
// first get the default layout files for the list type
result = getCms().readResources(configFolder, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED);
} catch (CmsException e) {
// error reading resources
if (LOG.isErrorEnabled()) {
LOG.error(e);
}
}
return result;
}
public boolean isNavigationPropertiesShown() {
boolean is = false;
try {
for (PropertyBean prop : getFields()) {
if (prop.name.equals(CmsPropertyDefinition.PROPERTY_NAVTEXT)) {
is = true;
break;
}
}
} catch (Exception e) {
LOG.warn("Unexpected error occured", e);
}
return is;
}
public List<PropertyBean> getFields() throws CmsXmlException, CmsException {
@SuppressWarnings("unchecked")
List<PropertyBean> fields = (List<PropertyBean>) getJsp().getRequest().getAttribute(ATTR_FIELDS);
if (fields == null) {
CmsXmlContent xmlC = CmsXmlContentFactory.unmarshal(getJsp().getCmsObject(), getJsp().getCmsObject().readFile(getTemplatePropertiesUrl(getParamResource(), getJsp())));
Locale l = (Locale) xmlC.getLocales().get(0);
XmlContentHelper xml = new XmlContentHelper(getJsp().getCmsObject(), xmlC, l);
int count = xmlC.getIndexCount("Property", l);
String name, titleKey, type, config;
fields = new ArrayList<PropertyBean>();
for (int i = 1; i <= count; i++) {
name = xml.getStringValue("Property["+i+"]/Name");
titleKey = xml.getStringValue("Property["+i+"]/TitleKey");
type = xml.getStringValue("Property["+i+"]/Type");
config = xml.getStringValue("Property["+i+"]/Configuration");
if ("Navigation".equals(type)) {
name = CmsPropertyDefinition.PROPERTY_NAVTEXT;
}
String localized = key(titleKey);
if (localized.startsWith(CmsMessages.UNKNOWN_KEY_EXTENSION)) {
localized = titleKey;
}
CmsProperty currentProperty = (CmsProperty)getActiveProperties().get(name);
String propValue = null;
if (currentProperty != null) {
propValue = currentProperty.getValue();
if (propValue != null) {
propValue = propValue.trim();
}
}
fields.add(new PropertyBean(name, propValue, localized, type, config));
}
getJsp().getRequest().setAttribute(ATTR_FIELDS, fields);
}
return fields;
}
/**
* Performs the editing of the resources properties.<p>
*
* @param request the HttpServletRequest
* @return true, if the properties were successfully changed, otherwise false
* @throws CmsException if editing is not successful
*/
protected boolean performEditOperation(HttpServletRequest request) throws CmsException {
@SuppressWarnings("unchecked")
List<CmsPropertyDefinition> propertyDef = getCms().readAllPropertyDefinitions();
boolean useTempfileProject = Boolean.valueOf(getParamUsetempfileproject()).booleanValue();
try {
if (useTempfileProject) {
switchToTempProject();
}
@SuppressWarnings("unchecked")
Map<String, CmsProperty> activeProperties = getPropertyMap(getCms().readPropertyObjects(getParamResource(), false));
String activeTab = getActiveTabName();
List<CmsProperty> propertiesToWrite = new ArrayList<CmsProperty>();
// check all property definitions of the resource for new values
Iterator<CmsPropertyDefinition> i = propertyDef.iterator();
while (i.hasNext()) {
CmsPropertyDefinition curPropDef = i.next();
String propName = CmsEncoder.escapeXml(curPropDef.getName());
String valueStructure = null;
String valueResource = null;
if (key(Messages.GUI_PROPERTIES_INDIVIDUAL_0).equals(activeTab)) {
// get parameters from the structure tab
valueStructure = request.getParameter(PREFIX_VALUE + propName);
valueResource = request.getParameter(PREFIX_RESOURCE + propName);
if (valueStructure != null
&& !"".equals(valueStructure.trim())
&& valueStructure.equals(valueResource)) {
// the resource value was shown/entered in input field, set structure value to empty String
valueStructure = "";
}
} else {
// get parameters from the resource tab
valueStructure = request.getParameter(PREFIX_STRUCTURE + propName);
valueResource = request.getParameter(PREFIX_VALUE + propName);
}
// check values for blanks and null
if (valueStructure != null) {
valueStructure = valueStructure.trim();
} else {
// This value was not part of the properties
continue;
}
if (valueResource != null) {
valueResource = valueResource.trim();
}
// create new CmsProperty object to store
CmsProperty newProperty = new CmsProperty();
newProperty.setName(curPropDef.getName());
newProperty.setStructureValue(valueStructure);
newProperty.setResourceValue(valueResource);
// get the old property values
CmsProperty oldProperty = activeProperties.get(curPropDef.getName());
if (oldProperty == null) {
// property was not set, create new empty property object
oldProperty = new CmsProperty();
oldProperty.setName(curPropDef.getName());
}
boolean writeStructureValue = false;
boolean writeResourceValue = false;
String oldValue = oldProperty.getStructureValue();
String newValue = newProperty.getStructureValue();
// write the structure value if the existing structure value is not null and we want to delete the structure value
writeStructureValue = (oldValue != null && newProperty.isDeleteStructureValue());
// or if we want to write a value which is neither the delete value or an empty value
writeStructureValue |= !newValue.equals(oldValue)
&& !"".equalsIgnoreCase(newValue)
&& !CmsProperty.DELETE_VALUE.equalsIgnoreCase(newValue);
// set the structure value explicitly to null to leave it as is in the database
if (!writeStructureValue) {
newProperty.setStructureValue(null);
}
oldValue = oldProperty.getResourceValue();
newValue = newProperty.getResourceValue();
// write the resource value if the existing resource value is not null and we want to delete the resource value
writeResourceValue = (oldValue != null && newProperty.isDeleteResourceValue());
// or if we want to write a value which is neither the delete value or an empty value
writeResourceValue |= CmsStringUtil.isNotEmpty(oldValue) && CmsStringUtil.isNotEmpty(newValue) && !newValue.equals(oldValue)
&& !CmsProperty.DELETE_VALUE.equalsIgnoreCase(newValue);
// set the resource value explicitly to null to leave it as is in the database
if (!writeResourceValue) {
newProperty.setResourceValue(null);
}
if (writeStructureValue || writeResourceValue) {
// add property to list only if property values have changed
propertiesToWrite.add(newProperty);
}
}
if (propertiesToWrite.size() > 0) {
// lock resource if autolock is enabled
checkLock(getParamResource());
//write the new property values
getCms().writePropertyObjects(getParamResource(), propertiesToWrite);
}
} finally {
if (useTempfileProject) {
switchToCurrentProject();
}
}
return true;
}
/*
*
*
* HTML BUILDING FUNCTIONS
*
*
*/
/**
* Creates the HTML String for the edit properties form.<p>
*
* @return the HTML output String for the edit properties form
*/
public String buildEditForm() {
CmsMessages messages = Messages.get().getBundle(getLocale());
StringBuffer result = new StringBuffer();
// check if the properties are editable
boolean editable = isEditable();
// create the column heads
result.append("<table border=\"0\">\n");
result.append("<tr>\n");
result.append("\t<td class=\"textbold\">");
result.append(messages.key(Messages.GUI_PROPERTY_0));
result.append("</td>\n");
result.append("\t<td class=\"textbold maxwidth\">");
result.append(key(Messages.GUI_PROPERTY_VALUE_0));
result.append("</td>\n");
result.append("\t<td class=\"textbold\" style=\"white-space: nowrap;\">");
result.append(key(Messages.GUI_PROPERTIES_ACTIVE_0)); // TODO Veryfy correct word.
result.append("</td>\n");
result.append("</tr>\n");
result.append("<tr><td colspan=\"3\"><span style=\"height: 6px;\"></span></td></tr>\n");
try {
List<PropertyBean> fields = getFields();
for (PropertyBean property : fields) {
if ("Text".equals(property.type) || "".equals(property.type) || property.type == null) {
result.append(buildPropertyEntry(property.name, property.title, editable));
} else if ("Navigation".equals(property.type)) {
result.append(buildNavigationProperties(editable));
} else if ("Checkbox".equals(property.type)) {
result.append(buildCheckBox(property.name, property.config, property.title));
} else if ("Select".equals(property.type)) {
result.append(buildPropertyResourcesSelectbox(property, editable));
} else if ("File".equals(property.type)) {
result.append(buildPropertySearchEntry(property.name, property.title, editable));
} else if ("Template".equals(property.type)) {
result.append(buildSelectTemplates(property));
}
}
} catch (CmsXmlException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (CmsException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
result.append("</table>");
return result.toString();
}
/**
* Builds the JavaScript to set the property form values delayed.<p>
*
* The values of the properties are not inserted directly in the <input> tag,
* because there is a display issue when the property values are very long.
* This method creates JavaScript to set the property input field values delayed.
* On the JSP, the code which is created from this method has to be executed delayed after
* the creation of the html form, e.g. in the <body> tag with the attribute
* onload="window.setTimeout('doSet()',50);".<p>
*
* @return the JavaScript to set the property form values delayed
*/
public String buildSetFormValues() {
StringBuffer result = new StringBuffer(1024);
try {
List<PropertyBean> fields = getFields();
for (PropertyBean prop : fields) {
if (prop.value != null) {
String propValue = CmsStringUtil.escapeJavaScript(prop.value);
// create the JS output for a single property
result.append("\tdocument.getElementById(\"");
result.append(PREFIX_VALUE);
result.append(prop.name);
result.append("\").value = \"");
result.append(propValue);
result.append("\";\n");
}
}
// check if the navigation text property value has to be added
if (showNavigation() && isNavigationPropertiesShown()) {
CmsProperty property = (CmsProperty)getActiveProperties().get(CmsPropertyDefinition.PROPERTY_NAVTEXT);
if (property != null) {
String propValue = property.getValue();
if (propValue != null) {
propValue = propValue.trim();
propValue = CmsStringUtil.escapeJavaScript(propValue);
// create the JS output for a single property
result.append("\tdocument.getElementById(\"");
result.append(PREFIX_VALUE);
result.append(CmsPropertyDefinition.PROPERTY_NAVTEXT);
result.append("\").value = \"");
result.append(propValue);
result.append("\";\n");
}
}
}
} catch (Exception e) {
LOG.warn("Uneapected error occured", e);
}
return result.toString();
}
/**
* Builds the html for the page template select box.<p>
*
* @param attributes optional attributes for the <select> tag
* @return the html for the page template select box
*/
@SuppressWarnings("unchecked")
public String buildSelectTemplates(PropertyBean property) {
List<ListItem> options = new ArrayList<ListItem>();
// List values = new ArrayList();
// int selectedValue = -1;
String currentTemplate = null;
TreeMap<String, String> templates = null;
try {
// read the current template
currentTemplate = property.value;
// get all available templates
templates = CmsNewResourceXmlPage.getTemplates(getCms(), getParamResource());
} catch (CmsException e) {
// ignore this exception
if (LOG.isInfoEnabled()) {
LOG.info(key(org.opencms.workplace.editors.Messages.LOG_READ_TEMPLATE_FAILED_0), e);
}
}
if (currentTemplate == null) {
currentTemplate = "";
}
if (templates == null) {
// no valid templated found, use only current one
addCurrentTemplate(currentTemplate, options);
} else {
boolean found = false;
// templates found, create option and value lists
Iterator<String> i = templates.keySet().iterator();
while (i.hasNext()) {
boolean selected = false;
String key = i.next();
String path = templates.get(key);
if (currentTemplate.equals(path)) {
found = selected = true;
}
options.add(new ListItem(path, key, selected));
}
if (!found) {
// current template was not found among module templates, add current template as option
addCurrentTemplate(currentTemplate, options);
}
}
return buildPropertySelectbox(property, isEditable(), false, options).toString();
}
/**
* Adds the currently selected template value to the option and value list.<p>
*
* @param currentTemplate the currently selected template to add
* @param options the option list
* @param values the value list
*/
private void addCurrentTemplate(String currentTemplate, List<ListItem> options) {
CmsMessages messages = Messages.get().getBundle(getLocale());
// template was not found in regular template folders, add current template value
if (CmsStringUtil.isEmpty(currentTemplate)) {
// current template not available, add "please select" value
String name = "--- " + messages.key(org.opencms.workplace.editors.Messages.GUI_PLEASE_SELECT_0) + " ---";
options.add(0, new ListItem(name, name, true));
} else {
// current template was set to some value, add this value to the selection
String name = null;
try {
// read the title of the current template
name = getCms().readPropertyObject(currentTemplate, CmsPropertyDefinition.PROPERTY_TITLE, false).getValue();
} catch (CmsException e) {
// ignore this exception - the title for this template was not readable
if (LOG.isInfoEnabled()) {
LOG.info(messages.key(org.opencms.workplace.editors.Messages.LOG_READ_TITLE_PROP_FAILED_1, currentTemplate), e);
}
}
if (name == null) {
name = currentTemplate;
}
options.add(0, new ListItem(currentTemplate, "* " + name, true));
}
}
/**
* Build the html for a property checkbox.<p>
*
* @param propertyName the property name
* @param propertyValue the property value
* @param propertyText the property text
*
* @return the html for a property checkbox
*/
public String buildCheckBox(String propertyName, String propertyValue, String propertyText) {
StringBuffer checkbox = new StringBuffer();
checkbox.append(buildTableRowStart(propertyText));
String checked = "";
if (getActiveProperties().containsKey(propertyName)) {
// the property is used, so create text field with checkbox and hidden field
CmsProperty currentProperty = (CmsProperty)getActiveProperties().get(propertyName);
String propValue = currentProperty.getValue();
if (propValue != null) {
propValue = propValue.trim();
}
propValue = CmsEncoder.escapeXml(propValue);
if (propertyValue.equals(propValue)) {
checked = " checked=\"checked\"";
}
} else {
// check radio if param value is the default
if (propertyValue.equals(PARAM_DEFAULT)) {
checked = " checked=\"checked\"";
}
}
checkbox.append("<input type=\"checkbox\" name=\"");
checkbox.append(PREFIX_VALUE);
checkbox.append(propertyName);
checkbox.append("\" value=\"");
checkbox.append(propertyValue);
checkbox.append("\"");
checkbox.append(checked);
checkbox.append(">");
checkbox.append(buildTableRowEnd());
return checkbox.toString();
}
/**
* Builds the html for a single search text input property row.<p>
*
* @param propertyName the name of the property
* @param propertyTitle the nice name of the property
* @param editable indicates if the properties are editable
* @return the html for a single text input property row
*/
private StringBuffer buildPropertySearchEntry(
String propertyName,
String propertyTitle,
boolean editable) {
StringBuffer result = new StringBuffer(256);
result.append(buildTableRowStart(propertyTitle));
String disabled = "";
if (!editable) {
disabled = " disabled=\"disabled\"";
}
String propValue = "";
// the property is used, so create text field with checkbox and hidden field
CmsProperty currentProperty = (CmsProperty)getActiveProperties().get(propertyName);
if (currentProperty != null) {
propValue = currentProperty.getValue();
if (!CmsStringUtil.isEmpty(propValue)) {
propValue = propValue.trim();
}
}
propValue = CmsEncoder.escapeXml(propValue);
result.append("<input type=\"text\" style=\"width: 99%\" class=\"maxwidth\" ");
result.append("name=\"");
result.append(PREFIX_VALUE);
result.append(propertyName);
result.append("\" id=\"");
result.append(PREFIX_VALUE);
result.append(propertyName);
result.append("\" value=\"");
result.append(propValue);
result.append("\"");
result.append(disabled);
result.append(">");
result.append("<input type=\"hidden\" name=\"");
result.append(PREFIX_HIDDEN);
result.append(propertyName);
result.append("\" id=\"");
result.append(PREFIX_HIDDEN);
result.append(propertyName);
result.append("\" value=\"");
result.append(propValue);
result.append("\">");
result.append("</td>\n");
result.append("<td>");
result.append("<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\">\n");
result.append("\t<tr>\n");
result.append("<td> </td>");
result.append("<td><a href=\"#\" onclick=\"javascript:top.openTreeWin('copy', true, 'main', '");
result.append(PREFIX_VALUE);
result.append(propertyName);
result.append("', document);\" class=\"button\" title=\"");
result.append(key(org.opencms.workplace.Messages.GUI_DIALOG_BUTTON_SEARCH_0));
result.append("\"><img class=\"button\" src=\"");
result.append(getSkinUri());
result.append("/buttons/folder.png\" border=\"0\"></a></td>");
result.append("</tr>\n");
result.append("</table>\n");
result.append("</td>\n");
result.append("</tr>");
return result;
}
/**
* Builds the html for a single selectbox property row to select the list layout.<p>
*
* @param configuration determines the contents of the list from files in the configuration folder
* @param propertyName the name of the property
* @param propertyTitle the nice name of the property
* @param editable indicates if the properties are editable
*
* @return the html for a single text input property row
*/
private StringBuffer buildPropertyResourcesSelectbox(
PropertyBean property,
boolean editable) {
String propValue = "";
// get property object from active properties
String inheritedValue = "";
if (property.value != null) {
// property value is directly set on resource
propValue = property.value;
inheritedValue = getDefault(property.name);
} else {
// property is not set on resource
propValue = getDefault(property.name);
if (CmsStringUtil.isEmptyOrWhitespaceOnly(propValue)) {
propValue = "";
}
inheritedValue = propValue;
}
List<CmsResource> resources = getConfigurationFiles(property.config);
List<ListItem> options = new ArrayList<ListItem>(resources.size() + 1);
// List<String> values = new ArrayList<String>(resources.size() + 1);
// int selectedIndex = 0;
for (int i = 0; i < resources.size(); i++) {
// loop all found resources defining the options
CmsResource res = resources.get(i);
String path = getCms().getSitePath(res);
// determine description to show for option
String description = "";
try {
description = getCms().readPropertyObject(path, CmsPropertyDefinition.PROPERTY_DESCRIPTION, false).getValue(
null);
if (CmsStringUtil.isEmpty(description)) {
description = getCms().readPropertyObject(path, CmsPropertyDefinition.PROPERTY_TITLE, false).getValue(
path);
}
} catch (CmsException e) {
// should never happen
if (LOG.isErrorEnabled()) {
LOG.error(e);
}
}
// try to find a localized key for the description property value
String localized = key(description);
if (localized.startsWith(CmsMessages.UNKNOWN_KEY_EXTENSION)) {
localized = description;
}
// check if this item is selected
boolean selected = false;
if (path.equals(propValue)) {
selected = true;
}
// determine value to add
if (path.equals(inheritedValue)) {
// the current path is like inherited path, so do not write property in this case
path = "";
}
options.add(new ListItem(path, localized, selected));
}
return buildPropertySelectbox(property, editable, false, options);
}
/**
* Builds the html for a single selectbox property row to select the list layout.<p>
*
* @param configuration determines the contents of the list from files in the configuration folder
* @param propertyName the name of the property
* @param propertyTitle the nice name of the property
* @param editable indicates if the properties are editable
*
* @return the html for a single text input property row
*/
private StringBuffer buildPropertySelectbox(
PropertyBean property,
boolean editable,
boolean multiple,
List<ListItem> options) {
StringBuffer result = new StringBuffer(128);
result.append(buildTableRowStart(property.title));
String disabled = "";
if (!editable) {
disabled = " disabled=\"disabled\"";
}
// create select tag attributes
StringBuffer attrs = new StringBuffer(4);
attrs.append("name=\"").append(PREFIX_VALUE).append(property.name).append("\"");
attrs.append(" class=\"maxwidth\"");
attrs.append(disabled);
if (multiple) {
attrs.append(" multiple=\"multiple\"");
}
List<String> optionCaptions = new ArrayList<String>(options.size());
List<String> values = new ArrayList<String>(options.size());
int selectedIndex = 0;
for (int n = 0; n < options.size(); n++) {
ListItem i = options.get(n);
optionCaptions.add(i.caption);
values.add(i.value);
if (i.selected) {
selectedIndex = n;
}
}
// create the select box
result.append(buildSelect(attrs.toString(), optionCaptions, values, selectedIndex));
// build the hidden field with old property value
result.append("<input type=\"hidden\" name=\"");
result.append(PREFIX_HIDDEN);
result.append(property.name);
result.append("\" id=\"");
result.append(PREFIX_HIDDEN);
result.append(property.name);
result.append("\" value=\"");
result.append(property.value);
result.append("\">");
result.append("</td>\n");
result.append("</tr>");
return result;
}
}