001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software GmbH & Co. KG, please see the
018 * company website: http://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: http://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.workplace.editors;
029
030import org.opencms.file.CmsPropertyDefinition;
031import org.opencms.i18n.CmsMessages;
032import org.opencms.jsp.CmsJspActionElement;
033import org.opencms.main.CmsException;
034import org.opencms.main.CmsLog;
035import org.opencms.util.CmsStringUtil;
036import org.opencms.workplace.commons.CmsPropertyCustom;
037import org.opencms.workplace.explorer.CmsNewResourceXmlPage;
038
039import java.util.ArrayList;
040import java.util.Iterator;
041import java.util.List;
042import java.util.Map.Entry;
043import java.util.TreeMap;
044
045import javax.servlet.http.HttpServletRequest;
046import javax.servlet.http.HttpServletResponse;
047import javax.servlet.jsp.PageContext;
048
049import org.apache.commons.logging.Log;
050
051/**
052 * Provides methods for the special xmlpage property dialog.<p>
053 *
054 * This is a special dialog that is used for xmlpages in the workplace and the editors.<p>
055 * Uses methods from the customized property dialog where possible.<p>
056 *
057 * The following files use this class:
058 * <ul>
059 * <li>/jsp/editors/dialogs/property.html
060 * </ul>
061 * <p>
062 *
063 * @since 6.0.0
064 */
065public class CmsDialogProperty extends CmsPropertyCustom {
066
067    /** The log object for this class. */
068    private static final Log LOG = CmsLog.getLog(CmsDialogProperty.class);
069
070    /** Flag indicating if the template property was changed. */
071    private boolean m_templateChanged;
072
073    /**
074     * Public constructor with JSP action element.<p>
075     *
076     * @param jsp an initialized JSP action element
077     */
078    public CmsDialogProperty(CmsJspActionElement jsp) {
079
080        super(jsp);
081    }
082
083    /**
084     * Public constructor with JSP variables.<p>
085     *
086     * @param context the JSP page context
087     * @param req the JSP request
088     * @param res the JSP response
089     */
090    public CmsDialogProperty(PageContext context, HttpServletRequest req, HttpServletResponse res) {
091
092        this(new CmsJspActionElement(context, req, res));
093    }
094
095    /**
096     * Creates the HTML String for the edit properties form.<p>
097     *
098     * @return the HTML output String for the edit properties form
099     */
100    @Override
101    public String buildEditForm() {
102
103        CmsMessages messages = Messages.get().getBundle(getLocale());
104        StringBuffer retValue = new StringBuffer(2048);
105
106        // check if the properties are editable
107        boolean editable = isEditable();
108        // create "disabled" attribute if properties are not editable
109        String disabled = "";
110        if (!editable) {
111            disabled = " disabled=\"disabled\"";
112        }
113
114        retValue.append("<table border=\"0\">\n");
115        retValue.append("<tr>\n");
116        retValue.append("\t<td class=\"textbold\">" + messages.key(Messages.GUI_INPUT_PROPERTY_0) + "</td>\n");
117        retValue.append("\t<td class=\"textbold\">" + messages.key(Messages.GUI_LABEL_VALUE_0) + "</td>\n");
118        retValue.append(
119            "\t<td class=\"textbold\" style=\"white-space: nowrap;\">"
120                + messages.key(Messages.GUI_INPUT_USEDPROPERTY_0)
121                + "</td>\n");
122        retValue.append("</tr>\n");
123        retValue.append("<tr><td><span style=\"height: 6px;\"></span></td></tr>\n");
124
125        // create template select box row
126        retValue.append(buildTableRowStart(messages.key(Messages.GUI_INPUT_TEMPLATE_0)));
127        retValue.append(
128            buildSelectTemplates(
129                "name=\"" + CmsPropertyDefinition.PROPERTY_TEMPLATE + "\" class=\"maxwidth noborder\"" + disabled));
130        retValue.append("</td>\n");
131        retValue.append("\t<td class=\"textcenter\">");
132        retValue.append("&nbsp;");
133        retValue.append(buildTableRowEnd());
134
135        // create the text property input rows
136        retValue.append(buildTextInput(editable));
137
138        // show navigation properties if enabled in explorer type settings
139        if (showNavigation()) {
140            retValue.append(buildNavigationProperties(editable));
141        }
142
143        retValue.append("</table>");
144
145        return retValue.toString();
146    }
147
148    /**
149     * Builds the html for the page template select box.<p>
150     *
151     * @param attributes optional attributes for the &lt;select&gt; tag
152     * @return the html for the page template select box
153     */
154    public String buildSelectTemplates(String attributes) {
155
156        List<String> options = new ArrayList<String>();
157        List<String> values = new ArrayList<String>();
158        int selectedValue = -1;
159        String currentTemplate = null;
160        TreeMap<String, String> templates = null;
161        try {
162            // read the current template
163            currentTemplate = getCms().readPropertyObject(
164                getParamResource(),
165                CmsPropertyDefinition.PROPERTY_TEMPLATE,
166                true).getValue();
167            // get all available templates
168            templates = CmsNewResourceXmlPage.getTemplates(getCms(), getParamResource());
169        } catch (CmsException e) {
170            // ignore this exception
171            if (LOG.isInfoEnabled()) {
172                LOG.info(Messages.get().getBundle().key(Messages.LOG_READ_TEMPLATE_FAILED_0), e);
173            }
174        }
175        if (currentTemplate == null) {
176            currentTemplate = "";
177        }
178        if (templates == null) {
179            // no valid template found, use only current one
180            addCurrentTemplate(currentTemplate, options, values);
181        } else {
182            boolean found = false;
183            // templates found, create option and value lists
184            Iterator<Entry<String, String>> i = templates.entrySet().iterator();
185            int counter = 0;
186            while (i.hasNext()) {
187                Entry<String, String> entry = i.next();
188                String key = entry.getKey();
189                String path = entry.getValue();
190                if (currentTemplate.equals(path)) {
191                    // mark the currently selected template
192                    selectedValue = counter;
193                    found = true;
194                }
195                options.add(key);
196                values.add(path);
197                counter++;
198            }
199            if (!found) {
200                // current template was not found among module templates, add current template as option
201                addCurrentTemplate(currentTemplate, options, values);
202                selectedValue = 0;
203            }
204        }
205
206        String hiddenField = "<input type=\"hidden\" name=\""
207            + PREFIX_HIDDEN
208            + CmsPropertyDefinition.PROPERTY_TEMPLATE
209            + "\" value=\""
210            + currentTemplate
211            + "\">";
212        return buildSelect(attributes, options, values, selectedValue, false) + hiddenField;
213    }
214
215    /**
216     * Returns if the template property was changed.<p>
217     *
218     * @return true if the template property was changed, otherwise false
219     */
220    public boolean hasTemplateChanged() {
221
222        return m_templateChanged;
223    }
224
225    /**
226     * Performs the editing of the resources properties.<p>
227     *
228     * @param request the HttpServletRequest
229     * @return true, if the properties were successfully changed, otherwise false
230     * @throws CmsException if editing is not successful
231     */
232    @Override
233    protected boolean performEditOperation(HttpServletRequest request) throws CmsException {
234
235        boolean useTempfileProject = Boolean.valueOf(getParamUsetempfileproject()).booleanValue();
236        try {
237            if (useTempfileProject) {
238                switchToTempProject();
239            }
240            // write the common properties defined in the explorer type settings
241            Iterator<String> i = getExplorerTypeSettings().getProperties().iterator();
242            // iterate over the properties
243            while (i.hasNext()) {
244                String curProperty = i.next();
245                String paramValue = request.getParameter(PREFIX_VALUE + curProperty);
246                String oldValue = request.getParameter(PREFIX_HIDDEN + curProperty);
247                writeProperty(curProperty, paramValue, oldValue);
248            }
249
250            // write special file properties
251            String paramValue = null;
252            String oldValue = null;
253
254            // write the navigation properties if enabled
255            if (showNavigation()) {
256                // get the navigation enabled parameter
257                paramValue = request.getParameter("enablenav");
258                if (Boolean.valueOf(paramValue).booleanValue()) {
259                    // navigation enabled, update params
260                    paramValue = request.getParameter("navpos");
261                    if (!"-1".equals(paramValue)) {
262                        // update the property only when it is different from "-1" (meaning no change)
263                        oldValue = request.getParameter(PREFIX_HIDDEN + CmsPropertyDefinition.PROPERTY_NAVPOS);
264                        writeProperty(CmsPropertyDefinition.PROPERTY_NAVPOS, paramValue, oldValue);
265                    }
266                    paramValue = request.getParameter(PREFIX_VALUE + CmsPropertyDefinition.PROPERTY_NAVTEXT);
267                    oldValue = request.getParameter(PREFIX_HIDDEN + CmsPropertyDefinition.PROPERTY_NAVTEXT);
268                    writeProperty(CmsPropertyDefinition.PROPERTY_NAVTEXT, paramValue, oldValue);
269                } else {
270                    // navigation disabled, delete property values
271                    writeProperty(CmsPropertyDefinition.PROPERTY_NAVPOS, null, null);
272                    writeProperty(CmsPropertyDefinition.PROPERTY_NAVTEXT, null, null);
273                }
274            }
275
276            // get the template parameter
277            paramValue = request.getParameter(CmsPropertyDefinition.PROPERTY_TEMPLATE);
278            oldValue = request.getParameter(PREFIX_HIDDEN + CmsPropertyDefinition.PROPERTY_TEMPLATE);
279            writeProperty(CmsPropertyDefinition.PROPERTY_TEMPLATE, paramValue, oldValue);
280            if ((paramValue != null) && !paramValue.equals(oldValue)) {
281                // template has changed, refresh editor window
282                m_templateChanged = true;
283            }
284
285        } finally {
286            if (useTempfileProject) {
287                switchToCurrentProject();
288            }
289        }
290        return true;
291    }
292
293    /**
294     * Adds the currently selected template value to the option and value list.<p>
295     *
296     * @param currentTemplate the currently selected template to add
297     * @param options the option list
298     * @param values the value list
299     */
300    private void addCurrentTemplate(String currentTemplate, List<String> options, List<String> values) {
301
302        CmsMessages messages = Messages.get().getBundle(getLocale());
303
304        // template was not found in regular template folders, add current template value
305        if (CmsStringUtil.isEmpty(currentTemplate)) {
306            // current template not available, add "please select" value
307            options.add(0, "--- " + messages.key(Messages.GUI_PLEASE_SELECT_0) + " ---");
308            values.add(0, "");
309        } else {
310            // current template was set to some value, add this value to the selection
311            String name = null;
312            try {
313                // read the title of the current template
314                name = getCms().readPropertyObject(
315                    currentTemplate,
316                    CmsPropertyDefinition.PROPERTY_TITLE,
317                    false).getValue();
318            } catch (CmsException e) {
319                // ignore this exception - the title for this template was not readable
320                if (LOG.isInfoEnabled()) {
321                    LOG.info(messages.key(Messages.LOG_READ_TITLE_PROP_FAILED_1, currentTemplate), e);
322                }
323            }
324            if (name == null) {
325                name = currentTemplate;
326            }
327            options.add(0, "* " + name);
328            values.add(0, currentTemplate);
329        }
330    }
331}