001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (https://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: https://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: https://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.list; 029 030import org.opencms.i18n.CmsMessageContainer; 031import org.opencms.jsp.CmsJspActionElement; 032import org.opencms.main.CmsException; 033import org.opencms.main.CmsLog; 034import org.opencms.main.CmsRuntimeException; 035import org.opencms.util.CmsCollectionsGenericWrapper; 036import org.opencms.util.CmsStringUtil; 037import org.opencms.workplace.CmsDialog; 038import org.opencms.workplace.CmsWorkplaceSettings; 039import org.opencms.workplace.tools.CmsToolDialog; 040 041import java.io.IOException; 042import java.util.ArrayList; 043import java.util.HashMap; 044import java.util.Hashtable; 045import java.util.Iterator; 046import java.util.List; 047import java.util.Map; 048 049import org.apache.commons.logging.Log; 050 051import jakarta.servlet.ServletException; 052import jakarta.servlet.http.HttpServletRequest; 053import jakarta.servlet.jsp.JspException; 054import jakarta.servlet.jsp.JspWriter; 055 056/** 057 * Provides a dialog with a list widget.<p> 058 * 059 * @since 6.0.0 060 */ 061public abstract class A_CmsListDialog extends CmsDialog { 062 063 /** Value for the action: execute a list item independent action of the list. */ 064 public static final int ACTION_LIST_INDEPENDENT_ACTION = 83; 065 066 /** Value for the action: execute an multi action of the list. */ 067 public static final int ACTION_LIST_MULTI_ACTION = 85; 068 069 /** Value for the action: search the list. */ 070 public static final int ACTION_LIST_SEARCH = 81; 071 072 /** Value for the action: go to a page. */ 073 public static final int ACTION_LIST_SELECT_PAGE = 82; 074 075 /** Value for the action: execute a single action of the list. */ 076 public static final int ACTION_LIST_SINGLE_ACTION = 84; 077 078 /** Value for the action: sort the list. */ 079 public static final int ACTION_LIST_SORT = 80; 080 081 /** Standard list button location. */ 082 public static final String ICON_ACTIVE = "list/active.png"; 083 084 /** Standard list button location. */ 085 public static final String ICON_ADD = "list/add.png"; 086 087 /** Standard list button location. */ 088 public static final String ICON_DELETE = "list/delete.png"; 089 090 /** Standard list button location. */ 091 public static final String ICON_DETAILS_HIDE = "list/details_hide.png"; 092 093 /** Standard list button location. */ 094 public static final String ICON_DETAILS_SHOW = "list/details_show.png"; 095 096 /** Standard list button location. */ 097 public static final String ICON_DISABLED = "list/disabled.png"; 098 099 /** Standard list button location. */ 100 public static final String ICON_INACTIVE = "list/inactive.png"; 101 102 /** Standard list button location. */ 103 public static final String ICON_MINUS = "list/minus.png"; 104 105 /** Standard list button location. */ 106 public static final String ICON_MULTI_ACTIVATE = "list/multi_activate.png"; 107 108 /** Standard list button location. */ 109 public static final String ICON_MULTI_ADD = "list/multi_add.png"; 110 111 /** Standard list button location. */ 112 public static final String ICON_MULTI_DEACTIVATE = "list/multi_deactivate.png"; 113 114 /** Standard list button location. */ 115 public static final String ICON_MULTI_DELETE = "list/multi_delete.png"; 116 117 /** Standard list button location. */ 118 public static final String ICON_MULTI_MINUS = "list/multi_minus.png"; 119 120 /** Request parameter value for the list action: a list item independent action has been triggered. */ 121 public static final String LIST_INDEPENDENT_ACTION = "listindependentaction"; 122 123 /** Request parameter value for the list action: a multi action has been triggered. */ 124 public static final String LIST_MULTI_ACTION = "listmultiaction"; 125 126 /** Request parameter value for the list action: search/filter. */ 127 public static final String LIST_SEARCH = "listsearch"; 128 129 /** Request parameter value for the list action: select a page. */ 130 public static final String LIST_SELECT_PAGE = "listselectpage"; 131 132 /** Request parameter value for the list action: a single action has been triggered. */ 133 public static final String LIST_SINGLE_ACTION = "listsingleaction"; 134 135 /** Request parameter value for the list action: sort. */ 136 public static final String LIST_SORT = "listsort"; 137 138 /** Request parameter key for the requested page. */ 139 public static final String PARAM_FORMNAME = "formname"; 140 141 /** Request parameter key for the list action. */ 142 public static final String PARAM_LIST_ACTION = "listaction"; 143 144 /** Request parameter key for the requested page. */ 145 public static final String PARAM_PAGE = "page"; 146 147 /** Request parameter key for search the filter. */ 148 public static final String PARAM_SEARCH_FILTER = "searchfilter"; 149 150 /** Request parameter key for the selected item(s). */ 151 public static final String PARAM_SEL_ITEMS = "selitems"; 152 153 /** Request parameter key for the column to sort the list. */ 154 public static final String PARAM_SORT_COL = "sortcol"; 155 156 /** The log object for this class. */ 157 private static final Log LOG = CmsLog.getLog(A_CmsListDialog.class); 158 159 public static String KEY_META_DATA_CACHE = "key_meta_data_cache"; 160 161 /** metadata map for all used list metadata objects. */ 162 private Map<String, CmsListMetadata> m_metadatas; 163 164 /** A flag which indicates whether the list should use database paging (only supported for some lists) .**/ 165 protected boolean m_lazy; 166 167 /** Activation decision Flag. */ 168 private boolean m_active; 169 170 /** the internal list. */ 171 private CmsHtmlList m_list; 172 173 /** The id of the list. */ 174 private String m_listId; 175 176 /** Cached List state in case of {@link #refreshList()} method call. */ 177 private CmsListState m_listState; 178 179 /** The displayed page. */ 180 private String m_paramFormName; 181 182 /** The list action. */ 183 private String m_paramListAction; 184 185 /** The displayed page. */ 186 private String m_paramPage; 187 188 /** The search filter text. */ 189 private String m_paramSearchFilter; 190 191 /** The selected items, comma separated list. */ 192 private String m_paramSelItems; 193 194 /** The column to sort the list. */ 195 private String m_paramSortCol; 196 197 /** The column to search the list. */ 198 private String m_searchColId; 199 200 /** 201 * Public constructor.<p> 202 * 203 * @param jsp an initialized JSP action element 204 * @param listId the id of the displayed list 205 * @param listName the name of the list 206 * @param sortedColId the a priory sorted column 207 * @param sortOrder the order of the sorted column 208 * @param searchableColId the column to search into 209 */ 210 protected A_CmsListDialog( 211 CmsJspActionElement jsp, 212 String listId, 213 CmsMessageContainer listName, 214 String sortedColId, 215 CmsListOrderEnum sortOrder, 216 String searchableColId) { 217 218 this(jsp, listId, listName, sortedColId, sortOrder, searchableColId, false); 219 } 220 221 /** 222 * Public constructor.<p> 223 * 224 * @param jsp an initialized JSP action element 225 * @param listId the id of the displayed list 226 * @param listName the name of the list 227 * @param sortedColId the a priory sorted column 228 * @param sortOrder the order of the sorted column 229 * @param searchableColId the column to search into 230 * @param lazy if this parameter is true, the list should load only load the list items of the current page, if possible 231 */ 232 @SuppressWarnings("unchecked") 233 protected A_CmsListDialog( 234 CmsJspActionElement jsp, 235 String listId, 236 CmsMessageContainer listName, 237 String sortedColId, 238 CmsListOrderEnum sortOrder, 239 String searchableColId, 240 boolean lazy) { 241 242 super(jsp); 243 m_lazy = lazy; 244 m_metadatas = (Map<String, CmsListMetadata>)jsp.getRequest().getSession().getAttribute(KEY_META_DATA_CACHE); 245 if (m_metadatas == null) { 246 m_metadatas = new HashMap<String, CmsListMetadata>(); 247 jsp.getRequest().getSession().setAttribute(KEY_META_DATA_CACHE, m_metadatas); 248 } 249 if (LOG.isDebugEnabled()) { 250 LOG.debug(Messages.get().getBundle().key(Messages.LOG_START_INIT_LIST_1, listId)); 251 } 252 // set list id 253 m_listId = listId; 254 // set active flag for 2 lists dialog 255 m_active = (getListId() + "-form").equals(getParamFormName()); 256 setParamFormName(getListId() + "-form"); 257 // abort if already forwarded 258 if (isForwarded()) { 259 return; 260 } 261 m_searchColId = searchableColId; 262 // try to read the list from the session 263 listRecovery(listId); 264 // initialization 265 if (getList() == null) { 266 // create the list 267 setList(new CmsHtmlList(listId, listName, getMetadata(this.getClass().getName(), listId))); 268 // set the number of items per page from the user settings 269 getList().setMaxItemsPerPage(getSettings().getUserSettings().getExplorerFileEntries()); 270 // sort the list 271 if ((sortedColId != null) && (getList().getMetadata().getColumnDefinition(sortedColId) != null)) { 272 getList().setWp(this); 273 getList().setSortedColumn(sortedColId); 274 if ((sortOrder != null) && (sortOrder == CmsListOrderEnum.ORDER_DESCENDING)) { 275 getList().setSortedColumn(sortedColId); 276 } 277 } 278 // save the current state of the list 279 listSave(); 280 } 281 getList().setWp(this); 282 if (LOG.isDebugEnabled()) { 283 LOG.debug(Messages.get().getBundle().key(Messages.LOG_END_INIT_LIST_1, listId)); 284 } 285 } 286 287 /** 288 * Returns the list object for the given list dialog, or <code>null</code> 289 * if no list object has been set.<p> 290 * 291 * @param listDialog the list dialog class 292 * @param settings the wp settings for accessing the session 293 * 294 * @return the list object for this list dialog, or <code>null</code> 295 */ 296 public static CmsHtmlList getListObject(Class<?> listDialog, CmsWorkplaceSettings settings) { 297 298 return getListObjectMap(settings).get(listDialog.getName()); 299 } 300 301 /** 302 * Returns the (internal use only) map of list objects.<p> 303 * 304 * @param settings the wp settings for accessing the session 305 * 306 * @return the (internal use only) map of list objects 307 */ 308 private static Map<String, CmsHtmlList> getListObjectMap(CmsWorkplaceSettings settings) { 309 310 Map<String, CmsHtmlList> objects = CmsCollectionsGenericWrapper.map(settings.getListObject()); 311 if (objects == null) { 312 // using hashtable as most efficient version of a synchronized map 313 objects = new Hashtable<String, CmsHtmlList>(); 314 settings.setListObject(objects); 315 } 316 return objects; 317 } 318 319 /** 320 * Performs the dialog actions depending on the initialized action.<p> 321 * 322 * @throws JspException if dialog actions fail 323 * @throws IOException in case of errors forwarding to the required result page 324 * @throws ServletException in case of errors forwarding to the required result page 325 */ 326 public void actionDialog() throws JspException, ServletException, IOException { 327 328 if (isForwarded()) { 329 return; 330 } 331 if (getAction() == ACTION_CANCEL) { 332 // ACTION: cancel button pressed 333 actionCloseDialog(); 334 return; 335 } 336 337 if (LOG.isDebugEnabled()) { 338 LOG.debug( 339 Messages.get().getBundle().key( 340 Messages.LOG_START_ACTION_LIST_2, 341 getListId(), 342 Integer.valueOf(getAction()))); 343 } 344 switch (getAction()) { 345 //////////////////// ACTION: default actions 346 case ACTION_LIST_SEARCH: 347 case ACTION_LIST_SORT: 348 case ACTION_LIST_SELECT_PAGE: 349 executeDefaultActions(); 350 break; 351 352 //////////////////// ACTION: execute single list action 353 case ACTION_LIST_SINGLE_ACTION: 354 if (getSelectedItem() != null) { 355 executeListSingleActions(); 356 } 357 break; 358 359 //////////////////// ACTION: execute multiple list actions 360 case ACTION_LIST_MULTI_ACTION: 361 executeListMultiActions(); 362 break; 363 364 //////////////////// ACTION: execute independent list actions 365 case ACTION_LIST_INDEPENDENT_ACTION: 366 executeListIndepActions(); 367 break; 368 369 case ACTION_DEFAULT: 370 default: 371 // ACTION: show dialog (default) 372 setParamAction(DIALOG_INITIAL); 373 } 374 if (LOG.isDebugEnabled()) { 375 LOG.debug( 376 Messages.get().getBundle().key( 377 Messages.LOG_END_ACTION_LIST_2, 378 getListId(), 379 Integer.valueOf(getAction()))); 380 } 381 refreshList(); 382 } 383 384 /** 385 * Generates the dialog starting html code.<p> 386 * 387 * @return html code 388 */ 389 public String defaultActionHtml() { 390 391 if ((getList() != null) && getList().getAllContent().isEmpty()) { 392 // TODO: check the need for this 393 refreshList(); 394 } 395 StringBuffer result = new StringBuffer(2048); 396 result.append(defaultActionHtmlStart()); 397 result.append(customHtmlStart()); 398 result.append(defaultActionHtmlContent()); 399 result.append(customHtmlEnd()); 400 result.append(defaultActionHtmlEnd()); 401 return result.toString(); 402 } 403 404 /** 405 * Performs the dialog actions depending on the initialized action and displays the dialog form.<p> 406 * 407 * @throws JspException if dialog actions fail 408 * @throws IOException if writing to the JSP out fails, or in case of errors forwarding to the required result page 409 * @throws ServletException in case of errors forwarding to the required result page 410 */ 411 public void displayDialog() throws JspException, IOException, ServletException { 412 413 displayDialog(false); 414 } 415 416 /** 417 * Performs the dialog actions depending on the initialized action and displays the dialog form if needed.<p> 418 * 419 * @param writeLater if <code>true</code> no output is written, 420 * you have to call manually the <code>{@link #defaultActionHtml()}</code> method. 421 * 422 * @throws JspException if dialog actions fail 423 * @throws IOException if writing to the JSP out fails, or in case of errors forwarding to the required result page 424 * @throws ServletException in case of errors forwarding to the required result page 425 */ 426 public void displayDialog(boolean writeLater) throws JspException, IOException, ServletException { 427 428 actionDialog(); 429 if (writeLater) { 430 return; 431 } 432 writeDialog(); 433 } 434 435 /** 436 * This method execute the default actions for searching, sorting and paging.<p> 437 */ 438 public void executeDefaultActions() { 439 440 switch (getAction()) { 441 442 case ACTION_LIST_SEARCH: 443 executeSearch(); 444 break; 445 case ACTION_LIST_SORT: 446 executeSort(); 447 break; 448 case ACTION_LIST_SELECT_PAGE: 449 executeSelectPage(); 450 break; 451 default: 452 // ignore 453 } 454 listSave(); 455 } 456 457 /** 458 * This method should handle the default list independent actions, 459 * by comparing <code>{@link #getParamListAction()}</code> with the id 460 * of the action to execute.<p> 461 * 462 * if you want to handle additional independent actions, override this method, 463 * handling your actions and FINALLY calling <code>super.executeListIndepActions();</code>.<p> 464 */ 465 public void executeListIndepActions() { 466 467 if (getList().getMetadata().getItemDetailDefinition(getParamListAction()) != null) { 468 // toggle item details 469 getList().getMetadata().toogleDetailState(getParamListAction()); 470 // lazy initialization 471 initializeDetail(getParamListAction()); 472 } 473 listSave(); 474 } 475 476 /** 477 * This method should handle every defined list multi action, 478 * by comparing <code>{@link #getParamListAction()}</code> with the id 479 * of the action to execute.<p> 480 * 481 * @throws IOException in case of errors when including a required sub-element 482 * @throws ServletException in case of errors when including a required sub-element 483 * @throws CmsRuntimeException to signal that an action is not supported 484 */ 485 public abstract void executeListMultiActions() throws IOException, ServletException, CmsRuntimeException; 486 487 /** 488 * This method should handle every defined list single action, 489 * by comparing <code>{@link #getParamListAction()}</code> with the id 490 * of the action to execute.<p> 491 * 492 * @throws IOException in case of errors when including a required sub-element 493 * @throws ServletException in case of errors when including a required sub-element 494 * @throws CmsRuntimeException to signal that an action is not supported 495 */ 496 public abstract void executeListSingleActions() throws IOException, ServletException, CmsRuntimeException; 497 498 /** 499 * Returns the list.<p> 500 * 501 * @return the list 502 */ 503 public CmsHtmlList getList() { 504 505 if ((m_list != null) && (m_list.getMetadata() == null)) { 506 m_list.setMetadata(getMetadata(getClass().getName(), m_list.getId())); 507 } 508 return m_list; 509 } 510 511 /** 512 * Returns the Id of the list.<p> 513 * 514 * @return the list Id 515 */ 516 public final String getListId() { 517 518 return m_listId; 519 } 520 521 /** 522 * Returns the list metadata object for the given dialog.<p> 523 * 524 * @param listDialogName the dialog class name 525 * 526 * @return the list metadata object 527 */ 528 public CmsListMetadata getMetadata(String listDialogName) { 529 530 return getMetadataCache().get(listDialogName); 531 } 532 533 /** 534 * Should generate the metadata definition for the list, and return the 535 * corresponding <code>{@link CmsListMetadata}</code> object.<p> 536 * 537 * @param listDialogName the name of the class generating the list 538 * @param listId the id of the list 539 * 540 * @return The metadata for the given list 541 */ 542 public synchronized CmsListMetadata getMetadata(String listDialogName, String listId) { 543 544 getSettings(); 545 String metaDataKey = listDialogName + listId; 546 547 if ((getMetadataCache().get(metaDataKey) == null) || getMetadataCache().get(metaDataKey).isVolatile()) { 548 if (LOG.isDebugEnabled()) { 549 LOG.debug(Messages.get().getBundle().key(Messages.LOG_START_METADATA_LIST_1, getListId())); 550 } 551 CmsListMetadata metadata = new CmsListMetadata(listId); 552 553 setColumns(metadata); 554 // always check the search action 555 setSearchAction(metadata, m_searchColId); 556 setIndependentActions(metadata); 557 metadata.addIndependentAction(new CmsListPrintIAction()); 558 setMultiActions(metadata); 559 metadata.checkIds(); 560 getMetadataCache().put(metaDataKey, metadata); 561 if (LOG.isDebugEnabled()) { 562 LOG.debug(Messages.get().getBundle().key(Messages.LOG_END_METADATA_LIST_1, getListId())); 563 } 564 } 565 return getMetadata(metaDataKey); 566 } 567 568 /** 569 * Returns the form name.<p> 570 * 571 * @return the form name 572 */ 573 public String getParamFormName() { 574 575 return m_paramFormName; 576 } 577 578 /** 579 * Returns the List Action.<p> 580 * 581 * @return the List Action 582 */ 583 public String getParamListAction() { 584 585 return m_paramListAction; 586 } 587 588 /** 589 * Returns the current Page.<p> 590 * 591 * @return the current Page 592 */ 593 public String getParamPage() { 594 595 return m_paramPage; 596 } 597 598 /** 599 * Returns the Search Filter.<p> 600 * 601 * @return the Search Filter 602 */ 603 public String getParamSearchFilter() { 604 605 return m_paramSearchFilter; 606 } 607 608 /** 609 * Returns the selected Items.<p> 610 * 611 * @return the selected Items 612 */ 613 public String getParamSelItems() { 614 615 return m_paramSelItems; 616 } 617 618 /** 619 * Returns the sorted Column.<p> 620 * 621 * @return the sorted Column 622 */ 623 public String getParamSortCol() { 624 625 return m_paramSortCol; 626 } 627 628 /** 629 * Returns the current selected item.<p> 630 * 631 * @return the current selected item 632 */ 633 public CmsListItem getSelectedItem() { 634 635 try { 636 return getList().getItem( 637 CmsStringUtil.splitAsArray(getParamSelItems(), CmsHtmlList.ITEM_SEPARATOR)[0].trim()); 638 } catch (Exception e) { 639 try { 640 return getList().getItem(""); 641 } catch (Exception e1) { 642 return null; 643 } 644 } 645 } 646 647 /** 648 * Returns a list of current selected items.<p> 649 * 650 * @return a list of current selected items 651 */ 652 public List<CmsListItem> getSelectedItems() { 653 654 Iterator<String> it = CmsStringUtil.splitAsList( 655 getParamSelItems(), 656 CmsHtmlList.ITEM_SEPARATOR, 657 true).iterator(); 658 List<CmsListItem> items = new ArrayList<CmsListItem>(); 659 while (it.hasNext()) { 660 String id = it.next(); 661 items.add(getList().getItem(id)); 662 } 663 return items; 664 } 665 666 /** 667 * Returns the activation flag.<p> 668 * 669 * Useful for dialogs with several lists.<p> 670 * 671 * Is <code></code> if the original <code>formname</code> parameter 672 * is equals to <code>${listId}-form</code>.<p> 673 * 674 * @return the activation flag 675 */ 676 public boolean isActive() { 677 678 return m_active; 679 } 680 681 /** 682 * This method re-read the rows of the list, the user should call this method after executing an action 683 * that add or remove rows to the list.<p> 684 */ 685 public synchronized void refreshList() { 686 687 if (getList() == null) { 688 return; 689 } 690 if (LOG.isDebugEnabled()) { 691 LOG.debug(Messages.get().getBundle().key(Messages.LOG_START_REFRESH_LIST_1, getListId())); 692 } 693 m_listState = getList().getState(); 694 getList().clear(); 695 fillList(); 696 getList().setState(m_listState); 697 m_listState = null; 698 listSave(); 699 if (LOG.isDebugEnabled()) { 700 LOG.debug(Messages.get().getBundle().key(Messages.LOG_END_REFRESH_LIST_1, getListId())); 701 } 702 } 703 704 /** 705 * Removes the list from the workplace settings.<p> 706 * 707 * Next time the list is displayed the list will be reloaded.<p> 708 */ 709 public void removeList() { 710 711 setList(null); 712 listSave(); 713 } 714 715 /** 716 * Sets the list.<p> 717 * 718 * @param list the list to set 719 */ 720 public void setList(CmsHtmlList list) { 721 722 m_list = list; 723 } 724 725 /** 726 * Stores the given object as "list object" for the given list dialog in the current users session.<p> 727 * 728 * @param listDialog the list dialog class 729 * @param listObject the list to store 730 */ 731 public void setListObject(Class<?> listDialog, CmsHtmlList listObject) { 732 733 if (listObject == null) { 734 // null object: remove the entry from the map 735 getListObjectMap(getSettings()).remove(listDialog.getName()); 736 } else { 737 if ((listObject.getMetadata() != null) && listObject.getMetadata().isVolatile()) { 738 listObject.setMetadata(null); 739 } 740 getListObjectMap(getSettings()).put(listDialog.getName(), listObject); 741 } 742 } 743 744 /** 745 * Sets the form name.<p> 746 * 747 * @param formName the form name to set 748 */ 749 public void setParamFormName(String formName) { 750 751 m_paramFormName = formName; 752 } 753 754 /** 755 * Sets the List Action.<p> 756 * 757 * @param listAction the list Action to set 758 */ 759 public void setParamListAction(String listAction) { 760 761 m_paramListAction = listAction; 762 } 763 764 /** 765 * Sets the current Page.<p> 766 * 767 * @param page the current Page to set 768 */ 769 public void setParamPage(String page) { 770 771 m_paramPage = page; 772 } 773 774 /** 775 * Sets the Search Filter.<p> 776 * 777 * @param searchFilter the Search Filter to set 778 */ 779 public void setParamSearchFilter(String searchFilter) { 780 781 m_paramSearchFilter = searchFilter; 782 } 783 784 /** 785 * Sets the selected Items.<p> 786 * 787 * @param paramSelItems the selected Items to set 788 */ 789 public void setParamSelItems(String paramSelItems) { 790 791 m_paramSelItems = paramSelItems; 792 } 793 794 /** 795 * Sets the sorted Column.<p> 796 * 797 * @param sortCol the sorted Column to set 798 */ 799 public void setParamSortCol(String sortCol) { 800 801 m_paramSortCol = sortCol; 802 } 803 804 /** 805 * Writes the dialog html code, only if the <code>{@link #ACTION_DEFAULT}</code> is set.<p> 806 * 807 * @throws IOException if writing to the JSP out fails, or in case of errros forwarding to the required result page 808 */ 809 public void writeDialog() throws IOException { 810 811 if (isForwarded()) { 812 return; 813 } 814 if (LOG.isDebugEnabled()) { 815 LOG.debug(Messages.get().getBundle().key(Messages.LOG_START_WRITE_LIST_1, getListId())); 816 } 817 JspWriter out = getJsp().getJspContext().getOut(); 818 out.print(defaultActionHtml()); 819 if (LOG.isDebugEnabled()) { 820 LOG.debug(Messages.get().getBundle().key(Messages.LOG_END_WRITE_LIST_1, getListId())); 821 } 822 } 823 824 /** 825 * Can be overwritten to add some code after the list.<p> 826 * 827 * @return custom html code 828 */ 829 protected String customHtmlEnd() { 830 831 return dialogContentEnd(); 832 } 833 834 /** 835 * Can be overwritten to add some code before the list.<p> 836 * 837 * @return custom html code 838 */ 839 protected String customHtmlStart() { 840 841 return ""; 842 } 843 844 /** 845 * Returns the html code for the default action content.<p> 846 * 847 * @return html code 848 */ 849 protected String defaultActionHtmlContent() { 850 851 StringBuffer result = new StringBuffer(2048); 852 result.append("<form name='"); 853 result.append(getList().getId()); 854 result.append("-form' action='"); 855 result.append(getDialogRealUri()); 856 result.append("' method='post' class='nomargin'"); 857 if (getList().getMetadata().isSearchable()) { 858 result.append(" onsubmit=\"listSearchAction('"); 859 result.append(getList().getId()); 860 result.append("', '"); 861 result.append(getList().getMetadata().getSearchAction().getId()); 862 result.append("', '"); 863 result.append(getList().getMetadata().getSearchAction().getConfirmationMessage().key(getLocale())); 864 result.append("');\""); 865 } 866 result.append(">\n"); 867 result.append(allParamsAsHidden()); 868 result.append("\n"); 869 getList().setWp(this); 870 result.append(getList().listHtml()); 871 result.append("\n</form>\n"); 872 return result.toString(); 873 } 874 875 /** 876 * Generates the dialog ending html code.<p> 877 * 878 * @return html code 879 */ 880 protected String defaultActionHtmlEnd() { 881 882 StringBuffer result = new StringBuffer(2048); 883 result.append(dialogEnd()); 884 result.append(bodyEnd()); 885 result.append(htmlEnd()); 886 return result.toString(); 887 } 888 889 /** 890 * Generates the dialog starting html code.<p> 891 * 892 * @return html code 893 */ 894 protected String defaultActionHtmlStart() { 895 896 StringBuffer result = new StringBuffer(2048); 897 result.append(htmlStart(null)); 898 result.append(getList().listJs()); 899 result.append(bodyStart("dialog", null)); 900 result.append(dialogStart()); 901 result.append(dialogContentStart(getParamTitle())); 902 return result.toString(); 903 } 904 905 /** 906 * Filter a list, given the action is set to <code>LIST_SEARCH</code> and 907 * the filter text is set in the <code>PARAM_SEARCH_FILTER</code> parameter.<p> 908 */ 909 protected void executeSearch() { 910 911 getList().setSearchFilter(getParamSearchFilter()); 912 } 913 914 /** 915 * Select a page, given the action is set to <code>LIST_SELECT_PAGE</code> and 916 * the page to go to is set in the <code>PARAM_PAGE</code> parameter.<p> 917 */ 918 protected void executeSelectPage() { 919 920 int page = Integer.valueOf(getParamPage()).intValue(); 921 getList().setCurrentPage(page); 922 } 923 924 /** 925 * Sort the list, given the action is set to <code>LIST_SORT</code> and 926 * the sort column is set in the <code>PARAM_SORT_COL</code> parameter.<p> 927 */ 928 protected void executeSort() { 929 930 getList().setSortedColumn(getParamSortCol()); 931 } 932 933 /** 934 * Lazy initialization for detail data.<p> 935 * 936 * Should fill the given detail column for every list item in <code>{@link CmsHtmlList#getContent()}</code> 937 * 938 * Should not throw any kind of exception.<p> 939 * 940 * @param detailId the id of the detail to initialize 941 */ 942 protected abstract void fillDetails(String detailId); 943 944 /** 945 * Calls the <code>{@link #getListItems}</code> method and catches any exception.<p> 946 */ 947 protected void fillList() { 948 949 try { 950 getList().setContent(getListItems()); 951 // initialize detail columns 952 Iterator<CmsListItemDetails> itDetails = getList().getMetadata().getItemDetailDefinitions().iterator(); 953 while (itDetails.hasNext()) { 954 initializeDetail(itDetails.next().getId()); 955 } 956 } catch (Exception e) { 957 throw new CmsRuntimeException( 958 Messages.get().container(Messages.ERR_LIST_FILL_1, getList().getName().key(getLocale()), null), 959 e); 960 } 961 } 962 963 /** 964 * Should generate a list with the list items to be displayed.<p> 965 * 966 * @return a list of <code>{@link CmsListItem}</code>s 967 * 968 * @throws CmsException if something goes wrong 969 */ 970 protected abstract List<CmsListItem> getListItems() throws CmsException; 971 972 /** 973 * Returns the current list state.<p> 974 * 975 * @return the current list state 976 */ 977 protected CmsListState getListState() { 978 979 if (m_listState != null) { 980 // in case of refreshList call 981 return m_listState; 982 } 983 return getList().getState(); 984 } 985 986 /** 987 * Gets the list metadata cache.<p> 988 * 989 * @return the list metadata cache 990 */ 991 protected Map<String, CmsListMetadata> getMetadataCache() { 992 993 return m_metadatas; 994 } 995 996 /** 997 * Lazy details initialization.<p> 998 * 999 * @param detailId the id of the detail column 1000 */ 1001 protected void initializeDetail(String detailId) { 1002 1003 // if detail column visible or printable 1004 CmsListItemDetails details = getList().getMetadata().getItemDetailDefinition(detailId); 1005 if (details.isVisible() || details.isPrintable()) { 1006 // if the list is not empty 1007 if (getList().getTotalSize() > 0) { 1008 // if the detail column has not been previously initialized 1009 if (getList().getAllContent().get(0).get(detailId) == null) { 1010 if (LOG.isDebugEnabled()) { 1011 LOG.debug( 1012 Messages.get().getBundle().key(Messages.LOG_START_DETAILS_LIST_2, getListId(), detailId)); 1013 } 1014 fillDetails(detailId); 1015 if (LOG.isDebugEnabled()) { 1016 LOG.debug( 1017 Messages.get().getBundle().key(Messages.LOG_END_DETAILS_LIST_2, getListId(), detailId)); 1018 } 1019 } 1020 } 1021 } 1022 } 1023 1024 /** 1025 * @see org.opencms.workplace.CmsWorkplace#initWorkplaceRequestValues(org.opencms.workplace.CmsWorkplaceSettings, jakarta.servlet.http.HttpServletRequest) 1026 */ 1027 @Override 1028 protected void initWorkplaceRequestValues(CmsWorkplaceSettings settings, HttpServletRequest request) { 1029 1030 super.initWorkplaceRequestValues(settings, request); 1031 // set the action for the JSP switch 1032 if (LIST_SEARCH.equals(getParamAction())) { 1033 setAction(ACTION_LIST_SEARCH); 1034 } else if (LIST_SORT.equals(getParamAction())) { 1035 setAction(ACTION_LIST_SORT); 1036 } else if (LIST_SELECT_PAGE.equals(getParamAction())) { 1037 setAction(ACTION_LIST_SELECT_PAGE); 1038 } else if (LIST_INDEPENDENT_ACTION.equals(getParamAction())) { 1039 setAction(ACTION_LIST_INDEPENDENT_ACTION); 1040 } else if (LIST_SINGLE_ACTION.equals(getParamAction())) { 1041 setAction(ACTION_LIST_SINGLE_ACTION); 1042 } else if (LIST_MULTI_ACTION.equals(getParamAction())) { 1043 setAction(ACTION_LIST_MULTI_ACTION); 1044 } 1045 setParamStyle(CmsToolDialog.STYLE_NEW); 1046 // test the needed parameters 1047 try { 1048 validateParamaters(); 1049 } catch (Exception e) { 1050 // redirect to parent if parameters not available 1051 setAction(ACTION_CANCEL); 1052 try { 1053 actionCloseDialog(); 1054 } catch (JspException e1) { 1055 // noop 1056 } 1057 return; 1058 } 1059 } 1060 1061 /** 1062 * Recover the last list instance that is read from the request attributes.<p> 1063 * 1064 * This is required for keep the whole list in memory while you browse a page.<p> 1065 * 1066 * @param listId the id of the expected list 1067 */ 1068 protected synchronized void listRecovery(String listId) { 1069 1070 CmsHtmlList list = getListObject(this.getClass(), getSettings()); 1071 if ((list != null) && !list.getId().equals(listId)) { 1072 list = null; 1073 } 1074 setList(list); 1075 } 1076 1077 /** 1078 * Save the state of the list in the session.<p> 1079 */ 1080 protected synchronized void listSave() { 1081 1082 setListObject(this.getClass(), getList()); 1083 } 1084 1085 /** 1086 * Should create the columns and add them to the given list metadata object.<p> 1087 * 1088 * This method will be just executed once, the first time the constructor is called.<p> 1089 * 1090 * @param metadata the list metadata 1091 */ 1092 protected abstract void setColumns(CmsListMetadata metadata); 1093 1094 /** 1095 * Should add the independent actions to the given list metadata object.<p> 1096 * 1097 * This method will be just executed once, the first time the constructor is called.<p> 1098 * 1099 * @param metadata the list metadata 1100 */ 1101 protected abstract void setIndependentActions(CmsListMetadata metadata); 1102 1103 /** 1104 * Should add the multi actions to the given list metadata object.<p> 1105 * 1106 * This method will be just executed once, the first time the constructor is called.<p> 1107 * 1108 * @param metadata the list metadata 1109 */ 1110 protected abstract void setMultiActions(CmsListMetadata metadata); 1111 1112 /** 1113 * Creates the default search action.<p> 1114 * 1115 * Can be overridden for more sophisticated search.<p> 1116 * 1117 * @param metadata the metadata of the list to do searchable 1118 * @param columnId the if of the column to search into 1119 */ 1120 protected void setSearchAction(CmsListMetadata metadata, String columnId) { 1121 1122 CmsListColumnDefinition col = metadata.getColumnDefinition(columnId); 1123 if ((columnId != null) && (col != null)) { 1124 if (metadata.getSearchAction() == null) { 1125 // makes the list searchable 1126 CmsListSearchAction searchAction = new CmsListSearchAction(col); 1127 searchAction.useDefaultShowAllAction(); 1128 metadata.setSearchAction(searchAction); 1129 } 1130 } 1131 } 1132 1133 /** 1134 * A convenient method to throw a list unsupported 1135 * action runtime exception.<p> 1136 * 1137 * Should be triggered if your list implementation does not 1138 * support the <code>{@link #getParamListAction()}</code> 1139 * action.<p> 1140 * 1141 * @throws CmsRuntimeException always to signal that this operation is not supported 1142 */ 1143 protected void throwListUnsupportedActionException() throws CmsRuntimeException { 1144 1145 throw new CmsRuntimeException( 1146 Messages.get().container( 1147 Messages.ERR_LIST_UNSUPPORTED_ACTION_2, 1148 getList().getName().key(getLocale()), 1149 getParamListAction())); 1150 } 1151 1152 /** 1153 * Should be overridden for parameter validation.<p> 1154 * 1155 * @throws Exception if the parameters are not valid 1156 */ 1157 protected void validateParamaters() throws Exception { 1158 1159 // valid by default 1160 } 1161}