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; 029 030import org.opencms.i18n.CmsEncoder; 031import org.opencms.jsp.CmsJspActionElement; 032import org.opencms.main.CmsLog; 033import org.opencms.main.I_CmsThrowable; 034import org.opencms.main.OpenCms; 035import org.opencms.util.CmsRequestUtil; 036import org.opencms.util.CmsStringUtil; 037import org.opencms.widgets.A_CmsWidget; 038import org.opencms.widgets.CmsDisplayWidget; 039import org.opencms.widgets.I_CmsWidget; 040import org.opencms.widgets.I_CmsWidgetDialog; 041 042import java.io.IOException; 043import java.util.ArrayList; 044import java.util.Arrays; 045import java.util.HashMap; 046import java.util.HashSet; 047import java.util.Hashtable; 048import java.util.Iterator; 049import java.util.List; 050import java.util.Map; 051import java.util.Set; 052 053import javax.servlet.ServletException; 054import javax.servlet.http.HttpServletRequest; 055import javax.servlet.http.HttpServletResponse; 056import javax.servlet.jsp.JspException; 057import javax.servlet.jsp.JspWriter; 058import javax.servlet.jsp.PageContext; 059 060import org.apache.commons.logging.Log; 061 062/** 063 * Base class for dialogs that use the OpenCms widgets without XML content.<p> 064 * 065 * @since 6.0.0 066 */ 067public abstract class CmsWidgetDialog extends CmsDialog implements I_CmsWidgetDialog { 068 069 /** Action for optional element creation. */ 070 public static final int ACTION_ELEMENT_ADD = 152; 071 072 /** Action for optional element removal. */ 073 public static final int ACTION_ELEMENT_REMOVE = 153; 074 075 /** Value for the action: error in the form validation. */ 076 public static final int ACTION_ERROR = 303; 077 078 /** Value for the action: save the dialog. */ 079 public static final int ACTION_SAVE = 300; 080 081 /** Request parameter value for the action: save the dialog. */ 082 public static final String DIALOG_SAVE = "save"; 083 084 /** Indicates an optional element should be created. */ 085 public static final String EDITOR_ACTION_ELEMENT_ADD = "addelement"; 086 087 /** Indicates an optional element should be removed. */ 088 public static final String EDITOR_ACTION_ELEMENT_REMOVE = "removeelement"; 089 090 /** Prefix for "hidden" parameters, required since these must be unescaped later. */ 091 public static final String HIDDEN_PARAM_PREFIX = "hidden."; 092 093 /** The log object for this class. */ 094 private static final Log LOG = CmsLog.getLog(CmsWidgetDialog.class); 095 096 /** The errors thrown by commit actions. */ 097 protected List<Throwable> m_commitErrors; 098 099 /** The object edited with this widget dialog. */ 100 protected Object m_dialogObject; 101 102 /** The allowed pages for this dialog in a List. */ 103 protected List<String> m_pages; 104 105 /** Controls which page is currently displayed in the dialog. */ 106 protected String m_paramPage; 107 108 /** The validation errors for the input form. */ 109 protected List<Throwable> m_validationErrorList; 110 111 /** Contains all parameter value of this dialog. */ 112 protected Map<String, List<CmsWidgetDialogParameter>> m_widgetParamValues; 113 114 /** The list of widgets used on the dialog. */ 115 protected List<CmsWidgetDialogParameter> m_widgets; 116 117 /** The set of help message ids that have already been used. */ 118 private Set<String> m_helpMessageIds; 119 120 /** 121 * Parameter stores the index of the element to add or remove.<p> 122 * 123 * This must not be <code>null</code>, because it must be available 124 * when calling <code>{@link org.opencms.workplace.CmsWorkplace#paramsAsHidden()}</code>.<p> 125 */ 126 private String m_paramElementIndex = "0"; 127 128 /** 129 * Parameter stores the name of the element to add or remove.<p> 130 * 131 * This must not be <code>null</code>, because it must be available 132 * when calling <code>{@link org.opencms.workplace.CmsWorkplace#paramsAsHidden()}</code>.<p> 133 */ 134 private String m_paramElementName = "undefined"; 135 136 /** Optional localized key prefix identificator. */ 137 private String m_prefix; 138 139 /** 140 * Public constructor with JSP action element.<p> 141 * 142 * @param jsp an initialized JSP action element 143 */ 144 public CmsWidgetDialog(CmsJspActionElement jsp) { 145 146 super(jsp); 147 } 148 149 /** 150 * Public constructor with JSP variables.<p> 151 * 152 * @param context the JSP page context 153 * @param req the JSP request 154 * @param res the JSP response 155 */ 156 public CmsWidgetDialog(PageContext context, HttpServletRequest req, HttpServletResponse res) { 157 158 this(new CmsJspActionElement(context, req, res)); 159 } 160 161 /** 162 * Deletes the edited dialog object from the session.<p> 163 */ 164 public void actionCancel() { 165 166 clearDialogObject(); 167 } 168 169 /** 170 * Commits the edited object after pressing the "OK" button.<p> 171 * 172 * @throws IOException in case of errors forwarding to the required result page 173 * @throws ServletException in case of errors forwarding to the required result page 174 */ 175 public abstract void actionCommit() throws IOException, ServletException; 176 177 /** 178 * Adds or removes an optional element.<p> 179 * 180 * Depends on the value stored in the <code>{@link CmsDialog#getAction()}</code> method.<p> 181 */ 182 public void actionToggleElement() { 183 184 // get the necessary parameters to add/remove the element 185 int index = 0; 186 try { 187 index = Integer.parseInt(getParamElementIndex()); 188 } catch (Exception e) { 189 // ignore, should not happen 190 } 191 String name = getParamElementName(); 192 // get the base parameter definition 193 CmsWidgetDialogParameter base = getParameterDefinition(name); 194 if (base != null) { 195 // the requested parameter is valid for this dialog 196 List<CmsWidgetDialogParameter> params = getParameters().get(name); 197 if (getAction() == ACTION_ELEMENT_REMOVE) { 198 // remove the value 199 params.remove(index); 200 } else { 201 List<CmsWidgetDialogParameter> sequence = getParameters().get(base.getName()); 202 if (sequence.size() > 0) { 203 // add the new value after the clicked element 204 index = index + 1; 205 } 206 CmsWidgetDialogParameter newParam = new CmsWidgetDialogParameter(base, index); 207 params.add(index, newParam); 208 } 209 // reset all index value in the parameter list 210 for (int i = 0; i < params.size(); i++) { 211 CmsWidgetDialogParameter param = params.get(i); 212 param.setindex(i); 213 } 214 } 215 } 216 217 /** 218 * Returns the html for a button to add an optional element.<p> 219 * 220 * @param elementName name of the element 221 * @param insertAfter the index of the element after which the new element should be created 222 * @param enabled if true, the button to add an element is shown, otherwise a spacer is returned 223 * @return the html for a button to add an optional element 224 */ 225 public String buildAddElement(String elementName, int insertAfter, boolean enabled) { 226 227 if (enabled) { 228 StringBuffer href = new StringBuffer(4); 229 href.append("javascript:addElement('"); 230 href.append(elementName); 231 href.append("', "); 232 href.append(insertAfter); 233 href.append(");"); 234 return button(href.toString(), null, "new.png", Messages.GUI_DIALOG_BUTTON_ADDNEW_0, 0); 235 } else { 236 return ""; 237 } 238 } 239 240 /** 241 * Builds the HTML for the dialog form.<p> 242 * 243 * @return the HTML for the dialog form 244 */ 245 public String buildDialogForm() { 246 247 // create the dialog HTML 248 return createDialogHtml(getParamPage()); 249 } 250 251 /** 252 * Returns the html for a button to remove an optional element.<p> 253 * 254 * @param elementName name of the element 255 * @param index the element index of the element to remove 256 * @param enabled if true, the button to remove an element is shown, otherwise a spacer is returned 257 * @return the html for a button to remove an optional element 258 */ 259 public String buildRemoveElement(String elementName, int index, boolean enabled) { 260 261 if (enabled) { 262 StringBuffer href = new StringBuffer(4); 263 href.append("javascript:removeElement('"); 264 href.append(elementName); 265 href.append("', "); 266 href.append(index); 267 href.append(");"); 268 return button(href.toString(), null, "deletecontent.png", Messages.GUI_DIALOG_BUTTON_DELETE_0, 0); 269 } else { 270 return ""; 271 } 272 } 273 274 /** 275 * Clears the "dialog object" for this widget dialog by removing it from the current users session.<p> 276 */ 277 public void clearDialogObject() { 278 279 setDialogObject(null); 280 } 281 282 /** 283 * Builds the end HTML for a block with 3D border in the dialog content area.<p> 284 * 285 * @return 3D block start / end segment 286 */ 287 @Override 288 public String dialogBlockEnd() { 289 290 StringBuffer result = new StringBuffer(8); 291 result.append(super.dialogBlockEnd()); 292 result.append(dialogSpacer()); 293 result.append("</td></tr>\n"); 294 return result.toString(); 295 } 296 297 /** 298 * Builds the start HTML for a block with 3D border and optional subheadline in the dialog content area.<p> 299 * 300 * @param headline the headline String for the block 301 * @return 3D block start / end segment 302 */ 303 @Override 304 public String dialogBlockStart(String headline) { 305 306 StringBuffer result = new StringBuffer(8); 307 result.append("<tr><td colspan=\"5\">\n"); 308 result.append(super.dialogBlockStart(headline)); 309 return result.toString(); 310 } 311 312 /** 313 * Creates the HTML for the buttons on the dialog.<p> 314 * 315 * @return the HTML for the buttons on the dialog.<p> 316 */ 317 public String dialogButtonsCustom() { 318 319 if (getPages().size() > 1) { 320 // this is a multi page dialog, create buttons according to current page 321 int pageIndex = getPages().indexOf(getParamPage()); 322 if (pageIndex == (getPages().size() - 1)) { 323 // this is the last dialog page 324 return dialogButtons(new int[] {BUTTON_OK, BUTTON_BACK, BUTTON_CANCEL}, new String[3]); 325 } else if (pageIndex > 0) { 326 // this is a dialog page between first and last page 327 return dialogButtons(new int[] {BUTTON_BACK, BUTTON_CONTINUE, BUTTON_CANCEL}, new String[3]); 328 } else { 329 // this is the first dialog page 330 return dialogButtons(new int[] {BUTTON_CONTINUE, BUTTON_CANCEL}, new String[2]); 331 } 332 } 333 boolean onlyDisplay = true; 334 Iterator<CmsWidgetDialogParameter> it = getWidgets().iterator(); 335 while (it.hasNext()) { 336 CmsWidgetDialogParameter wdp = it.next(); 337 if (!(wdp.getWidget() instanceof CmsDisplayWidget)) { 338 onlyDisplay = false; 339 break; 340 } 341 } 342 if (!onlyDisplay) { 343 // this is a single page dialog, create common buttons 344 return dialogButtons(new int[] {BUTTON_OK, BUTTON_CANCEL}, new String[2]); 345 } 346 // this is a display only dialog 347 return ""; 348 } 349 350 /** 351 * Performs the dialog actions depending on the initialized action and displays the dialog form.<p> 352 * 353 * @throws JspException if dialog actions fail 354 * @throws IOException if writing to the JSP out fails, or in case of errors forwarding to the required result page 355 * @throws ServletException in case of errors forwarding to the required result page 356 */ 357 public void displayDialog() throws JspException, IOException, ServletException { 358 359 displayDialog(false); 360 } 361 362 /** 363 * Performs the dialog actions depending on the initialized action and displays the dialog form if needed.<p> 364 * 365 * @param writeLater if <code>true</code> no output is written, 366 * you have to call manually the <code>{@link #defaultActionHtml()}</code> method. 367 * 368 * @throws JspException if dialog actions fail 369 * @throws IOException if writing to the JSP out fails, or in case of errors forwarding to the required result page 370 * @throws ServletException in case of errors forwarding to the required result page 371 */ 372 public void displayDialog(boolean writeLater) throws JspException, IOException, ServletException { 373 374 if (isForwarded()) { 375 return; 376 } 377 switch (getAction()) { 378 379 case ACTION_CANCEL: 380 // ACTION: cancel button pressed 381 actionCancel(); 382 actionCloseDialog(); 383 break; 384 385 case ACTION_ERROR: 386 // ACTION: an error occurred (display nothing) 387 break; 388 389 case ACTION_SAVE: 390 // ACTION: save edited values 391 setParamAction(DIALOG_OK); 392 actionCommit(); 393 if (closeDialogOnCommit()) { 394 setAction(ACTION_CANCEL); 395 actionCloseDialog(); 396 break; 397 } 398 setAction(ACTION_DEFAULT); 399 400 //$FALL-THROUGH$ 401 case ACTION_DEFAULT: 402 default: 403 // ACTION: show dialog (default) 404 if (!writeLater) { 405 writeDialog(); 406 } 407 } 408 } 409 410 /** 411 * @see org.opencms.widgets.I_CmsWidgetDialog#getButtonStyle() 412 */ 413 public int getButtonStyle() { 414 415 return getSettings().getUserSettings().getEditorButtonStyle(); 416 } 417 418 /** 419 * Returns the errors that are thrown by save actions or form generation.<p> 420 * 421 * @return the errors that are thrown by save actions or form generation 422 */ 423 public List<Throwable> getCommitErrors() { 424 425 return m_commitErrors; 426 } 427 428 /** 429 * Returns the dialog object for this widget dialog, or <code>null</code> 430 * if no dialog object has been set.<p> 431 * 432 * @return the dialog object for this widget dialog, or <code>null</code> 433 */ 434 public Object getDialogObject() { 435 436 if (m_dialogObject == null) { 437 m_dialogObject = getDialogObjectMap().get(getClass().getName()); 438 } 439 return m_dialogObject; 440 } 441 442 /** 443 * @see org.opencms.widgets.I_CmsWidgetDialog#getHelpMessageIds() 444 */ 445 public Set<String> getHelpMessageIds() { 446 447 if (m_helpMessageIds == null) { 448 m_helpMessageIds = new HashSet<String>(); 449 } 450 return m_helpMessageIds; 451 } 452 453 /** 454 * Returns the index of the element to add or remove.<p> 455 * 456 * @return the index of the element to add or remove 457 */ 458 public String getParamElementIndex() { 459 460 return m_paramElementIndex; 461 } 462 463 /** 464 * Returns the name of the element to add or remove.<p> 465 * 466 * @return the name of the element to add or remove 467 */ 468 public String getParamElementName() { 469 470 return m_paramElementName; 471 } 472 473 /** 474 * Returns the page parameter.<p> 475 * 476 * @return the page parameter 477 */ 478 public String getParamPage() { 479 480 return m_paramPage; 481 } 482 483 /** 484 * Returns the value of the widget parameter with the given name, or <code>null</code> 485 * if no such widget parameter is available.<p> 486 * 487 * @param name the widget parameter name to get the value for 488 * 489 * @return the value of the widget parameter with the given name 490 */ 491 public String getParamValue(String name) { 492 493 return getParamValue(name, 0); 494 } 495 496 /** 497 * Returns the value of the widget parameter with the given name and index, or <code>null</code> 498 * if no such widget parameter is available.<p> 499 * 500 * @param name the widget parameter name to get the value for 501 * @param index the widget parameter index 502 * 503 * @return the value of the widget parameter with the given name and index 504 */ 505 public String getParamValue(String name, int index) { 506 507 List<CmsWidgetDialogParameter> params = m_widgetParamValues.get(name); 508 if (params != null) { 509 if ((index >= 0) && (index < params.size())) { 510 CmsWidgetDialogParameter param = params.get(index); 511 if (param.getId().equals(CmsWidgetDialogParameter.createId(name, index))) { 512 return param.getStringValue(getCms()); 513 } 514 } 515 } 516 517 return null; 518 } 519 520 /** 521 * @see org.opencms.widgets.I_CmsWidgetDialog#getUserAgent() 522 */ 523 public String getUserAgent() { 524 525 return getJsp().getRequest().getHeader(CmsRequestUtil.HEADER_USER_AGENT); 526 } 527 528 /** 529 * Generates the HTML for the end of the widget dialog.<p> 530 * 531 * This HTML includes additional components, for example the <div> 532 * tags containing the help texts.<p> 533 * 534 * @return the HTML for the end of the widget dialog 535 */ 536 public String getWidgetHtmlEnd() { 537 538 StringBuffer result = new StringBuffer(32); 539 // iterate over unique widgets from collector 540 Iterator<CmsWidgetDialogParameter> i = getWidgets().iterator(); 541 while (i.hasNext()) { 542 CmsWidgetDialogParameter param = i.next(); 543 result.append(param.getWidget().getDialogHtmlEnd(getCms(), this, param)); 544 } 545 return result.toString(); 546 } 547 548 /** 549 * Generates the HTML include tags for external JavaScripts files of the used widgets.<p> 550 * 551 * @return the HTML include tags for external JavaScripts files of the used widgets 552 * 553 * @throws JspException if an error occurs during JavaScript generation 554 */ 555 public String getWidgetIncludes() throws JspException { 556 557 StringBuffer result = new StringBuffer(32); 558 try { 559 // iterate over unique widgets from collector 560 Iterator<CmsWidgetDialogParameter> i = getWidgets().iterator(); 561 Set<I_CmsWidget> set = new HashSet<I_CmsWidget>(); 562 while (i.hasNext()) { 563 I_CmsWidget widget = i.next().getWidget(); 564 if (!set.contains(widget)) { 565 result.append(widget.getDialogIncludes(getCms(), this)); 566 result.append('\n'); 567 set.add(widget); 568 } 569 } 570 } catch (Throwable e) { 571 572 includeErrorpage(this, e); 573 } 574 return result.toString(); 575 } 576 577 /** 578 * Generates the JavaScript init calls for the used widgets.<p> 579 * 580 * @return the JavaScript init calls for the used widgets 581 * 582 * @throws JspException the JavaScript init calls for the used widgets 583 */ 584 public String getWidgetInitCalls() throws JspException { 585 586 StringBuffer result = new StringBuffer(32); 587 try { 588 // iterate over unique widgets from collector 589 Iterator<CmsWidgetDialogParameter> i = getWidgets().iterator(); 590 Set<I_CmsWidget> set = new HashSet<I_CmsWidget>(); 591 while (i.hasNext()) { 592 I_CmsWidget widget = i.next().getWidget(); 593 if (!set.contains(widget)) { 594 result.append(widget.getDialogInitCall(getCms(), this)); 595 set.add(widget); 596 } 597 } 598 } catch (Throwable e) { 599 includeErrorpage(this, e); 600 } 601 return result.toString(); 602 } 603 604 /** 605 * Generates the JavaScript initialization methods for the used widgets.<p> 606 * 607 * @return the JavaScript initialization methods for the used widgets 608 * 609 * @throws JspException if an error occurs during JavaScript generation 610 */ 611 public String getWidgetInitMethods() throws JspException { 612 613 StringBuffer result = new StringBuffer(32); 614 try { 615 // iterate over unique widgets from collector 616 Iterator<CmsWidgetDialogParameter> i = getWidgets().iterator(); 617 Set<I_CmsWidget> set = new HashSet<I_CmsWidget>(); 618 while (i.hasNext()) { 619 I_CmsWidget widget = i.next().getWidget(); 620 if (!set.contains(widget)) { 621 result.append(widget.getDialogInitMethod(getCms(), this)); 622 set.add(widget); 623 } 624 } 625 } catch (Throwable e) { 626 includeErrorpage(this, e); 627 } 628 return result.toString(); 629 } 630 631 /** 632 * @see org.opencms.workplace.CmsWorkplace#paramsAsHidden() 633 */ 634 @Override 635 public String paramsAsHidden() { 636 637 if (getAction() != ACTION_ERROR) { 638 return super.paramsAsHidden(); 639 } 640 // on an error page, also output the widget parameters 641 StringBuffer result = new StringBuffer(); 642 result.append(super.paramsAsHidden()); 643 result.append('\n'); 644 result.append(widgetParamsAsHidden()); 645 return result.toString(); 646 } 647 648 /** 649 * Stores the given object as "dialog object" for this widget dialog in the current users session.<p> 650 * 651 * @param dialogObject the object to store 652 */ 653 public void setDialogObject(Object dialogObject) { 654 655 m_dialogObject = dialogObject; 656 if (dialogObject == null) { 657 // null object: remove the entry from the map 658 getDialogObjectMap().remove(getClass().getName()); 659 } else { 660 getDialogObjectMap().put(getClass().getName(), dialogObject); 661 } 662 } 663 664 /** 665 * Sets the index of the element to add or remove.<p> 666 * 667 * @param elementIndex the index of the element to add or remove 668 */ 669 public void setParamElementIndex(String elementIndex) { 670 671 m_paramElementIndex = elementIndex; 672 } 673 674 /** 675 * Sets the name of the element to add or remove.<p> 676 * 677 * @param elementName the name of the element to add or remove 678 */ 679 public void setParamElementName(String elementName) { 680 681 m_paramElementName = elementName; 682 } 683 684 /** 685 * Sets the page parameter.<p> 686 * 687 * @param paramPage the page parameter to set 688 */ 689 public void setParamPage(String paramPage) { 690 691 m_paramPage = paramPage; 692 } 693 694 /** 695 * Returns the values of all widget parameters of this dialog as HTML hidden fields.<p> 696 * 697 * @return the values of all widget parameters of this dialog as HTML hidden fields 698 * 699 * @see org.opencms.workplace.CmsWorkplace#paramsAsHidden() 700 */ 701 public String widgetParamsAsHidden() { 702 703 return widgetParamsAsHidden(null); 704 } 705 706 /** 707 * Returns the values of all widget parameters of this dialog as HTML hidden fields, 708 * excluding the widget values that are on the given dialog page.<p> 709 * 710 * This can be used to create multi-page dialogs where the values are passed from 711 * one page to another before everything is submitted. If a widget A is used on page X, 712 * there should be no "hidden" HTML field for A since otherwise A would have 2 values when 713 * submitting the dialog page: The one from the widget itself and the one from the hidden 714 * field. This may lead to undefined results when processing the submitted values.<p> 715 * 716 * @param excludeDialogPage the dialog page to exclude the values for 717 * 718 * @return the values of all widget parameters of this dialog as HTML hidden fields, 719 * excluding the widget values that are on the given dialog page 720 * 721 * @see org.opencms.workplace.CmsWorkplace#paramsAsHidden() 722 */ 723 public String widgetParamsAsHidden(String excludeDialogPage) { 724 725 StringBuffer result = new StringBuffer(); 726 Iterator<String> i = m_widgetParamValues.keySet().iterator(); 727 while (i.hasNext()) { 728 List<CmsWidgetDialogParameter> params = m_widgetParamValues.get(i.next()); 729 Iterator<CmsWidgetDialogParameter> j = params.iterator(); 730 while (j.hasNext()) { 731 CmsWidgetDialogParameter param = j.next(); 732 String value = param.getStringValue(getCms()); 733 if (CmsStringUtil.isNotEmpty(value) 734 && ((excludeDialogPage == null) || (!param.getDialogPage().equals(excludeDialogPage)))) { 735 result.append("<input type=\"hidden\" name=\""); 736 result.append(HIDDEN_PARAM_PREFIX); 737 result.append(param.getId()); 738 result.append("\" value=\""); 739 String encoded = CmsEncoder.encode(value, getCms().getRequestContext().getEncoding()); 740 result.append(encoded); 741 result.append("\">\n"); 742 } 743 } 744 } 745 return result.toString(); 746 } 747 748 /** 749 * Writes the dialog html code, only if the <code>{@link #ACTION_DEFAULT}</code> is set.<p> 750 * 751 * @throws JspException if dialog actions fail 752 * @throws IOException if writing to the JSP out fails, or in case of errors forwarding to the required result page 753 */ 754 public void writeDialog() throws IOException, JspException { 755 756 if (isForwarded()) { 757 return; 758 } 759 switch (getAction()) { 760 case ACTION_CANCEL: 761 case ACTION_ERROR: 762 case ACTION_SAVE: 763 break; 764 765 case ACTION_DEFAULT: 766 default: 767 // ACTION: show dialog (default) 768 setParamAction(DIALOG_SAVE); 769 JspWriter out = getJsp().getJspContext().getOut(); 770 out.print(defaultActionHtml()); 771 } 772 } 773 774 /** 775 * Adds the given error to the list of errors that are thrown by save actions or form generation.<p> 776 * 777 * If the error list has not been initialized yet, this is done automatically.<p> 778 * 779 * @param error the errors to add 780 */ 781 protected void addCommitError(Exception error) { 782 783 if (m_commitErrors == null) { 784 m_commitErrors = new ArrayList<Throwable>(); 785 } 786 m_commitErrors.add(error); 787 } 788 789 /** 790 * Adds a new widget parameter definition to the list of all widgets of this dialog.<p> 791 * 792 * @param param the widget parameter definition to add 793 */ 794 protected void addWidget(CmsWidgetDialogParameter param) { 795 796 if (m_widgets == null) { 797 m_widgets = new ArrayList<CmsWidgetDialogParameter>(); 798 } 799 param.setKeyPrefix(m_prefix); 800 m_widgets.add(param); 801 } 802 803 /** 804 * Returns <code>true</code> if the dialog should be closed after the values have been committed.<p> 805 * 806 * The default implementation returns <code>true</code> in case there are no 807 * commit errors.<p> 808 * 809 * @return <code>true</code> if the dialog should be closed after the values have been committed 810 */ 811 protected boolean closeDialogOnCommit() { 812 813 return !hasCommitErrors(); 814 } 815 816 /** 817 * Commits all values on the dialog.<p> 818 * 819 * @return a List of all Exceptions that occurred when comitting the dialog.<p> 820 */ 821 protected List<Throwable> commitWidgetValues() { 822 823 return commitWidgetValues(null); 824 } 825 826 /** 827 * Commits all values on the given dialog page.<p> 828 * 829 * @param dialogPage the dialog (page) to commit 830 * 831 * @return a List of all Exceptions that occurred when committing the dialog page.<p> 832 */ 833 protected List<Throwable> commitWidgetValues(String dialogPage) { 834 835 List<Throwable> result = new ArrayList<Throwable>(); 836 Iterator<CmsWidgetDialogParameter> i = getWidgets().iterator(); 837 while (i.hasNext()) { 838 // check for all widget parameters 839 CmsWidgetDialogParameter base = i.next(); 840 if ((dialogPage == null) || (base.getDialogPage() == null) || dialogPage.equals(base.getDialogPage())) { 841 // the parameter is located on the requested dialog 842 base.prepareCommit(); 843 List<CmsWidgetDialogParameter> params = m_widgetParamValues.get(base.getName()); 844 Iterator<CmsWidgetDialogParameter> j = params.iterator(); 845 while (j.hasNext()) { 846 CmsWidgetDialogParameter param = j.next(); 847 try { 848 param.commitValue(this); 849 } catch (Exception e) { 850 result.add(e); 851 } 852 } 853 } 854 } 855 setValidationErrorList(result); 856 return result; 857 } 858 859 /** 860 * Creates the dialog HTML for all defined widgets of this dialog.<p> 861 * 862 * @return the dialog HTML for all defined widgets of this dialog 863 */ 864 protected String createDialogHtml() { 865 866 return createDialogHtml(null); 867 } 868 869 /** 870 * Creates the dialog HTML for all defined widgets of the named dialog (page).<p> 871 * 872 * To get a more complex layout variation, you have to overwrite this method in your dialog class.<p> 873 * 874 * @param dialog the dialog (page) to get the HTML for 875 * @return the dialog HTML for all defined widgets of the named dialog (page) 876 */ 877 protected String createDialogHtml(String dialog) { 878 879 StringBuffer result = new StringBuffer(1024); 880 881 // create table 882 result.append(createWidgetTableStart()); 883 884 // show error header once if there were validation errors 885 result.append(createWidgetErrorHeader()); 886 887 Iterator<CmsWidgetDialogParameter> i = getWidgets().iterator(); 888 // iterate the type sequence 889 while (i.hasNext()) { 890 // get the current widget base definition 891 CmsWidgetDialogParameter base = i.next(); 892 // check if the element is on the requested dialog page 893 if ((dialog == null) || dialog.equals(base.getDialogPage())) { 894 // add the HTML for the dialog element 895 result.append(createDialogRowHtml(base)); 896 } 897 } 898 // close table 899 result.append(createWidgetTableEnd()); 900 901 return result.toString(); 902 } 903 904 /** 905 * Creates the dialog HTML for all occurrences of one widget parameter.<p> 906 * 907 * @param base the widget parameter base 908 * @return the dialog HTML for one widget parameter 909 */ 910 protected String createDialogRowHtml(CmsWidgetDialogParameter base) { 911 912 StringBuffer result = new StringBuffer(256); 913 914 List<CmsWidgetDialogParameter> sequence = getParameters().get(base.getName()); 915 int count = sequence.size(); 916 917 // check if value is optional or multiple 918 boolean addValue = false; 919 if (count < base.getMaxOccurs()) { 920 addValue = true; 921 } 922 boolean removeValue = false; 923 if (count > base.getMinOccurs()) { 924 removeValue = true; 925 } 926 927 // check if value is present 928 boolean disabledElement = false; 929 if (count < 1) { 930 // no parameter with the value present, but also not optional: use base as parameter 931 sequence = new ArrayList<CmsWidgetDialogParameter>(); 932 sequence.add(base); 933 count = 1; 934 if (base.getMinOccurs() == 0) { 935 disabledElement = true; 936 } 937 } 938 939 // loop through multiple elements 940 for (int j = 0; j < count; j++) { 941 942 // get the parameter and the widget 943 CmsWidgetDialogParameter p = sequence.get(j); 944 I_CmsWidget widget = p.getWidget(); 945 946 // check for an error in this row 947 if (p.hasError()) { 948 // show error message 949 result.append("<tr><td></td><td><img src=\""); 950 result.append(getSkinUri()).append("editors/xmlcontent/"); 951 result.append("error.png"); 952 result.append("\" border=\"0\" alt=\"\"></td><td class=\"xmlTdError\">"); 953 Throwable t = p.getError(); 954 while (t != null) { 955 if (t instanceof I_CmsThrowable) { 956 result.append(CmsEncoder.escapeXml(((I_CmsThrowable)t).getLocalizedMessage(getLocale()))); 957 } else { 958 result.append(CmsEncoder.escapeXml(t.getLocalizedMessage())); 959 } 960 t = t.getCause(); 961 if (t != null) { 962 result.append("<br>"); 963 } 964 } 965 result.append("</td><td colspan=\"2\"></td></tr>\n"); 966 } 967 968 // create label and help bubble cells 969 result.append("<tr>"); 970 result.append("<td class=\"xmlLabel"); 971 if (disabledElement) { 972 // element is disabled, mark it with css 973 result.append("Disabled"); 974 } 975 976 result.append("\">"); 977 result.append(keyDefault(A_CmsWidget.getLabelKey(p), p.getName())); 978 if (count > 1) { 979 result.append(" [").append(p.getIndex() + 1).append("]"); 980 } 981 result.append(": </td>"); 982 if (p.getIndex() == 0) { 983 // show help bubble only on first element of each content definition 984 result.append(p.getWidget().getHelpBubble(getCms(), this, p)); 985 } else { 986 // create empty cell for all following elements 987 result.append(dialogHorizontalSpacer(16)); 988 } 989 990 // append individual widget html cell if element is enabled 991 if (!disabledElement) { 992 // this is a simple type, display widget 993 result.append(widget.getDialogWidget(getCms(), this, p)); 994 } else { 995 // disabled element, show message for optional element 996 result.append("<td class=\"xmlTdDisabled maxwidth\">"); 997 result.append(key(Messages.GUI_EDITOR_WIDGET_OPTIONALELEMENT_0)); 998 result.append("</td>"); 999 } 1000 1001 // append add and remove element buttons if required 1002 result.append(dialogHorizontalSpacer(5)); 1003 result.append("<td>"); 1004 if (addValue || removeValue) { 1005 result.append("<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tr>"); 1006 1007 if (!addValue) { 1008 result.append(dialogHorizontalSpacer(25)); 1009 } else { 1010 result.append( 1011 "<td><table class=\"editorbuttonbackground\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tr>"); 1012 result.append(buildAddElement(base.getName(), p.getIndex(), addValue)); 1013 } 1014 1015 if (removeValue) { 1016 if (!addValue) { 1017 result.append( 1018 "<td><table class=\"editorbuttonbackground\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tr>"); 1019 } 1020 result.append(buildRemoveElement(base.getName(), p.getIndex(), removeValue)); 1021 } 1022 1023 result.append("</tr></table></td>"); 1024 result.append("</tr></table>"); 1025 } 1026 result.append("</td>"); 1027 // close row 1028 result.append("</tr>\n"); 1029 } 1030 1031 return result.toString(); 1032 } 1033 1034 /** 1035 * Creates the dialog widget rows HTML for the specified widget indices.<p> 1036 * 1037 * @param startIndex the widget index to start with 1038 * @param endIndex the widget index to stop at 1039 * 1040 * @return the dialog widget rows HTML for the specified widget indices 1041 */ 1042 protected String createDialogRowsHtml(int startIndex, int endIndex) { 1043 1044 StringBuffer result = new StringBuffer((endIndex - startIndex) * 8); 1045 for (int i = startIndex; i <= endIndex; i++) { 1046 CmsWidgetDialogParameter base = getWidgets().get(i); 1047 result.append(createDialogRowHtml(base)); 1048 } 1049 return result.toString(); 1050 } 1051 1052 /** 1053 * Creates the complete widget dialog end block HTML that finishes a widget block.<p> 1054 * 1055 * @return the complete widget dialog end block HTML that finishes a widget block 1056 */ 1057 protected String createWidgetBlockEnd() { 1058 1059 StringBuffer result = new StringBuffer(8); 1060 result.append(createWidgetTableEnd()); 1061 result.append(dialogBlockEnd()); 1062 return result.toString(); 1063 } 1064 1065 /** 1066 * Create the complete widget dialog start block HTML that begins a widget block with optional headline.<p> 1067 * 1068 * @param headline the headline String for the block 1069 * 1070 * @return the complete widget dialog start block HTML that begins a widget block with optional headline 1071 */ 1072 protected String createWidgetBlockStart(String headline) { 1073 1074 StringBuffer result = new StringBuffer(16); 1075 result.append(dialogBlockStart(headline)); 1076 result.append(createWidgetTableStart()); 1077 return result.toString(); 1078 } 1079 1080 /** 1081 * Creates the HTML for the error message if validation errors were found.<p> 1082 * 1083 * @return the HTML for the error message if validation errors were found 1084 */ 1085 protected String createWidgetErrorHeader() { 1086 1087 StringBuffer result = new StringBuffer(8); 1088 if (hasValidationErrors() || hasCommitErrors()) { 1089 result.append("<tr><td colspan=\"5\"> </td></tr>\n"); 1090 result.append("<tr><td colspan=\"2\"> </td>"); 1091 result.append("<td class=\"xmlTdErrorHeader\">"); 1092 result.append(key(Messages.GUI_EDITOR_WIDGET_VALIDATION_ERROR_TITLE_0)); 1093 result.append("</td><td colspan=\"2\"> "); 1094 result.append("</td></tr>\n"); 1095 result.append("<tr><td colspan=\"5\"> </td></tr>\n"); 1096 if (hasCommitErrors()) { 1097 result.append(dialogBlockStart("")); 1098 result.append(createWidgetTableStart()); 1099 Iterator<Throwable> i = getCommitErrors().iterator(); 1100 while (i.hasNext()) { 1101 Throwable t = i.next(); 1102 result.append("<tr><td><img src=\""); 1103 result.append(getSkinUri()).append("editors/xmlcontent/"); 1104 result.append("error.png"); 1105 result.append("\" border=\"0\" alt=\"\"></td><td class=\"xmlTdError maxwidth\">"); 1106 while (t != null) { 1107 String message = ""; 1108 if (t instanceof I_CmsThrowable) { 1109 message = ((I_CmsThrowable)t).getLocalizedMessage(getLocale()); 1110 } else { 1111 message = t.getLocalizedMessage(); 1112 } 1113 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(message)) { 1114 result.append(CmsStringUtil.escapeHtml(message)); 1115 } 1116 1117 t = t.getCause(); 1118 if (t != null) { 1119 result.append("<br/>"); 1120 } 1121 } 1122 result.append("</td></tr>\n"); 1123 } 1124 result.append(createWidgetTableEnd()); 1125 result.append(dialogBlockEnd()); 1126 } 1127 if (hasValidationErrors()) { 1128 result.append(dialogBlockStart("")); 1129 result.append(createWidgetTableStart()); 1130 Iterator<Throwable> i = getValidationErrorList().iterator(); 1131 while (i.hasNext()) { 1132 Throwable t = i.next(); 1133 result.append("<tr><td><img src=\""); 1134 result.append(getSkinUri()).append("editors/xmlcontent/"); 1135 result.append("error.png"); 1136 result.append("\" border=\"0\" alt=\"\"></td><td class=\"xmlTdError maxwidth\">"); 1137 while (t != null) { 1138 String message = ""; 1139 if (t instanceof I_CmsThrowable) { 1140 message = ((I_CmsThrowable)t).getLocalizedMessage(getLocale()); 1141 } else { 1142 message = t.getLocalizedMessage(); 1143 } 1144 result.append(CmsStringUtil.escapeHtml(message)); 1145 t = t.getCause(); 1146 if (t != null) { 1147 result.append("<br>"); 1148 } 1149 } 1150 result.append("</td></tr>\n"); 1151 } 1152 result.append(createWidgetTableEnd()); 1153 result.append(dialogBlockEnd()); 1154 } 1155 } 1156 return result.toString(); 1157 } 1158 1159 /** 1160 * Creates the HTML for the table around the dialog widgets.<p> 1161 * 1162 * @return the HTML for the table around the dialog widgets 1163 */ 1164 protected String createWidgetTableEnd() { 1165 1166 return "</table>\n"; 1167 } 1168 1169 /** 1170 * Creates the HTML to close the table around the dialog widgets.<p> 1171 * 1172 * @return the HTML to close the table around the dialog widgets 1173 */ 1174 protected String createWidgetTableStart() { 1175 1176 return "<table cellspacing='0' cellpadding='0' class='xmlTable'>\n"; 1177 } 1178 1179 /** 1180 * Generates the dialog starting html code.<p> 1181 * 1182 * @return html code 1183 * 1184 * @throws JspException if something goes wrong 1185 */ 1186 protected String defaultActionHtml() throws JspException { 1187 1188 StringBuffer result = new StringBuffer(2048); 1189 result.append(defaultActionHtmlStart()); 1190 result.append(defaultActionHtmlContent()); 1191 result.append(defaultActionHtmlEnd()); 1192 return result.toString(); 1193 } 1194 1195 /** 1196 * Returns the html code for the default action content.<p> 1197 * 1198 * @return html code 1199 */ 1200 protected String defaultActionHtmlContent() { 1201 1202 StringBuffer result = new StringBuffer(2048); 1203 result.append("<form name=\"EDITOR\" id=\"EDITOR\" method=\"post\" action=\"").append(getDialogRealUri()); 1204 result.append("\" class=\"nomargin\" onsubmit=\"return submitAction('").append(DIALOG_OK).append( 1205 "', null, 'EDITOR');\">\n"); 1206 result.append(dialogContentStart(getDialogTitle())); 1207 result.append(buildDialogForm()); 1208 result.append(dialogContentEnd()); 1209 result.append(dialogButtonsCustom()); 1210 result.append(paramsAsHidden()); 1211 if (getParamFramename() == null) { 1212 result.append("\n<input type=\"hidden\" name=\"").append(PARAM_FRAMENAME).append("\" value=\"\">\n"); 1213 } 1214 result.append("</form>\n"); 1215 result.append(getWidgetHtmlEnd()); 1216 return result.toString(); 1217 } 1218 1219 /** 1220 * Generates the dialog ending html code.<p> 1221 * 1222 * @return html code 1223 */ 1224 protected String defaultActionHtmlEnd() { 1225 1226 StringBuffer result = new StringBuffer(2048); 1227 result.append(dialogEnd()); 1228 result.append(bodyEnd()); 1229 result.append(htmlEnd()); 1230 return result.toString(); 1231 } 1232 1233 /** 1234 * Generates the dialog starting html code.<p> 1235 * 1236 * @return html code 1237 * 1238 * @throws JspException if something goes wrong 1239 */ 1240 protected String defaultActionHtmlStart() throws JspException { 1241 1242 StringBuffer result = new StringBuffer(2048); 1243 result.append(htmlStart("administration/index.html")); 1244 result.append("<script src=\"").append(getResourceUri()).append( 1245 "editors/xmlcontent/edit.js\"></script>\n"); 1246 result.append("<script src=\"").append(getResourceUri()).append( 1247 "editors/xmlcontent/help.js\"></script>\n"); 1248 result.append(getWidgetIncludes()); 1249 result.append("<script >\n<!--\n"); 1250 result.append("// flag indicating if form initialization is finished\n"); 1251 result.append("var initialized = false;\n"); 1252 result.append("// the OpenCms context path\n"); 1253 result.append("var contextPath = \"").append(OpenCms.getSystemInfo().getOpenCmsContext()).append("\";\n\n"); 1254 result.append("// action parameters of the form\n"); 1255 result.append("var actionAddElement = \"").append(EDITOR_ACTION_ELEMENT_ADD).append("\";\n"); 1256 result.append("var actionRemoveElement = \"").append(EDITOR_ACTION_ELEMENT_REMOVE).append("\";\n"); 1257 result.append("function init() {\n"); 1258 result.append(getWidgetInitCalls()); 1259 result.append("\tsetTimeout(\"scrollForm();\", 200);\n"); 1260 result.append("\tinitialized = true;\n"); 1261 result.append("\twindow.onbeforeunload=exitEditor;\n"); 1262 result.append("}\n\n"); 1263 result.append("window.exitEditorCalled = false;\n"); 1264 result.append("function exitEditor() {\n"); 1265 result.append("\tif (window.exitEditorCalled) return;\n"); 1266 result.append("\twindow.exitEditorCalled = true; \n"); 1267 result.append("\ttry {\n"); 1268 result.append("\t\t// close file selector popup if present\n"); 1269 result.append("\t\tcloseTreeWin();\n"); 1270 result.append("\t} catch (e) {}\n"); 1271 result.append("}\n"); 1272 result.append(getWidgetInitMethods()); 1273 result.append("\n// -->\n</script>\n"); 1274 result.append(bodyStart(null, "onload='init();' onunload='exitEditor();'")); 1275 result.append(dialogStart()); 1276 return result.toString(); 1277 } 1278 1279 /** 1280 * Defines the list of parameters for this dialog.<p> 1281 */ 1282 protected abstract void defineWidgets(); 1283 1284 /** 1285 * Fills all widgets of this widget dialog with the values from the request parameters.<p> 1286 * 1287 * @param request the current HTTP servlet request 1288 */ 1289 protected void fillWidgetValues(HttpServletRequest request) { 1290 1291 Map<?, ?> parameters = request.getParameterMap(); 1292 Map<String, String[]> processedParameters = new HashMap<String, String[]>(); 1293 Iterator<?> p = parameters.entrySet().iterator(); 1294 // make sure all "hidden" widget parameters are decoded 1295 while (p.hasNext()) { 1296 Map.Entry<?, ?> entry = (Map.Entry<?, ?>)p.next(); 1297 String key = (String)entry.getKey(); 1298 String[] values = (String[])entry.getValue(); 1299 if (key.startsWith(HIDDEN_PARAM_PREFIX)) { 1300 // this is an encoded hidden parameter 1301 key = key.substring(HIDDEN_PARAM_PREFIX.length()); 1302 String[] newValues = new String[values.length]; 1303 for (int l = 0; l < values.length; l++) { 1304 newValues[l] = CmsEncoder.decode(values[l], getCms().getRequestContext().getEncoding()); 1305 } 1306 values = newValues; 1307 } 1308 processedParameters.put(key, values); 1309 } 1310 1311 // now process the parameters 1312 m_widgetParamValues = new HashMap<String, List<CmsWidgetDialogParameter>>(); 1313 Iterator<CmsWidgetDialogParameter> i = getWidgets().iterator(); 1314 1315 while (i.hasNext()) { 1316 // check for all widget base parameters 1317 CmsWidgetDialogParameter base = i.next(); 1318 1319 List<CmsWidgetDialogParameter> params = new ArrayList<CmsWidgetDialogParameter>(); 1320 int maxOccurs = base.getMaxOccurs(); 1321 1322 boolean onPage = false; 1323 if (base.isCollectionBase()) { 1324 // for a collection base, check if we are on the page where the collection base is shown 1325 if (CmsStringUtil.isNotEmpty(getParamAction()) && !DIALOG_INITIAL.equals(getParamAction())) { 1326 // if no action set (usually for first display of dialog) make sure all values are shown 1327 // DIALOG_INITIAL is a special value for the first display and must be handled the same way 1328 String page = getParamPage(); 1329 // keep in mind that since the paramPage will be set AFTER the widget values are filled, 1330 // so the first time this page is called from another page the following will result to "false", 1331 // but for every "submit" on the page this will be "true" 1332 onPage = CmsStringUtil.isEmpty(page) 1333 || CmsStringUtil.isEmpty(base.getDialogPage()) 1334 || base.getDialogPage().equals(page); 1335 } 1336 } 1337 1338 for (int j = 0; j < maxOccurs; j++) { 1339 // check for all possible values in the request parameters 1340 String id = CmsWidgetDialogParameter.createId(base.getName(), j); 1341 1342 boolean required = (params.size() < base.getMinOccurs()) 1343 || (processedParameters.get(id) != null) 1344 || (!onPage && base.hasValue(j)); 1345 1346 if (required) { 1347 CmsWidgetDialogParameter param = new CmsWidgetDialogParameter(base, params.size(), j); 1348 param.setKeyPrefix(m_prefix); 1349 base.getWidget().setEditorValue(getCms(), processedParameters, this, param); 1350 params.add(param); 1351 } 1352 } 1353 m_widgetParamValues.put(base.getName(), params); 1354 } 1355 } 1356 1357 /** 1358 * Returns the title for this Dialog.<p> 1359 * 1360 * In the default implementation this method returns <code>null</code>. 1361 * Override this if needed.<p> 1362 * 1363 * @return the title for this Dialog, or <code>null</code> if this dialog has no title 1364 */ 1365 protected String getDialogTitle() { 1366 1367 return null; 1368 } 1369 1370 /** 1371 * Returns the allowed pages for this dialog.<p> 1372 * 1373 * @return the allowed pages for this dialog 1374 */ 1375 protected abstract String[] getPageArray(); 1376 1377 /** 1378 * Returns the allowed pages for this dialog.<p> 1379 * 1380 * @return the allowed pages for this dialog 1381 */ 1382 protected List<String> getPages() { 1383 1384 if (m_pages == null) { 1385 m_pages = Arrays.asList(getPageArray()); 1386 } 1387 return m_pages; 1388 } 1389 1390 /** 1391 * Returns the parameter widget definition for the given parameter name.<p> 1392 * 1393 * @param name the parameter name to get the definition for 1394 * 1395 * @return the parameter widget definition for the given parameter name 1396 */ 1397 protected CmsWidgetDialogParameter getParameterDefinition(String name) { 1398 1399 Iterator<CmsWidgetDialogParameter> i = getWidgets().iterator(); 1400 while (i.hasNext()) { 1401 // check for all widget parameters 1402 CmsWidgetDialogParameter base = i.next(); 1403 if (base.getName().equals(name)) { 1404 return base; 1405 } 1406 } 1407 return null; 1408 } 1409 1410 /** 1411 * Returns the map with the widget parameter values.<p> 1412 * 1413 * @return the map with the widget parameter values 1414 */ 1415 protected Map<String, List<CmsWidgetDialogParameter>> getParameters() { 1416 1417 return m_widgetParamValues; 1418 } 1419 1420 /** 1421 * Returns the validation errors for the dialog.<p> 1422 * 1423 * The method (@link CmsWidgetDialog#commitWidgetValues(String)) has to set this list.<p> 1424 * 1425 * @return the validation errors for the dialog 1426 */ 1427 protected List<Throwable> getValidationErrorList() { 1428 1429 return m_validationErrorList; 1430 } 1431 1432 /** 1433 * Returns the widget HTML code for the given parameter.<p> 1434 * 1435 * @param param the name (id) of the parameter to get the widget HTML for 1436 * 1437 * @return the widget HTML code for the given parameter 1438 */ 1439 protected String getWidget(CmsWidgetDialogParameter param) { 1440 1441 if (param != null) { 1442 return param.getWidget().getDialogWidget(getCms(), this, param); 1443 } 1444 return null; 1445 } 1446 1447 /** 1448 * Returns the list of all widgets used on this widget dialog, the 1449 * List must contain Objects of type <code>{@link CmsWidgetDialogParameter}</code>.<p> 1450 * 1451 * @return the list of all widgets used on this widget dialog 1452 */ 1453 protected List<CmsWidgetDialogParameter> getWidgets() { 1454 1455 if (m_widgets == null) { 1456 m_widgets = new ArrayList<CmsWidgetDialogParameter>(); 1457 } 1458 return m_widgets; 1459 } 1460 1461 /** 1462 * Returns <code>true</code> if the current dialog (page) has commit errors.<p> 1463 * 1464 * @return <code>true</code> if the current dialog (page) has commit errors 1465 */ 1466 protected boolean hasCommitErrors() { 1467 1468 return (m_commitErrors != null) && (m_commitErrors.size() > 0); 1469 } 1470 1471 /** 1472 * Returns <code>true</code> if the current dialog (page) has validation errors.<p> 1473 * 1474 * @return <code>true</code> if the current dialog (page) has validation errors 1475 */ 1476 protected boolean hasValidationErrors() { 1477 1478 return (m_validationErrorList != null) && (m_validationErrorList.size() > 0); 1479 } 1480 1481 /** 1482 * @see org.opencms.workplace.CmsWorkplace#initWorkplaceRequestValues(org.opencms.workplace.CmsWorkplaceSettings, javax.servlet.http.HttpServletRequest) 1483 */ 1484 @Override 1485 protected void initWorkplaceRequestValues(CmsWorkplaceSettings settings, HttpServletRequest request) { 1486 1487 // set the dialog type 1488 setParamDialogtype(getClass().getName()); 1489 1490 // fill the parameter values in the get/set methods 1491 fillParamValues(request); 1492 1493 if (CmsStringUtil.isEmptyOrWhitespaceOnly(getParamPage()) || !getPages().contains(getParamPage())) { 1494 // ensure a valid page is set 1495 setParamPage(getPages().get(0)); 1496 } 1497 1498 // test the needed parameters 1499 try { 1500 validateParamaters(); 1501 } catch (Exception e) { 1502 if (LOG.isInfoEnabled()) { 1503 LOG.info(Messages.get().container(Messages.ERR_WORKPLACE_DIALOG_PARAMS_1, getCurrentToolPath()), e); 1504 } 1505 // close if parameters not available 1506 setAction(ACTION_CANCEL); 1507 try { 1508 actionCloseDialog(); 1509 } catch (JspException e1) { 1510 // ignore 1511 } 1512 return; 1513 } 1514 1515 // fill the widget map 1516 defineWidgets(); 1517 fillWidgetValues(request); 1518 1519 // set the action for the JSP switch 1520 if (DIALOG_SAVE.equals(getParamAction())) { 1521 // ok button pressed, save 1522 List<Throwable> errors = commitWidgetValues(null); 1523 if (errors.size() > 0) { 1524 setAction(ACTION_DEFAULT); 1525 // found validation errors, redisplay page 1526 return; 1527 } 1528 setAction(ACTION_SAVE); 1529 } else if (DIALOG_OK.equals(getParamAction())) { 1530 // ok button pressed 1531 setAction(ACTION_CANCEL); 1532 } else if (DIALOG_CANCEL.equals(getParamAction())) { 1533 // cancel button pressed 1534 setAction(ACTION_CANCEL); 1535 } else if (EDITOR_ACTION_ELEMENT_ADD.equals(getParamAction())) { 1536 // add optional input element 1537 setAction(ACTION_ELEMENT_ADD); 1538 actionToggleElement(); 1539 setAction(ACTION_DEFAULT); 1540 } else if (EDITOR_ACTION_ELEMENT_REMOVE.equals(getParamAction())) { 1541 // remove optional input element 1542 setAction(ACTION_ELEMENT_REMOVE); 1543 actionToggleElement(); 1544 setAction(ACTION_DEFAULT); 1545 } else if (DIALOG_BACK.equals(getParamAction())) { 1546 // go back one page 1547 setAction(ACTION_DEFAULT); 1548 List<Throwable> errors = commitWidgetValues(getParamPage()); 1549 if (errors.size() > 0) { 1550 // found validation errors, redisplay page 1551 return; 1552 } 1553 int pageIndex = getPages().indexOf(getParamPage()) - 1; 1554 setParamPage(getPages().get(pageIndex)); 1555 1556 } else if (DIALOG_CONTINUE.equals(getParamAction())) { 1557 // go to next page 1558 setAction(ACTION_DEFAULT); 1559 List<Throwable> errors = commitWidgetValues(getParamPage()); 1560 if (errors.size() > 0) { 1561 // found validation errors, redisplay page 1562 return; 1563 } 1564 int pageIndex = getPages().indexOf(getParamPage()) + 1; 1565 setParamPage(getPages().get(pageIndex)); 1566 1567 } else { 1568 // first dialog call, set the default action 1569 setAction(ACTION_DEFAULT); 1570 } 1571 } 1572 1573 /** 1574 * Sets the errors that are thrown by save actions or form generation.<p> 1575 * 1576 * @param errors the errors that are thrown by save actions or form generation 1577 */ 1578 protected void setCommitErrors(List<Throwable> errors) { 1579 1580 m_commitErrors = errors; 1581 } 1582 1583 /** 1584 * Sets an optional localized key prefix identificator for all widgets.<p> 1585 * 1586 * @param prefix the optional localized key prefix identificator for all widgets 1587 * 1588 * @see org.opencms.widgets.I_CmsWidgetParameter#setKeyPrefix(java.lang.String) 1589 */ 1590 protected void setKeyPrefix(String prefix) { 1591 1592 m_prefix = prefix; 1593 } 1594 1595 /** 1596 * Sets the allowed pages for this dialog.<p> 1597 * 1598 * @param pages the allowed pages for this dialog 1599 */ 1600 protected void setPages(List<String> pages) { 1601 1602 m_pages = pages; 1603 } 1604 1605 /** 1606 * Sets the validation errors for the dialog.<p> 1607 * 1608 * Use this in the method (@link CmsWidgetDialog#commitWidgetValues(String)) to set the list.<p> 1609 * 1610 * @param errors the validation errors 1611 */ 1612 protected void setValidationErrorList(List<Throwable> errors) { 1613 1614 m_validationErrorList = errors; 1615 } 1616 1617 /** 1618 * Should be overridden for parameter validation.<p> 1619 * 1620 * The exception is never seen by the user, so it can be just a <code>new {@link Exception}()</code>.<p> 1621 * 1622 * @throws Exception if the parameters are not valid 1623 */ 1624 protected void validateParamaters() throws Exception { 1625 1626 // valid by default 1627 } 1628 1629 /** 1630 * Returns the (internal use only) map of dialog objects.<p> 1631 * 1632 * @return the (internal use only) map of dialog objects 1633 */ 1634 private Map<String, Object> getDialogObjectMap() { 1635 1636 @SuppressWarnings("unchecked") 1637 Map<String, Object> objects = (Map<String, Object>)getSettings().getDialogObject(); 1638 if (objects == null) { 1639 // using hash table as most efficient version of a synchronized map 1640 objects = new Hashtable<String, Object>(); 1641 getSettings().setDialogObject(objects); 1642 } 1643 return objects; 1644 } 1645}