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.CmsFile; 031import org.opencms.file.CmsObject; 032import org.opencms.file.CmsPropertyDefinition; 033import org.opencms.file.CmsResource; 034import org.opencms.file.CmsResourceFilter; 035import org.opencms.i18n.CmsLocaleManager; 036import org.opencms.jsp.CmsJspActionElement; 037import org.opencms.main.CmsException; 038import org.opencms.main.CmsLog; 039import org.opencms.util.CmsStringUtil; 040import org.opencms.workplace.CmsDialog; 041import org.opencms.workplace.CmsWorkplaceSettings; 042import org.opencms.xml.page.CmsXmlPage; 043import org.opencms.xml.page.CmsXmlPageFactory; 044 045import java.util.ArrayList; 046import java.util.Collections; 047import java.util.Iterator; 048import java.util.List; 049import java.util.Locale; 050 051import javax.servlet.http.HttpServletRequest; 052import javax.servlet.http.HttpServletResponse; 053import javax.servlet.jsp.JspException; 054import javax.servlet.jsp.PageContext; 055 056import org.apache.commons.logging.Log; 057 058/** 059 * Provides methods for the editor elements dialog.<p> 060 * 061 * The following files use this class: 062 * <ul> 063 * <li>/jsp/editors/dialogs/elements.html 064 * </ul> 065 * <p> 066 * 067 * @since 6.0.0 068 */ 069public class CmsDialogElements extends CmsDialog { 070 071 /** Value for the action: update the elements of the page. */ 072 public static final int ACTION_UPDATE_ELEMENTS = 210; 073 074 /** The dialog type. */ 075 public static final String DIALOG_TYPE = "elementselector"; 076 077 /** Request parameter value for the action: update the elements of the page. */ 078 public static final String DIALOG_UPDATE_ELEMENTS = "updateelements"; 079 080 /** Prefix for the html input field for the body. */ 081 public static final String PREFIX_PARAM_BODY = "element-"; 082 083 /** The log object for this class. */ 084 private static final Log LOG = CmsLog.getLog(CmsDialogElements.class); 085 086 /** Stores the element to change to after an element update operation. */ 087 private String m_changeElement; 088 089 /** List used to store information of all possible elements of the page. */ 090 private List<CmsDialogElement> m_elementList; 091 092 /** The element locale. */ 093 private Locale m_elementLocale; 094 095 // Special parameters used by this dialog 096 /** The element language parameter. */ 097 private String m_paramElementlanguage; 098 099 /** The element name parameter. */ 100 private String m_paramElementname; 101 102 /** The temporary file parameter. */ 103 private String m_paramTempFile; 104 105 /** 106 * Public constructor.<p> 107 * 108 * @param jsp an initialized JSP action element 109 */ 110 public CmsDialogElements(CmsJspActionElement jsp) { 111 112 super(jsp); 113 m_changeElement = ""; 114 } 115 116 /** 117 * Public constructor with JSP variables.<p> 118 * 119 * @param context the JSP page context 120 * @param req the JSP request 121 * @param res the JSP response 122 */ 123 public CmsDialogElements(PageContext context, HttpServletRequest req, HttpServletResponse res) { 124 125 this(new CmsJspActionElement(context, req, res)); 126 m_changeElement = ""; 127 } 128 129 /** 130 * Creates a list of possible elements of a template from the template property "template-elements" 131 * and the elements available in the provided xmlPage.<p> 132 * 133 * @param cms the CmsObject 134 * @param xmlPage the resource to read the elements from 135 * @param xmlPageUri the URI of the resource to read the template property from 136 * @param locale the current element locale 137 * @return the list of elements in a String array with element name, nice name (if present) and mandatory flag 138 */ 139 public static List<CmsDialogElement> computeElements( 140 CmsObject cms, 141 CmsXmlPage xmlPage, 142 String xmlPageUri, 143 Locale locale) { 144 145 List<CmsDialogElement> result = new ArrayList<CmsDialogElement>(); 146 147 if (xmlPage != null) { 148 List<String> elementNames = xmlPage.getNames(locale); 149 150 Iterator<String> i = elementNames.iterator(); 151 while (i.hasNext()) { 152 String name = i.next(); 153 CmsDialogElement element = new CmsDialogElement(name, null, false, false, true); 154 result.add(element); 155 } 156 } 157 158 String currentTemplate = null; 159 try { 160 currentTemplate = cms.readPropertyObject( 161 xmlPageUri, 162 CmsPropertyDefinition.PROPERTY_TEMPLATE, 163 true).getValue(); 164 } catch (CmsException e) { 165 if (LOG.isWarnEnabled()) { 166 LOG.warn(e.getLocalizedMessage(), e); 167 } 168 } 169 if ((currentTemplate != null) && (currentTemplate.length() > 0)) { 170 // template found, check template-elements property 171 String elements = null; 172 try { 173 // read the property from the template file 174 elements = cms.readPropertyObject( 175 currentTemplate, 176 CmsPropertyDefinition.PROPERTY_TEMPLATE_ELEMENTS, 177 false).getValue(null); 178 } catch (CmsException e) { 179 if (LOG.isWarnEnabled()) { 180 LOG.warn(e.getLocalizedMessage(), e); 181 } 182 } 183 if (elements != null) { 184 // elements are defined on template file, merge with available elements 185 List<String> tokens = CmsStringUtil.splitAsList(elements, ',', true); 186 Iterator<String> it = tokens.iterator(); 187 while (it.hasNext()) { 188 String currentElement = it.next(); 189 String niceName = null; 190 boolean mandatory = false; 191 int sepIndex = currentElement.indexOf("|"); 192 if (sepIndex != -1) { 193 // nice name found for current element, extract it 194 niceName = currentElement.substring(sepIndex + 1); 195 currentElement = currentElement.substring(0, sepIndex); 196 } 197 if (currentElement.endsWith("*")) { 198 // element is mandatory 199 mandatory = true; 200 currentElement = currentElement.substring(0, currentElement.length() - 1); 201 } 202 203 CmsDialogElement element = new CmsDialogElement(currentElement, niceName, mandatory, true, false); 204 if (result.contains(element)) { 205 element.setExisting(true); 206 result.remove(element); 207 } 208 result.add(element); 209 } 210 } 211 } 212 213 Collections.sort(result); 214 return result; 215 } 216 217 /** 218 * Creates a list of possible elements of a template from the template property "template-elements" 219 * and the elements available in the provided resource file.<p> 220 * 221 * @param cms the CmsObject 222 * @param xmlPageUri the resource to read the elements from 223 * @param locale the current element locale 224 * @return the list of elements in a String array with element name, nice name (if present) and mandatory flag 225 */ 226 public static List<CmsDialogElement> computeElements(CmsObject cms, String xmlPageUri, Locale locale) { 227 228 CmsXmlPage page = null; 229 try { 230 // read the xmlpage file 231 CmsFile pageFile = cms.readFile(xmlPageUri, CmsResourceFilter.IGNORE_EXPIRATION); 232 page = CmsXmlPageFactory.unmarshal(cms, pageFile); 233 } catch (CmsException e) { 234 LOG.warn(Messages.get().getBundle().key(Messages.LOG_READ_XMLPAGE_FAILED_1, xmlPageUri), e); 235 // xmlpage will be null, only "template-elements" property on template will be checked 236 } 237 return computeElements(cms, page, xmlPageUri, locale); 238 } 239 240 /** 241 * Updates the enabled/diabled status of all elements of the current page.<p> 242 * 243 * @throws JspException if there is an error including the error page 244 */ 245 public void actionUpdateElements() throws JspException { 246 247 try { 248 List<CmsDialogElement> elementList = computeElements(); 249 CmsFile file = getCms().readFile(getParamTempfile(), CmsResourceFilter.IGNORE_EXPIRATION); 250 CmsXmlPage page = CmsXmlPageFactory.unmarshal(getCms(), file); 251 boolean foundMandatory = false; 252 m_changeElement = ""; 253 Iterator<CmsDialogElement> i = elementList.iterator(); 254 while (i.hasNext()) { 255 // get the current list element 256 CmsDialogElement element = i.next(); 257 if (element.isMandantory() 258 || element.getName().equals(getParamElementname()) 259 || Boolean.valueOf( 260 getJsp().getRequest().getParameter(PREFIX_PARAM_BODY + element.getName())).booleanValue()) { 261 if (!element.isExisting()) { 262 // create element in order to enable it properly 263 page.addValue(element.getName(), getElementLocale()); 264 } 265 page.setEnabled(element.getName(), getElementLocale(), true); 266 if (element.isMandantory() && !foundMandatory) { 267 m_changeElement = element.getName(); 268 foundMandatory = true; 269 } 270 } else { 271 if (element.isExisting()) { 272 // remove element if it is already existing 273 page.removeValue(element.getName(), getElementLocale()); 274 } 275 } 276 } 277 // write the temporary file 278 file.setContents(page.marshal()); 279 getCms().writeFile(file); 280 // set the javascript functions which should be executed 281 if (page.isEnabled(getParamElementname(), getElementLocale())) { 282 m_changeElement = getParamElementname(); 283 } else if (!foundMandatory) { 284 if (elementList.size() > 0) { 285 m_changeElement = elementList.get(0).getName(); 286 } 287 } 288 } catch (Throwable e) { 289 // show error dialog 290 setParamMessage(Messages.get().getBundle(getLocale()).key(Messages.ERR_UPDATE_ELEMENTS_0)); 291 includeErrorpage(this, e); 292 } 293 } 294 295 /** 296 * Builds the html String for a form list of all possible page elements.<p> 297 * 298 * @return the html String for a form list 299 */ 300 public String buildElementList() { 301 302 StringBuffer retValue = new StringBuffer(512); 303 retValue.append("<table border=\"0\">\n"); 304 retValue.append("<tr>\n"); 305 retValue.append( 306 "\t<td class=\"textbold\" unselectable=\"on\">" 307 + key(Messages.GUI_EDITOR_DIALOG_ELEMENTS_PAGEELEMENT_0) 308 + "</td>\n"); 309 retValue.append("\t<td class=\"textbold\" unselectable=\"on\"> " 310 + key(Messages.GUI_EDITOR_DIALOG_ELEMENTS_ENABLED_0) 311 + " </td>\n"); 312 retValue.append("</tr>\n"); 313 retValue.append("<tr><td colspan=\"2\"><span style=\"height: 6px;\"></span></td></tr>\n"); 314 315 try { 316 317 // get the list of all possible elements 318 List<CmsDialogElement> elementList = computeElements(); 319 320 // get all present bodies from the temporary file 321 CmsFile file = getCms().readFile(getParamTempfile(), CmsResourceFilter.IGNORE_EXPIRATION); 322 CmsXmlPage page = CmsXmlPageFactory.unmarshal(getCms(), file); 323 324 // show all possible elements 325 Iterator<CmsDialogElement> i = elementList.iterator(); 326 while (i.hasNext()) { 327 // get the current list element 328 CmsDialogElement element = i.next(); 329 // build an element row 330 retValue.append("<tr>\n"); 331 retValue.append("\t<td style=\"white-space: nowrap;\" unselectable=\"on\">" + element.getNiceName()); 332 retValue.append("</td>\n"); 333 retValue.append("\t<td class=\"textcenter\" unselectable=\"on\"><input type=\"checkbox\" name=\""); 334 retValue.append(PREFIX_PARAM_BODY); 335 retValue.append(element.getName()); 336 retValue.append("\" value=\"true\""); 337 338 if ((!page.hasValue(element.getName(), getElementLocale()) && element.isMandantory()) 339 || page.isEnabled(element.getName(), getElementLocale())) { 340 retValue.append(" checked=\"checked\""); 341 } 342 if (element.isMandantory() || element.getName().equals(getParamElementname())) { 343 retValue.append(" disabled=\"disabled\""); 344 } 345 retValue.append(">"); 346 retValue.append("<script >registerElement(\""); 347 348 retValue.append(element.getName()); 349 retValue.append("\", "); 350 retValue.append(page.isEnabled(element.getName(), getElementLocale())); 351 retValue.append(");</script>"); 352 353 retValue.append("</td>\n"); 354 retValue.append("</tr>\n"); 355 } 356 357 } catch (CmsException e) { 358 // should usually never happen 359 if (LOG.isInfoEnabled()) { 360 LOG.info(e.getLocalizedMessage(), e); 361 } 362 } 363 364 retValue.append("</table>\n"); 365 return retValue.toString(); 366 } 367 368 /** 369 * Creates a list of possible elements of a template from the template property "template-elements".<p> 370 * 371 * @return the list of elements in a String array with element name, nice name (if present) and mandatory flag 372 */ 373 public List<CmsDialogElement> computeElements() { 374 375 if (m_elementList == null) { 376 m_elementList = computeElements(getCms(), getParamTempfile(), getElementLocale()); 377 } 378 return m_elementList; 379 } 380 381 /** 382 * Returns the element name that has to be changed.<p> 383 * 384 * @return the element name that has to be changed 385 */ 386 public String getChangeElement() { 387 388 return m_changeElement; 389 } 390 391 /** 392 * Returns the current element locale.<p> 393 * 394 * @return the current element locale 395 */ 396 public Locale getElementLocale() { 397 398 if (m_elementLocale == null) { 399 m_elementLocale = CmsLocaleManager.getLocale(getParamElementlanguage()); 400 } 401 return m_elementLocale; 402 } 403 404 /** 405 * Returns the current element language.<p> 406 * 407 * @return the current element language 408 */ 409 public String getParamElementlanguage() { 410 411 return m_paramElementlanguage; 412 } 413 414 /** 415 * Returns the current element name.<p> 416 * 417 * @return the current element name 418 */ 419 public String getParamElementname() { 420 421 return m_paramElementname; 422 } 423 424 /** 425 * Returns the name of the temporary file.<p> 426 * 427 * @return the name of the temporary file 428 */ 429 public String getParamTempfile() { 430 431 return m_paramTempFile; 432 } 433 434 /** 435 * Sets the current element language.<p> 436 * 437 * @param elementLanguage the current element language 438 */ 439 public void setParamElementlanguage(String elementLanguage) { 440 441 m_paramElementlanguage = elementLanguage; 442 } 443 444 /** 445 * Sets the current element name.<p> 446 * 447 * @param elementName the current element name 448 */ 449 public void setParamElementname(String elementName) { 450 451 m_paramElementname = elementName; 452 } 453 454 /** 455 * Sets the name of the temporary file.<p> 456 * 457 * @param fileName the name of the temporary file 458 */ 459 public void setParamTempfile(String fileName) { 460 461 m_paramTempFile = fileName; 462 } 463 464 /** 465 * @see org.opencms.workplace.CmsWorkplace#initWorkplaceRequestValues(org.opencms.workplace.CmsWorkplaceSettings, javax.servlet.http.HttpServletRequest) 466 */ 467 @Override 468 protected void initWorkplaceRequestValues(CmsWorkplaceSettings settings, HttpServletRequest request) { 469 470 // fill the parameter values in the get/set methods 471 fillParamValues(request); 472 // set the dialog type 473 setParamDialogtype(DIALOG_TYPE); 474 // set the action for the JSP switch 475 if (DIALOG_UPDATE_ELEMENTS.equals(getParamAction())) { 476 setAction(ACTION_UPDATE_ELEMENTS); 477 } else { 478 setAction(ACTION_DEFAULT); 479 // build title for delete dialog 480 setParamTitle(key( 481 Messages.GUI_EDITOR_DIALOG_ELEMENTS_TITLE_1, 482 new Object[] {CmsResource.getName(getParamResource())})); 483 } 484 } 485}