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.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 javax.servlet.ServletException; 050import javax.servlet.http.HttpServletRequest; 051import javax.servlet.jsp.JspException; 052import javax.servlet.jsp.JspWriter; 053 054import org.apache.commons.logging.Log; 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(Messages.LOG_END_ACTION_LIST_2, getListId(), Integer.valueOf(getAction()))); 377 } 378 refreshList(); 379 } 380 381 /** 382 * Generates the dialog starting html code.<p> 383 * 384 * @return html code 385 */ 386 public String defaultActionHtml() { 387 388 if ((getList() != null) && getList().getAllContent().isEmpty()) { 389 // TODO: check the need for this 390 refreshList(); 391 } 392 StringBuffer result = new StringBuffer(2048); 393 result.append(defaultActionHtmlStart()); 394 result.append(customHtmlStart()); 395 result.append(defaultActionHtmlContent()); 396 result.append(customHtmlEnd()); 397 result.append(defaultActionHtmlEnd()); 398 return result.toString(); 399 } 400 401 /** 402 * Performs the dialog actions depending on the initialized action and displays the dialog form.<p> 403 * 404 * @throws JspException if dialog actions fail 405 * @throws IOException if writing to the JSP out fails, or in case of errors forwarding to the required result page 406 * @throws ServletException in case of errors forwarding to the required result page 407 */ 408 public void displayDialog() throws JspException, IOException, ServletException { 409 410 displayDialog(false); 411 } 412 413 /** 414 * Performs the dialog actions depending on the initialized action and displays the dialog form if needed.<p> 415 * 416 * @param writeLater if <code>true</code> no output is written, 417 * you have to call manually the <code>{@link #defaultActionHtml()}</code> method. 418 * 419 * @throws JspException if dialog actions fail 420 * @throws IOException if writing to the JSP out fails, or in case of errors forwarding to the required result page 421 * @throws ServletException in case of errors forwarding to the required result page 422 */ 423 public void displayDialog(boolean writeLater) throws JspException, IOException, ServletException { 424 425 actionDialog(); 426 if (writeLater) { 427 return; 428 } 429 writeDialog(); 430 } 431 432 /** 433 * This method execute the default actions for searching, sorting and paging.<p> 434 */ 435 public void executeDefaultActions() { 436 437 switch (getAction()) { 438 439 case ACTION_LIST_SEARCH: 440 executeSearch(); 441 break; 442 case ACTION_LIST_SORT: 443 executeSort(); 444 break; 445 case ACTION_LIST_SELECT_PAGE: 446 executeSelectPage(); 447 break; 448 default: 449 // ignore 450 } 451 listSave(); 452 } 453 454 /** 455 * This method should handle the default list independent actions, 456 * by comparing <code>{@link #getParamListAction()}</code> with the id 457 * of the action to execute.<p> 458 * 459 * if you want to handle additional independent actions, override this method, 460 * handling your actions and FINALLY calling <code>super.executeListIndepActions();</code>.<p> 461 */ 462 public void executeListIndepActions() { 463 464 if (getList().getMetadata().getItemDetailDefinition(getParamListAction()) != null) { 465 // toggle item details 466 getList().getMetadata().toogleDetailState(getParamListAction()); 467 // lazy initialization 468 initializeDetail(getParamListAction()); 469 } 470 listSave(); 471 } 472 473 /** 474 * This method should handle every defined list multi action, 475 * by comparing <code>{@link #getParamListAction()}</code> with the id 476 * of the action to execute.<p> 477 * 478 * @throws IOException in case of errors when including a required sub-element 479 * @throws ServletException in case of errors when including a required sub-element 480 * @throws CmsRuntimeException to signal that an action is not supported 481 */ 482 public abstract void executeListMultiActions() throws IOException, ServletException, CmsRuntimeException; 483 484 /** 485 * This method should handle every defined list single action, 486 * by comparing <code>{@link #getParamListAction()}</code> with the id 487 * of the action to execute.<p> 488 * 489 * @throws IOException in case of errors when including a required sub-element 490 * @throws ServletException in case of errors when including a required sub-element 491 * @throws CmsRuntimeException to signal that an action is not supported 492 */ 493 public abstract void executeListSingleActions() throws IOException, ServletException, CmsRuntimeException; 494 495 /** 496 * Returns the list.<p> 497 * 498 * @return the list 499 */ 500 public CmsHtmlList getList() { 501 502 if ((m_list != null) && (m_list.getMetadata() == null)) { 503 m_list.setMetadata(getMetadata(getClass().getName(), m_list.getId())); 504 } 505 return m_list; 506 } 507 508 /** 509 * Returns the Id of the list.<p> 510 * 511 * @return the list Id 512 */ 513 public final String getListId() { 514 515 return m_listId; 516 } 517 518 /** 519 * Returns the list metadata object for the given dialog.<p> 520 * 521 * @param listDialogName the dialog class name 522 * 523 * @return the list metadata object 524 */ 525 public CmsListMetadata getMetadata(String listDialogName) { 526 527 return getMetadataCache().get(listDialogName); 528 } 529 530 /** 531 * Should generate the metadata definition for the list, and return the 532 * corresponding <code>{@link CmsListMetadata}</code> object.<p> 533 * 534 * @param listDialogName the name of the class generating the list 535 * @param listId the id of the list 536 * 537 * @return The metadata for the given list 538 */ 539 public synchronized CmsListMetadata getMetadata(String listDialogName, String listId) { 540 541 getSettings(); 542 String metaDataKey = listDialogName + listId; 543 544 if ((getMetadataCache().get(metaDataKey) == null) || getMetadataCache().get(metaDataKey).isVolatile()) { 545 if (LOG.isDebugEnabled()) { 546 LOG.debug(Messages.get().getBundle().key(Messages.LOG_START_METADATA_LIST_1, getListId())); 547 } 548 CmsListMetadata metadata = new CmsListMetadata(listId); 549 550 setColumns(metadata); 551 // always check the search action 552 setSearchAction(metadata, m_searchColId); 553 setIndependentActions(metadata); 554 metadata.addIndependentAction(new CmsListPrintIAction()); 555 setMultiActions(metadata); 556 metadata.checkIds(); 557 getMetadataCache().put(metaDataKey, metadata); 558 if (LOG.isDebugEnabled()) { 559 LOG.debug(Messages.get().getBundle().key(Messages.LOG_END_METADATA_LIST_1, getListId())); 560 } 561 } 562 return getMetadata(metaDataKey); 563 } 564 565 /** 566 * Returns the form name.<p> 567 * 568 * @return the form name 569 */ 570 public String getParamFormName() { 571 572 return m_paramFormName; 573 } 574 575 /** 576 * Returns the List Action.<p> 577 * 578 * @return the List Action 579 */ 580 public String getParamListAction() { 581 582 return m_paramListAction; 583 } 584 585 /** 586 * Returns the current Page.<p> 587 * 588 * @return the current Page 589 */ 590 public String getParamPage() { 591 592 return m_paramPage; 593 } 594 595 /** 596 * Returns the Search Filter.<p> 597 * 598 * @return the Search Filter 599 */ 600 public String getParamSearchFilter() { 601 602 return m_paramSearchFilter; 603 } 604 605 /** 606 * Returns the selected Items.<p> 607 * 608 * @return the selected Items 609 */ 610 public String getParamSelItems() { 611 612 return m_paramSelItems; 613 } 614 615 /** 616 * Returns the sorted Column.<p> 617 * 618 * @return the sorted Column 619 */ 620 public String getParamSortCol() { 621 622 return m_paramSortCol; 623 } 624 625 /** 626 * Returns the current selected item.<p> 627 * 628 * @return the current selected item 629 */ 630 public CmsListItem getSelectedItem() { 631 632 try { 633 return getList().getItem( 634 CmsStringUtil.splitAsArray(getParamSelItems(), CmsHtmlList.ITEM_SEPARATOR)[0].trim()); 635 } catch (Exception e) { 636 try { 637 return getList().getItem(""); 638 } catch (Exception e1) { 639 return null; 640 } 641 } 642 } 643 644 /** 645 * Returns a list of current selected items.<p> 646 * 647 * @return a list of current selected items 648 */ 649 public List<CmsListItem> getSelectedItems() { 650 651 Iterator<String> it = CmsStringUtil.splitAsList( 652 getParamSelItems(), 653 CmsHtmlList.ITEM_SEPARATOR, 654 true).iterator(); 655 List<CmsListItem> items = new ArrayList<CmsListItem>(); 656 while (it.hasNext()) { 657 String id = it.next(); 658 items.add(getList().getItem(id)); 659 } 660 return items; 661 } 662 663 /** 664 * Returns the activation flag.<p> 665 * 666 * Useful for dialogs with several lists.<p> 667 * 668 * Is <code></code> if the original <code>formname</code> parameter 669 * is equals to <code>${listId}-form</code>.<p> 670 * 671 * @return the activation flag 672 */ 673 public boolean isActive() { 674 675 return m_active; 676 } 677 678 /** 679 * This method re-read the rows of the list, the user should call this method after executing an action 680 * that add or remove rows to the list.<p> 681 */ 682 public synchronized void refreshList() { 683 684 if (getList() == null) { 685 return; 686 } 687 if (LOG.isDebugEnabled()) { 688 LOG.debug(Messages.get().getBundle().key(Messages.LOG_START_REFRESH_LIST_1, getListId())); 689 } 690 m_listState = getList().getState(); 691 getList().clear(); 692 fillList(); 693 getList().setState(m_listState); 694 m_listState = null; 695 listSave(); 696 if (LOG.isDebugEnabled()) { 697 LOG.debug(Messages.get().getBundle().key(Messages.LOG_END_REFRESH_LIST_1, getListId())); 698 } 699 } 700 701 /** 702 * Removes the list from the workplace settings.<p> 703 * 704 * Next time the list is displayed the list will be reloaded.<p> 705 */ 706 public void removeList() { 707 708 setList(null); 709 listSave(); 710 } 711 712 /** 713 * Sets the list.<p> 714 * 715 * @param list the list to set 716 */ 717 public void setList(CmsHtmlList list) { 718 719 m_list = list; 720 } 721 722 /** 723 * Stores the given object as "list object" for the given list dialog in the current users session.<p> 724 * 725 * @param listDialog the list dialog class 726 * @param listObject the list to store 727 */ 728 public void setListObject(Class<?> listDialog, CmsHtmlList listObject) { 729 730 if (listObject == null) { 731 // null object: remove the entry from the map 732 getListObjectMap(getSettings()).remove(listDialog.getName()); 733 } else { 734 if ((listObject.getMetadata() != null) && listObject.getMetadata().isVolatile()) { 735 listObject.setMetadata(null); 736 } 737 getListObjectMap(getSettings()).put(listDialog.getName(), listObject); 738 } 739 } 740 741 /** 742 * Sets the form name.<p> 743 * 744 * @param formName the form name to set 745 */ 746 public void setParamFormName(String formName) { 747 748 m_paramFormName = formName; 749 } 750 751 /** 752 * Sets the List Action.<p> 753 * 754 * @param listAction the list Action to set 755 */ 756 public void setParamListAction(String listAction) { 757 758 m_paramListAction = listAction; 759 } 760 761 /** 762 * Sets the current Page.<p> 763 * 764 * @param page the current Page to set 765 */ 766 public void setParamPage(String page) { 767 768 m_paramPage = page; 769 } 770 771 /** 772 * Sets the Search Filter.<p> 773 * 774 * @param searchFilter the Search Filter to set 775 */ 776 public void setParamSearchFilter(String searchFilter) { 777 778 m_paramSearchFilter = searchFilter; 779 } 780 781 /** 782 * Sets the selected Items.<p> 783 * 784 * @param paramSelItems the selected Items to set 785 */ 786 public void setParamSelItems(String paramSelItems) { 787 788 m_paramSelItems = paramSelItems; 789 } 790 791 /** 792 * Sets the sorted Column.<p> 793 * 794 * @param sortCol the sorted Column to set 795 */ 796 public void setParamSortCol(String sortCol) { 797 798 m_paramSortCol = sortCol; 799 } 800 801 /** 802 * Writes the dialog html code, only if the <code>{@link #ACTION_DEFAULT}</code> is set.<p> 803 * 804 * @throws IOException if writing to the JSP out fails, or in case of errros forwarding to the required result page 805 */ 806 public void writeDialog() throws IOException { 807 808 if (isForwarded()) { 809 return; 810 } 811 if (LOG.isDebugEnabled()) { 812 LOG.debug(Messages.get().getBundle().key(Messages.LOG_START_WRITE_LIST_1, getListId())); 813 } 814 JspWriter out = getJsp().getJspContext().getOut(); 815 out.print(defaultActionHtml()); 816 if (LOG.isDebugEnabled()) { 817 LOG.debug(Messages.get().getBundle().key(Messages.LOG_END_WRITE_LIST_1, getListId())); 818 } 819 } 820 821 /** 822 * Can be overwritten to add some code after the list.<p> 823 * 824 * @return custom html code 825 */ 826 protected String customHtmlEnd() { 827 828 return dialogContentEnd(); 829 } 830 831 /** 832 * Can be overwritten to add some code before the list.<p> 833 * 834 * @return custom html code 835 */ 836 protected String customHtmlStart() { 837 838 return ""; 839 } 840 841 /** 842 * Returns the html code for the default action content.<p> 843 * 844 * @return html code 845 */ 846 protected String defaultActionHtmlContent() { 847 848 StringBuffer result = new StringBuffer(2048); 849 result.append("<form name='"); 850 result.append(getList().getId()); 851 result.append("-form' action='"); 852 result.append(getDialogRealUri()); 853 result.append("' method='post' class='nomargin'"); 854 if (getList().getMetadata().isSearchable()) { 855 result.append(" onsubmit=\"listSearchAction('"); 856 result.append(getList().getId()); 857 result.append("', '"); 858 result.append(getList().getMetadata().getSearchAction().getId()); 859 result.append("', '"); 860 result.append(getList().getMetadata().getSearchAction().getConfirmationMessage().key(getLocale())); 861 result.append("');\""); 862 } 863 result.append(">\n"); 864 result.append(allParamsAsHidden()); 865 result.append("\n"); 866 getList().setWp(this); 867 result.append(getList().listHtml()); 868 result.append("\n</form>\n"); 869 return result.toString(); 870 } 871 872 /** 873 * Generates the dialog ending html code.<p> 874 * 875 * @return html code 876 */ 877 protected String defaultActionHtmlEnd() { 878 879 StringBuffer result = new StringBuffer(2048); 880 result.append(dialogEnd()); 881 result.append(bodyEnd()); 882 result.append(htmlEnd()); 883 return result.toString(); 884 } 885 886 /** 887 * Generates the dialog starting html code.<p> 888 * 889 * @return html code 890 */ 891 protected String defaultActionHtmlStart() { 892 893 StringBuffer result = new StringBuffer(2048); 894 result.append(htmlStart(null)); 895 result.append(getList().listJs()); 896 result.append(bodyStart("dialog", null)); 897 result.append(dialogStart()); 898 result.append(dialogContentStart(getParamTitle())); 899 return result.toString(); 900 } 901 902 /** 903 * Filter a list, given the action is set to <code>LIST_SEARCH</code> and 904 * the filter text is set in the <code>PARAM_SEARCH_FILTER</code> parameter.<p> 905 */ 906 protected void executeSearch() { 907 908 getList().setSearchFilter(getParamSearchFilter()); 909 } 910 911 /** 912 * Select a page, given the action is set to <code>LIST_SELECT_PAGE</code> and 913 * the page to go to is set in the <code>PARAM_PAGE</code> parameter.<p> 914 */ 915 protected void executeSelectPage() { 916 917 int page = Integer.valueOf(getParamPage()).intValue(); 918 getList().setCurrentPage(page); 919 } 920 921 /** 922 * Sort the list, given the action is set to <code>LIST_SORT</code> and 923 * the sort column is set in the <code>PARAM_SORT_COL</code> parameter.<p> 924 */ 925 protected void executeSort() { 926 927 getList().setSortedColumn(getParamSortCol()); 928 } 929 930 /** 931 * Lazy initialization for detail data.<p> 932 * 933 * Should fill the given detail column for every list item in <code>{@link CmsHtmlList#getContent()}</code> 934 * 935 * Should not throw any kind of exception.<p> 936 * 937 * @param detailId the id of the detail to initialize 938 */ 939 protected abstract void fillDetails(String detailId); 940 941 /** 942 * Calls the <code>{@link #getListItems}</code> method and catches any exception.<p> 943 */ 944 protected void fillList() { 945 946 try { 947 getList().setContent(getListItems()); 948 // initialize detail columns 949 Iterator<CmsListItemDetails> itDetails = getList().getMetadata().getItemDetailDefinitions().iterator(); 950 while (itDetails.hasNext()) { 951 initializeDetail(itDetails.next().getId()); 952 } 953 } catch (Exception e) { 954 throw new CmsRuntimeException( 955 Messages.get().container(Messages.ERR_LIST_FILL_1, getList().getName().key(getLocale()), null), 956 e); 957 } 958 } 959 960 /** 961 * Should generate a list with the list items to be displayed.<p> 962 * 963 * @return a list of <code>{@link CmsListItem}</code>s 964 * 965 * @throws CmsException if something goes wrong 966 */ 967 protected abstract List<CmsListItem> getListItems() throws CmsException; 968 969 /** 970 * Returns the current list state.<p> 971 * 972 * @return the current list state 973 */ 974 protected CmsListState getListState() { 975 976 if (m_listState != null) { 977 // in case of refreshList call 978 return m_listState; 979 } 980 return getList().getState(); 981 } 982 983 /** 984 * Gets the list metadata cache.<p> 985 * 986 * @return the list metadata cache 987 */ 988 protected Map<String, CmsListMetadata> getMetadataCache() { 989 990 return m_metadatas; 991 } 992 993 /** 994 * Lazy details initialization.<p> 995 * 996 * @param detailId the id of the detail column 997 */ 998 protected void initializeDetail(String detailId) { 999 1000 // if detail column visible or printable 1001 CmsListItemDetails details = getList().getMetadata().getItemDetailDefinition(detailId); 1002 if (details.isVisible() || details.isPrintable()) { 1003 // if the list is not empty 1004 if (getList().getTotalSize() > 0) { 1005 // if the detail column has not been previously initialized 1006 if (getList().getAllContent().get(0).get(detailId) == null) { 1007 if (LOG.isDebugEnabled()) { 1008 LOG.debug( 1009 Messages.get().getBundle().key(Messages.LOG_START_DETAILS_LIST_2, getListId(), detailId)); 1010 } 1011 fillDetails(detailId); 1012 if (LOG.isDebugEnabled()) { 1013 LOG.debug( 1014 Messages.get().getBundle().key(Messages.LOG_END_DETAILS_LIST_2, getListId(), detailId)); 1015 } 1016 } 1017 } 1018 } 1019 } 1020 1021 /** 1022 * @see org.opencms.workplace.CmsWorkplace#initWorkplaceRequestValues(org.opencms.workplace.CmsWorkplaceSettings, javax.servlet.http.HttpServletRequest) 1023 */ 1024 @Override 1025 protected void initWorkplaceRequestValues(CmsWorkplaceSettings settings, HttpServletRequest request) { 1026 1027 super.initWorkplaceRequestValues(settings, request); 1028 // set the action for the JSP switch 1029 if (LIST_SEARCH.equals(getParamAction())) { 1030 setAction(ACTION_LIST_SEARCH); 1031 } else if (LIST_SORT.equals(getParamAction())) { 1032 setAction(ACTION_LIST_SORT); 1033 } else if (LIST_SELECT_PAGE.equals(getParamAction())) { 1034 setAction(ACTION_LIST_SELECT_PAGE); 1035 } else if (LIST_INDEPENDENT_ACTION.equals(getParamAction())) { 1036 setAction(ACTION_LIST_INDEPENDENT_ACTION); 1037 } else if (LIST_SINGLE_ACTION.equals(getParamAction())) { 1038 setAction(ACTION_LIST_SINGLE_ACTION); 1039 } else if (LIST_MULTI_ACTION.equals(getParamAction())) { 1040 setAction(ACTION_LIST_MULTI_ACTION); 1041 } 1042 setParamStyle(CmsToolDialog.STYLE_NEW); 1043 // test the needed parameters 1044 try { 1045 validateParamaters(); 1046 } catch (Exception e) { 1047 // redirect to parent if parameters not available 1048 setAction(ACTION_CANCEL); 1049 try { 1050 actionCloseDialog(); 1051 } catch (JspException e1) { 1052 // noop 1053 } 1054 return; 1055 } 1056 } 1057 1058 /** 1059 * Recover the last list instance that is read from the request attributes.<p> 1060 * 1061 * This is required for keep the whole list in memory while you browse a page.<p> 1062 * 1063 * @param listId the id of the expected list 1064 */ 1065 protected synchronized void listRecovery(String listId) { 1066 1067 CmsHtmlList list = getListObject(this.getClass(), getSettings()); 1068 if ((list != null) && !list.getId().equals(listId)) { 1069 list = null; 1070 } 1071 setList(list); 1072 } 1073 1074 /** 1075 * Save the state of the list in the session.<p> 1076 */ 1077 protected synchronized void listSave() { 1078 1079 setListObject(this.getClass(), getList()); 1080 } 1081 1082 /** 1083 * Should create the columns and add them to the given list metadata object.<p> 1084 * 1085 * This method will be just executed once, the first time the constructor is called.<p> 1086 * 1087 * @param metadata the list metadata 1088 */ 1089 protected abstract void setColumns(CmsListMetadata metadata); 1090 1091 /** 1092 * Should add the independent actions to the given list metadata object.<p> 1093 * 1094 * This method will be just executed once, the first time the constructor is called.<p> 1095 * 1096 * @param metadata the list metadata 1097 */ 1098 protected abstract void setIndependentActions(CmsListMetadata metadata); 1099 1100 /** 1101 * Should add the multi actions to the given list metadata object.<p> 1102 * 1103 * This method will be just executed once, the first time the constructor is called.<p> 1104 * 1105 * @param metadata the list metadata 1106 */ 1107 protected abstract void setMultiActions(CmsListMetadata metadata); 1108 1109 /** 1110 * Creates the default search action.<p> 1111 * 1112 * Can be overridden for more sophisticated search.<p> 1113 * 1114 * @param metadata the metadata of the list to do searchable 1115 * @param columnId the if of the column to search into 1116 */ 1117 protected void setSearchAction(CmsListMetadata metadata, String columnId) { 1118 1119 CmsListColumnDefinition col = metadata.getColumnDefinition(columnId); 1120 if ((columnId != null) && (col != null)) { 1121 if (metadata.getSearchAction() == null) { 1122 // makes the list searchable 1123 CmsListSearchAction searchAction = new CmsListSearchAction(col); 1124 searchAction.useDefaultShowAllAction(); 1125 metadata.setSearchAction(searchAction); 1126 } 1127 } 1128 } 1129 1130 /** 1131 * A convenient method to throw a list unsupported 1132 * action runtime exception.<p> 1133 * 1134 * Should be triggered if your list implementation does not 1135 * support the <code>{@link #getParamListAction()}</code> 1136 * action.<p> 1137 * 1138 * @throws CmsRuntimeException always to signal that this operation is not supported 1139 */ 1140 protected void throwListUnsupportedActionException() throws CmsRuntimeException { 1141 1142 throw new CmsRuntimeException( 1143 Messages.get().container( 1144 Messages.ERR_LIST_UNSUPPORTED_ACTION_2, 1145 getList().getName().key(getLocale()), 1146 getParamListAction())); 1147 } 1148 1149 /** 1150 * Should be overridden for parameter validation.<p> 1151 * 1152 * @throws Exception if the parameters are not valid 1153 */ 1154 protected void validateParamaters() throws Exception { 1155 1156 // valid by default 1157 } 1158}