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, 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.ade.galleries.client; 029 030import org.opencms.ade.galleries.client.preview.I_CmsPreviewFactory; 031import org.opencms.ade.galleries.client.preview.I_CmsResourcePreview; 032import org.opencms.ade.galleries.client.ui.CmsSearchTab.ParamType; 033import org.opencms.ade.galleries.shared.CmsGalleryConfiguration; 034import org.opencms.ade.galleries.shared.CmsGalleryDataBean; 035import org.opencms.ade.galleries.shared.CmsGalleryFolderBean; 036import org.opencms.ade.galleries.shared.CmsGallerySearchBean; 037import org.opencms.ade.galleries.shared.CmsGallerySearchScope; 038import org.opencms.ade.galleries.shared.CmsGalleryTreeEntry; 039import org.opencms.ade.galleries.shared.CmsResourceTypeBean; 040import org.opencms.ade.galleries.shared.CmsResourceTypeBean.TypeVisibility; 041import org.opencms.ade.galleries.shared.CmsSiteSelectorOption; 042import org.opencms.ade.galleries.shared.CmsSitemapEntryBean; 043import org.opencms.ade.galleries.shared.CmsVfsEntryBean; 044import org.opencms.ade.galleries.shared.I_CmsBinaryPreviewProvider; 045import org.opencms.ade.galleries.shared.I_CmsGalleryConfiguration; 046import org.opencms.ade.galleries.shared.I_CmsGalleryProviderConstants; 047import org.opencms.ade.galleries.shared.I_CmsGalleryProviderConstants.GalleryMode; 048import org.opencms.ade.galleries.shared.I_CmsGalleryProviderConstants.GalleryTabId; 049import org.opencms.ade.galleries.shared.I_CmsGalleryProviderConstants.SortParams; 050import org.opencms.ade.galleries.shared.rpc.I_CmsGalleryService; 051import org.opencms.ade.galleries.shared.rpc.I_CmsGalleryServiceAsync; 052import org.opencms.gwt.client.CmsCoreProvider; 053import org.opencms.gwt.client.rpc.CmsRpcAction; 054import org.opencms.gwt.client.ui.CmsDeleteWarningDialog; 055import org.opencms.gwt.client.ui.CmsErrorDialog; 056import org.opencms.gwt.client.util.CmsClientCollectionUtil; 057import org.opencms.gwt.client.util.CmsDebugLog; 058import org.opencms.gwt.client.util.CmsJsUtil; 059import org.opencms.gwt.client.util.I_CmsSimpleCallback; 060import org.opencms.gwt.shared.CmsCategoryBean; 061import org.opencms.gwt.shared.CmsCategoryTreeEntry; 062import org.opencms.gwt.shared.CmsGalleryContainerInfo; 063import org.opencms.gwt.shared.CmsTemplateContextInfo; 064import org.opencms.gwt.shared.rpc.I_CmsVfsServiceAsync; 065import org.opencms.gwt.shared.sort.CmsComparatorPath; 066import org.opencms.gwt.shared.sort.CmsComparatorTitle; 067import org.opencms.gwt.shared.sort.CmsComparatorType; 068import org.opencms.util.CmsStringUtil; 069import org.opencms.util.CmsUUID; 070 071import java.util.ArrayList; 072import java.util.Arrays; 073import java.util.Collections; 074import java.util.HashMap; 075import java.util.HashSet; 076import java.util.List; 077import java.util.Map; 078import java.util.Set; 079import java.util.function.Supplier; 080 081import com.google.common.collect.ComparisonChain; 082import com.google.common.collect.Lists; 083import com.google.gwt.core.client.GWT; 084import com.google.gwt.core.client.JavaScriptObject; 085import com.google.gwt.event.logical.shared.HasValueChangeHandlers; 086import com.google.gwt.event.logical.shared.ValueChangeEvent; 087import com.google.gwt.event.logical.shared.ValueChangeHandler; 088import com.google.gwt.event.shared.GwtEvent; 089import com.google.gwt.event.shared.HandlerRegistration; 090import com.google.gwt.event.shared.SimpleEventBus; 091import com.google.gwt.user.client.Command; 092import com.google.gwt.user.client.rpc.AsyncCallback; 093import com.google.gwt.user.client.rpc.ServiceDefTarget; 094 095/** 096 * Gallery dialog controller.<p> 097 * 098 * This class handles the communication between gallery dialog and the server. 099 * It contains the gallery data, but no references to the gallery dialog widget. 100 * 101 * @since 8.0.0 102 */ 103public class CmsGalleryController implements HasValueChangeHandlers<CmsGallerySearchBean> { 104 105 /** The gallery service instance. */ 106 private static I_CmsGalleryServiceAsync m_gallerySvc; 107 108 /** The preview factory registration. */ 109 private static Map<String, I_CmsPreviewFactory> m_previewFactoryRegistration = new HashMap<String, I_CmsPreviewFactory>(); 110 111 /** The current load results call id. */ 112 protected int m_currentCallId; 113 114 /** The gallery dialog bean. */ 115 protected CmsGalleryDataBean m_dialogBean; 116 117 /** The gallery dialog mode. */ 118 protected I_CmsGalleryProviderConstants.GalleryMode m_dialogMode; 119 120 /** The event bus. */ 121 protected SimpleEventBus m_eventBus; 122 123 /** The gallery controller handler. */ 124 protected CmsGalleryControllerHandler m_handler; 125 126 /** Flag to indicate that a load results request is currently running. */ 127 protected boolean m_loading; 128 129 /** The gallery search object. */ 130 protected CmsGallerySearchBean m_searchObject; 131 132 /** The gallery configuration. */ 133 private I_CmsGalleryConfiguration m_configuration; 134 135 /** Provides container information for the gallery dialog. */ 136 private Supplier<CmsGalleryContainerInfo> m_containerInfoProvider = () -> null; 137 138 /** The current resource preview. */ 139 private I_CmsResourcePreview<?> m_currentPreview; 140 141 /** Flag to record whether the user changed the gallery selection. */ 142 private boolean m_galleriesChanged; 143 144 /** Flag which controls whether the galleries in the gallery tab should be selectable. */ 145 private boolean m_galleriesSelectable; 146 147 /** Flag which indicates whether the site selector should be shown. */ 148 private boolean m_isShowSiteSelector = true; 149 150 /** Flag which controls whether the results should be selectable. If this is false, the results will not be selectable, but if it is true, the results may still be unselectable for a different reason. */ 151 private boolean m_resultsSelectable = true; 152 153 /** If <code>true</code> the search object is changed <code>false</code> otherwise. */ 154 private boolean m_searchObjectChanged = true; 155 156 /** The search able resource types. */ 157 private List<CmsResourceTypeBean> m_searchTypes; 158 159 /** The start site to set for the site selector. */ 160 private String m_startSite; 161 162 /** The configured tabs. */ 163 private GalleryTabId[] m_tabIds; 164 165 /** Provides the template context information. */ 166 private Supplier<CmsTemplateContextInfo> m_templateContextInfoProvider = () -> null; 167 168 /** The tree token for this gallery instance (determines which tree open state to use). */ 169 private String m_treeToken; 170 171 /** The vfs service. */ 172 private I_CmsVfsServiceAsync m_vfsService; 173 174 /** 175 * Constructor.<p> 176 * 177 * @param handler the controller handler 178 * @param dialogBean the gallery data 179 * @param searchBean the prefetched search 180 */ 181 public CmsGalleryController( 182 CmsGalleryControllerHandler handler, 183 CmsGalleryDataBean dialogBean, 184 CmsGallerySearchBean searchBean) { 185 186 m_handler = handler; 187 m_eventBus = new SimpleEventBus(); 188 addValueChangeHandler(m_handler); 189 JavaScriptObject embeddedConfig = CmsJsUtil.getAttribute(CmsJsUtil.getWindow(), "embeddedConfiguration"); 190 if (embeddedConfig != null) { 191 CmsGalleryConfigurationJSO config = embeddedConfig.cast(); 192 m_handler.m_galleryDialog.setOverrideFormats(true); 193 m_handler.m_galleryDialog.setUseFormats(config.isUseFormats()); 194 m_handler.m_galleryDialog.setImageFormats(config.getImageFormats()); 195 m_handler.m_galleryDialog.setImageFormatNames(config.getImageFormatNames()); 196 } 197 m_dialogBean = dialogBean; 198 m_searchObject = searchBean; 199 m_dialogMode = m_dialogBean.getMode(); 200 201 if (m_searchObject == null) { 202 m_searchObject = new CmsGallerySearchBean(); 203 m_searchObject.setOriginalGalleryData(dialogBean); 204 m_searchObject.setGalleryMode(m_dialogMode); 205 m_searchObject.setIgnoreSearchExclude(m_dialogMode != GalleryMode.ade); 206 m_searchObject.setLocale(m_dialogBean.getLocale()); 207 m_searchObject.setScope(m_dialogBean.getScope()); 208 m_searchObject.setSortOrder(m_dialogBean.getSortOrder().name()); 209 m_searchObject.setGalleryStoragePrefix(m_dialogBean.getGalleryStoragePrefix()); 210 if (m_dialogBean.getStartFolderFilter() != null) { 211 m_searchObject.setFolders(m_dialogBean.getStartFolderFilter()); 212 } 213 } 214 if (m_dialogBean != null) { 215 m_tabIds = m_dialogBean.getTabIds(); 216 m_handler.onInitialSearch(m_searchObject, m_dialogBean, this, true); 217 } 218 } 219 220 /** 221 * Constructor.<p> 222 * 223 * @param handler the controller handler 224 * @param conf the gallery configuration 225 */ 226 public CmsGalleryController(CmsGalleryControllerHandler handler, final I_CmsGalleryConfiguration conf) { 227 228 m_configuration = conf; 229 m_resultsSelectable = conf.isResultsSelectable(); 230 m_galleriesSelectable = conf.isGalleriesSelectable(); 231 m_handler = handler; 232 m_handler.m_galleryDialog.setUseFormats(m_configuration.isUseFormats()); 233 m_handler.m_galleryDialog.setImageFormats(m_configuration.getImageFormats()); 234 m_handler.m_galleryDialog.setImageFormatNames(m_configuration.getImageFormatNames()); 235 m_eventBus = new SimpleEventBus(); 236 addValueChangeHandler(m_handler); 237 m_treeToken = m_configuration.getTreeToken(); 238 CmsRpcAction<CmsGalleryDataBean> initAction = new CmsRpcAction<CmsGalleryDataBean>() { 239 240 @Override 241 public void execute() { 242 243 try { 244 CmsGalleryConfiguration config = new CmsGalleryConfiguration(conf); 245 getGalleryService().getInitialSettings(config, this); 246 } catch (Throwable t) { 247 CmsErrorDialog.handleException(t); 248 } 249 } 250 251 @Override 252 protected void onResponse(CmsGalleryDataBean result) { 253 254 m_dialogBean = result; 255 m_dialogMode = m_dialogBean.getMode(); 256 if (m_dialogBean.getStartTab() != GalleryTabId.cms_tab_results) { 257 List<GalleryTabId> tabs = Arrays.asList(getTabIds()); 258 // in case the selected start tab is not present, choose another one 259 if (!tabs.contains(m_dialogBean.getStartTab())) { 260 if ((m_dialogMode == GalleryMode.widget) && tabs.contains(GalleryTabId.cms_tab_vfstree)) { 261 m_dialogBean.setStartTab(GalleryTabId.cms_tab_vfstree); 262 } else { 263 m_dialogBean.setStartTab(tabs.get(0)); 264 } 265 } 266 } 267 initialSearch(); 268 } 269 }; 270 initAction.execute(); 271 m_tabIds = m_configuration.getTabConfiguration().getTabs().toArray(new GalleryTabId[] {}); 272 setShowSiteSelector(m_configuration.isShowSiteSelector()); 273 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(m_configuration.getStartSite())) { 274 setStartSite(m_configuration.getStartSite()); 275 } 276 } 277 278 /** 279 * Creates a gallery service instance.<p> 280 * 281 * @return the gallery service instance 282 */ 283 public static I_CmsGalleryServiceAsync createGalleryService() { 284 285 I_CmsGalleryServiceAsync service; 286 service = GWT.create(I_CmsGalleryService.class); 287 String serviceUrl = CmsCoreProvider.get().link("org.opencms.ade.galleries.CmsGalleryService.gwt"); 288 ((ServiceDefTarget)service).setServiceEntryPoint(serviceUrl); 289 return service; 290 } 291 292 /** 293 * Returns the gallery service instance.<p> 294 * 295 * @return the gallery service instance 296 */ 297 public static I_CmsGalleryServiceAsync getGalleryService() { 298 299 if (m_gallerySvc == null) { 300 I_CmsGalleryServiceAsync service = createGalleryService(); 301 m_gallerySvc = service; 302 } 303 return m_gallerySvc; 304 } 305 306 /** 307 * Registers a preview factory for the given name. 308 * 309 * @param previewProviderName the preview provider name 310 * @param factory the preview factory 311 */ 312 public static void registerPreviewFactory(String previewProviderName, I_CmsPreviewFactory factory) { 313 314 m_previewFactoryRegistration.put(previewProviderName, factory); 315 } 316 317 /** 318 * Add category to search object.<p> 319 * 320 * @param categoryPath the id of the category to add 321 */ 322 public void addCategory(String categoryPath) { 323 324 m_searchObject.addCategory(categoryPath); 325 m_searchObjectChanged = true; 326 ValueChangeEvent.fire(this, m_searchObject); 327 } 328 329 /** 330 * Sets the created until date to the search object.<p> 331 * 332 * @param end the created until date as long 333 */ 334 public void addDateCreatedEnd(long end) { 335 336 m_searchObject.setDateCreatedEnd(end); 337 m_searchObjectChanged = true; 338 ValueChangeEvent.fire(this, m_searchObject); 339 } 340 341 /** 342 * Sets the created since date to the search object.<p> 343 * 344 * @param start the created since date as long 345 */ 346 public void addDateCreatedStart(long start) { 347 348 m_searchObject.setDateCreatedStart(start); 349 m_searchObjectChanged = true; 350 ValueChangeEvent.fire(this, m_searchObject); 351 } 352 353 /** 354 * Sets the modified until date to the search object.<p> 355 * 356 * @param end the modified until date as long 357 */ 358 public void addDateModifiedEnd(long end) { 359 360 m_searchObject.setDateModifiedEnd(end); 361 m_searchObjectChanged = true; 362 ValueChangeEvent.fire(this, m_searchObject); 363 } 364 365 /** 366 * Sets the modified since date to the search object.<p> 367 * 368 * @param start the modified since date as long 369 */ 370 public void addDateModifiedStart(long start) { 371 372 m_searchObject.setDateModifiedStart(start); 373 m_searchObjectChanged = true; 374 ValueChangeEvent.fire(this, m_searchObject); 375 } 376 377 /** 378 * Adds a folder to the current search object.<p> 379 * 380 * @param folder the folder to add 381 */ 382 public void addFolder(String folder) { 383 384 m_searchObject.addFolder(folder); 385 m_searchObjectChanged = true; 386 ValueChangeEvent.fire(this, m_searchObject); 387 } 388 389 /** 390 * Add gallery to search object.<p> 391 * 392 * @param galleryPath the id of the gallery to add 393 */ 394 public void addGallery(String galleryPath) { 395 396 m_searchObject.addGallery(galleryPath); 397 m_searchObjectChanged = true; 398 m_galleriesChanged = true; 399 ValueChangeEvent.fire(this, m_searchObject); 400 } 401 402 /** 403 * Sets the locale to the search object.<p> 404 * 405 * @param locale the locale to set 406 */ 407 public void addLocale(String locale) { 408 409 m_searchObject.setLocale(locale); 410 m_searchObjectChanged = true; 411 ValueChangeEvent.fire(this, m_searchObject); 412 } 413 414 /** 415 * Sets the search scope in the search object.<p> 416 * 417 * @param scope the search scope 418 */ 419 public void addScope(CmsGallerySearchScope scope) { 420 421 m_searchObject.setScope(scope); 422 m_searchObjectChanged = true; 423 ValueChangeEvent.fire(this, m_searchObject); 424 } 425 426 /** 427 * Adds the search query from the search tab.<p> 428 * 429 * @param searchQuery the search query 430 */ 431 public void addSearchQuery(String searchQuery) { 432 433 m_searchObject.setQuery(searchQuery); 434 m_searchObjectChanged = true; 435 ValueChangeEvent.fire(this, m_searchObject); 436 } 437 438 /** 439 * Add type to search object.<p> 440 * 441 * @param resourceType the id(name?) of the resource type to add 442 */ 443 public void addType(String resourceType) { 444 445 m_searchObject.addType(resourceType); 446 m_searchObjectChanged = true; 447 ValueChangeEvent.fire(this, m_searchObject); 448 } 449 450 /** 451 * @see com.google.gwt.event.logical.shared.HasValueChangeHandlers#addValueChangeHandler(com.google.gwt.event.logical.shared.ValueChangeHandler) 452 */ 453 public HandlerRegistration addValueChangeHandler(ValueChangeHandler<CmsGallerySearchBean> handler) { 454 455 return m_eventBus.addHandlerToSource(ValueChangeEvent.getType(), this, handler); 456 } 457 458 /** 459 * Removes all selected categories from the search object.<p> 460 */ 461 public void clearCategories() { 462 463 List<String> selectedCategories = m_searchObject.getCategories(); 464 m_handler.onClearCategories(selectedCategories); 465 m_searchObject.clearCategories(); 466 updateResultsTab(false); 467 ValueChangeEvent.fire(this, m_searchObject); 468 } 469 470 /** 471 * Removes all selected folders from the search object.<p> 472 * 473 * @param searchChanged if true, marks the search parameters as changed 474 */ 475 public void clearFolders(boolean searchChanged) { 476 477 Set<String> selectedFolders = m_searchObject.getFolders(); 478 if (searchChanged) { 479 m_searchObjectChanged = true; 480 } 481 m_handler.onClearFolders(selectedFolders); 482 m_searchObject.clearFolders(); 483 updateResultsTab(false); 484 ValueChangeEvent.fire(this, m_searchObject); 485 } 486 487 /** 488 * Removes all selected galleries from the search object.<p> 489 */ 490 public void clearGalleries() { 491 492 List<String> selectedGalleries = m_searchObject.getGalleries(); 493 m_handler.onClearGalleries(selectedGalleries); 494 m_searchObject.clearGalleries(); 495 updateResultsTab(false); 496 ValueChangeEvent.fire(this, m_searchObject); 497 } 498 499 /** 500 * Removes all full text search criteria from the search object.<p> 501 */ 502 public void clearTextSearch() { 503 504 m_searchObject.clearFullTextSearch(); 505 m_handler.onClearFullTextSearch(); 506 updateResultsTab(false); 507 ValueChangeEvent.fire(this, m_searchObject); 508 } 509 510 /** 511 * Removes all selected types from the search object.<p> 512 */ 513 public void clearTypes() { 514 515 List<String> selectedTypes = m_searchObject.getTypes(); 516 m_handler.onClearTypes(selectedTypes); 517 m_searchObject.clearTypes(); 518 updateResultsTab(false); 519 ValueChangeEvent.fire(this, m_searchObject); 520 } 521 522 /** 523 * Checks for broken links, ask for confirmation and finally deletes the given resource.<p> 524 * 525 * @param resourcePath the resource path of the resource to delete 526 */ 527 public void deleteResource(final String resourcePath) { 528 529 CmsDeleteWarningDialog dialog = new CmsDeleteWarningDialog(resourcePath); 530 Command callback = new Command() { 531 532 /** 533 * @see com.google.gwt.user.client.Command#execute() 534 */ 535 public void execute() { 536 537 updateResultsTab(false); 538 } 539 }; 540 dialog.loadAndShow(callback); 541 } 542 543 /** 544 * @see com.google.gwt.event.shared.HasHandlers#fireEvent(com.google.gwt.event.shared.GwtEvent) 545 */ 546 public void fireEvent(GwtEvent<?> event) { 547 548 m_eventBus.fireEventFromSource(event, this); 549 } 550 551 /** 552 * Gets the available galleries.<p> 553 * 554 * @return the list of available galleries 555 */ 556 public List<CmsGalleryFolderBean> getAvailableGalleries() { 557 558 return m_dialogBean.getGalleries(); 559 } 560 561 /** 562 * Returns the available locales.<p> 563 * 564 * @return the available locales 565 */ 566 public Map<String, String> getAvailableLocales() { 567 568 return m_dialogBean.getLocales(); 569 } 570 571 /** 572 * Gets the default search scope.<p> 573 * 574 * @return the default search scope 575 */ 576 public CmsGallerySearchScope getDefaultScope() { 577 578 return m_dialogBean.getDefaultScope(); 579 } 580 581 /** 582 * Gets the default site root for the sitemap tab.<p> 583 * 584 * @return the default site root for the sitemap tab 585 */ 586 public String getDefaultSitemapTabSiteRoot() { 587 588 return getDefaultSiteRoot(m_dialogBean.getSitemapSiteSelectorOptions()); 589 } 590 591 /** 592 * Gets the default site root for the VFS tab.<p> 593 * 594 * @return the default site root for the VFS tab 595 */ 596 public String getDefaultVfsTabSiteRoot() { 597 598 return getDefaultSiteRoot(m_dialogBean.getVfsSiteSelectorOptions()); 599 } 600 601 /** 602 * Returns the gallery dialog mode.<p> 603 * 604 * @return the gallery dialog mode 605 */ 606 public I_CmsGalleryProviderConstants.GalleryMode getDialogMode() { 607 608 return m_dialogMode; 609 } 610 611 /** 612 * Returns the gallery folder info to the given path.<p> 613 * 614 * @param galleryPath the gallery folder path 615 * 616 * @return the gallery folder info 617 */ 618 public CmsGalleryFolderBean getGalleryInfo(String galleryPath) { 619 620 CmsGalleryFolderBean result = null; 621 for (CmsGalleryFolderBean folderBean : getAvailableGalleries()) { 622 if (folderBean.getPath().equals(galleryPath)) { 623 result = folderBean; 624 break; 625 } 626 } 627 return result; 628 } 629 630 /** 631 * Gets the option which should be preselected for the site selector, or null.<p> 632 * 633 * @param siteRoot the site root 634 * @param options the list of options 635 * 636 * @return the key for the option to preselect 637 */ 638 public String getPreselectOption(String siteRoot, List<CmsSiteSelectorOption> options) { 639 640 if ((siteRoot == null) || options.isEmpty()) { 641 return null; 642 } 643 for (CmsSiteSelectorOption option : options) { 644 if (CmsStringUtil.joinPaths(siteRoot, "/").equals(CmsStringUtil.joinPaths(option.getSiteRoot(), "/"))) { 645 return option.getSiteRoot(); 646 } 647 } 648 return options.get(0).getSiteRoot(); 649 } 650 651 /** 652 * Returns the result view type.<p> 653 * 654 * @return the result view type 655 */ 656 public String getResultViewType() { 657 658 return m_dialogBean.getResultViewType(); 659 } 660 661 /** 662 * Returns the search locale.<p> 663 * 664 * @return the search locale 665 */ 666 public String getSearchLocale() { 667 668 return m_searchObject.getLocale(); 669 } 670 671 /** 672 * Returns the gallery search scope.<p> 673 * 674 * @return the gallery search scope 675 */ 676 public CmsGallerySearchScope getSearchScope() { 677 678 return m_dialogBean.getScope(); 679 } 680 681 /** 682 * Returns the searchable resource types.<p> 683 * 684 * @return the searchable resource types 685 */ 686 public List<CmsResourceTypeBean> getSearchTypes() { 687 688 if (m_searchTypes != null) { 689 return m_searchTypes; 690 } 691 m_searchTypes = Lists.newArrayList(); 692 for (CmsResourceTypeBean type : m_dialogBean.getTypes()) { 693 if (type.getVisibility() != TypeVisibility.hidden) { 694 m_searchTypes.add(type); 695 } 696 } 697 return m_searchTypes; 698 } 699 700 /** 701 * Returns the default value for the "show expired" check box.<p> 702 * 703 * @return the default value for "show expired" 704 */ 705 public boolean getShowExpiredDefault() { 706 707 return m_dialogBean.getIncludeExpiredDefault(); 708 } 709 710 /** 711 * Gets the sitemap site selector options.<p> 712 * 713 * @return the sitemap site selector options 714 */ 715 public List<CmsSiteSelectorOption> getSitemapSiteSelectorOptions() { 716 717 return m_dialogBean.getSitemapSiteSelectorOptions(); 718 } 719 720 /** 721 * Returns the start locale.<p> 722 * 723 * @return the start locale 724 */ 725 public String getStartLocale() { 726 727 return m_dialogBean.getLocale(); 728 } 729 730 /** 731 * Gets the start site root.<p> 732 * 733 * @return the start site root 734 */ 735 public String getStartSiteRoot() { 736 737 return m_startSite; 738 } 739 740 /** 741 * Loads the sub entries for the given path.<p> 742 * 743 * @param rootPath the root path 744 * @param isRoot <code>true</code> if the requested entry is the root entry 745 * @param filter the sitemap filter string 746 * @param callback the callback to execute with the result 747 */ 748 public void getSubEntries( 749 final String rootPath, 750 final boolean isRoot, 751 final String filter, 752 final I_CmsSimpleCallback<List<CmsSitemapEntryBean>> callback) { 753 754 CmsRpcAction<List<CmsSitemapEntryBean>> action = new CmsRpcAction<List<CmsSitemapEntryBean>>() { 755 756 @Override 757 public void execute() { 758 759 start(0, false); 760 getGalleryService().getSubEntries(rootPath, isRoot, filter, this); 761 } 762 763 @Override 764 protected void onResponse(List<CmsSitemapEntryBean> result) { 765 766 stop(false); 767 callback.execute(result); 768 } 769 770 }; 771 action.execute(); 772 } 773 774 /** 775 * Retrieves the sub-folders of a given folder.<p> 776 * 777 * @param folder the folder whose sub-folders should be retrieved 778 * @param callback the callback for processing the sub-folders 779 */ 780 public void getSubFolders(final String folder, final AsyncCallback<List<CmsVfsEntryBean>> callback) { 781 782 CmsRpcAction<List<CmsVfsEntryBean>> action = new CmsRpcAction<List<CmsVfsEntryBean>>() { 783 784 @Override 785 public void execute() { 786 787 start(0, false); 788 getGalleryService().getSubFolders(folder, this); 789 } 790 791 @Override 792 protected void onResponse(List<CmsVfsEntryBean> result) { 793 794 stop(false); 795 callback.onSuccess(result); 796 } 797 798 }; 799 action.execute(); 800 } 801 802 /** 803 * Returns the configured tab id's.<p> 804 * 805 * @return the configured tab id's 806 */ 807 public GalleryTabId[] getTabIds() { 808 809 if (m_tabIds == null) { 810 return m_dialogMode.getTabs(); 811 } else { 812 return m_tabIds; 813 } 814 } 815 816 /** 817 * Gets the tree token, which is used to determine which tree state is loaded/saved for the VFS and sitemap tabs.<p> 818 * 819 * @return the tree token 820 */ 821 public String getTreeToken() { 822 823 return m_treeToken; 824 } 825 826 /** 827 * Returns the resource type info for the given resource type name.<p> 828 * 829 * @param typeName the resource type name 830 * 831 * @return the type info 832 */ 833 public CmsResourceTypeBean getTypeInfo(String typeName) { 834 835 CmsResourceTypeBean result = null; 836 for (CmsResourceTypeBean typeBean : m_dialogBean.getTypes()) { 837 if (typeBean.getType().equals(typeName)) { 838 result = typeBean; 839 break; 840 } 841 } 842 return result; 843 } 844 845 /** 846 * Gets the site selector options.<p> 847 * 848 * @return the site selector options 849 */ 850 public List<CmsSiteSelectorOption> getVfsSiteSelectorOptions() { 851 852 return m_dialogBean.getVfsSiteSelectorOptions(); 853 } 854 855 /** 856 * Returns true if the galleries in the gallery tab should be selectable.<p> 857 * 858 * @return true if the galleries should be selectable 859 */ 860 public boolean hasGalleriesSelectable() { 861 862 return m_galleriesSelectable; 863 } 864 865 /** 866 * Returns if a preview is available for the given resource type.<p> 867 * 868 * @param resourceType the requested resource type 869 * 870 * @return <code>true</code> if a preview is available for the given resource type 871 */ 872 public boolean hasPreview(String resourceType) { 873 874 return getProviderName(resourceType) != null; 875 } 876 877 /** 878 * Returns false if the results in the result tab should not be selectable.<p> 879 * 880 * @return false if the results in the result tab should not be selectable 881 */ 882 public boolean hasResultsSelectable() { 883 884 return m_resultsSelectable; 885 } 886 887 /** 888 * Returns if folders should be selectable.<p> 889 * 890 * @return <code>true</code> if folders should be selectable 891 */ 892 public boolean hasSelectFolder() { 893 894 if (hasSelectResource()) { 895 for (CmsResourceTypeBean type : m_dialogBean.getTypes()) { 896 if (type.getType().contains(I_CmsGalleryProviderConstants.RESOURCE_TYPE_FOLDER)) { 897 return true; 898 } 899 } 900 } 901 return false; 902 } 903 904 /** 905 * Returns if resource entries in the search result are selectable.<p> 906 * 907 * @return if resource entries in the search result are selectable 908 */ 909 public boolean hasSelectResource() { 910 911 return (m_dialogMode == GalleryMode.editor) || (m_dialogMode == GalleryMode.widget); 912 } 913 914 /** 915 * Returns if files are included.<p> 916 * 917 * @return <code>true</code> if files are included 918 */ 919 public boolean isIncludeFiles() { 920 921 return (m_configuration == null) || m_configuration.isIncludeFiles(); 922 } 923 924 /** 925 * Returns if a load results request is currently running.<p> 926 * 927 * @return <code>true</code> if a load results request is currently running 928 */ 929 public boolean isLoading() { 930 931 return m_loading; 932 } 933 934 /** 935 * Checks if the gallery is first opened in results tab.<p> 936 * 937 * @return true if gallery is first opened in results tab, false otherwise 938 */ 939 public boolean isOpenInResults() { 940 941 if (I_CmsGalleryProviderConstants.GalleryTabId.cms_tab_results.name().equals(m_searchObject.getTabId())) { 942 return true; 943 } 944 return false; 945 } 946 947 /** 948 * Returns <code>true</code>, if the search object was manipulated by the controller 949 * <code>false</code> otherwise.<p> 950 * 951 * @return the search object changed flag 952 */ 953 public boolean isSearchObjectChanged() { 954 955 return m_searchObjectChanged; 956 } 957 958 /** 959 * Checks if any search parameter are selected.<p> 960 * 961 * @return <code>false</code> if any search parameter is selected, <code>true</code> 962 * if there are no search parameter selected 963 */ 964 public boolean isSearchObjectEmpty() { 965 966 return m_searchObject.isEmpty(); 967 } 968 969 /** 970 * Returns true if the site selector should be shown.<p> 971 * 972 * @return true if the site selector should be shown 973 */ 974 public boolean isShowSiteSelector() { 975 976 return m_isShowSiteSelector; 977 } 978 979 /** 980 * Loads the root VFS entry bean for a given site selector option.<p> 981 * 982 * @param siteRoot the site root for which the VFS entry should be loaded 983 * @param filter the search filter 984 * 985 * @param asyncCallback the callback to call with the result 986 */ 987 public void loadVfsEntryBean( 988 final String siteRoot, 989 final String filter, 990 991 final AsyncCallback<CmsVfsEntryBean> asyncCallback) { 992 993 CmsRpcAction<CmsVfsEntryBean> action = new CmsRpcAction<CmsVfsEntryBean>() { 994 995 @Override 996 public void execute() { 997 998 start(200, false); 999 getGalleryService().loadVfsEntryBean(siteRoot, filter, this); 1000 } 1001 1002 @Override 1003 public void onResponse(CmsVfsEntryBean result) { 1004 1005 stop(false); 1006 asyncCallback.onSuccess(result); 1007 } 1008 1009 }; 1010 action.execute(); 1011 } 1012 1013 /** 1014 * Opens the preview for the given resource by the given resource type.<p> 1015 * 1016 * @param resourcePath the resource path 1017 * @param resourceType the resource type name 1018 */ 1019 public void openPreview(String resourcePath, String resourceType) { 1020 1021 if (m_currentPreview != null) { 1022 m_currentPreview.removePreview(); 1023 } 1024 String provider = getProviderName(resourceType); 1025 if (m_previewFactoryRegistration.containsKey(provider)) { 1026 m_handler.m_galleryDialog.useMaxDimensions(); 1027 m_currentPreview = m_previewFactoryRegistration.get(provider).getPreview(m_handler.m_galleryDialog); 1028 m_currentPreview.openPreview(resourcePath, !m_resultsSelectable); 1029 m_handler.hideShowPreviewButton(false); 1030 } else { 1031 CmsDebugLog.getInstance().printLine( 1032 "Preview provider \"" + provider + "\" has not been registered properly."); 1033 } 1034 } 1035 1036 /** 1037 * Remove the category from the search object.<p> 1038 * 1039 * @param categoryPath the category path as id 1040 */ 1041 public void removeCategory(String categoryPath) { 1042 1043 m_searchObject.removeCategory(categoryPath); 1044 m_searchObjectChanged = true; 1045 ValueChangeEvent.fire(this, m_searchObject); 1046 } 1047 1048 /** 1049 * Removes the category from the search object.<p> 1050 * 1051 * @param key the category 1052 */ 1053 public void removeCategoryParam(String key) { 1054 1055 if (m_searchObject.getCategories().contains(key)) { 1056 m_handler.onClearCategories(Collections.singletonList(key)); 1057 m_searchObject.removeCategory(key); 1058 updateResultsTab(false); 1059 ValueChangeEvent.fire(this, m_searchObject); 1060 } 1061 } 1062 1063 /** 1064 * Removes a folder from the current search object.<p> 1065 * 1066 * @param folder the folder to remove 1067 */ 1068 public void removeFolder(String folder) { 1069 1070 m_searchObject.removeFolder(folder); 1071 m_searchObjectChanged = true; 1072 ValueChangeEvent.fire(this, m_searchObject); 1073 } 1074 1075 /** 1076 * Removes the folder from the search object.<p> 1077 * 1078 * @param key the folder 1079 */ 1080 public void removeFolderParam(String key) { 1081 1082 if (m_searchObject.getFolders().contains(key)) { 1083 m_handler.onClearFolders(Collections.singletonList(key)); 1084 m_searchObject.removeFolder(key); 1085 updateResultsTab(false); 1086 ValueChangeEvent.fire(this, m_searchObject); 1087 } 1088 } 1089 1090 /** 1091 * Remove the gallery from the search object.<p> 1092 * 1093 * @param galleryPath the gallery path as id 1094 */ 1095 public void removeGallery(String galleryPath) { 1096 1097 m_searchObject.removeGallery(galleryPath); 1098 m_searchObjectChanged = true; 1099 m_galleriesChanged = true; 1100 ValueChangeEvent.fire(this, m_searchObject); 1101 } 1102 1103 /** 1104 * Removes a selected gallery from the search object.<p> 1105 * 1106 * @param key the gallery key 1107 */ 1108 public void removeGalleryParam(String key) { 1109 1110 if (m_searchObject.getGalleries().contains(key)) { 1111 m_galleriesChanged = true; 1112 m_handler.onClearGalleries(Collections.singletonList(key)); 1113 m_searchObject.removeGallery(key); 1114 updateResultsTab(false); 1115 ValueChangeEvent.fire(this, m_searchObject); 1116 } 1117 } 1118 1119 /** 1120 * Removes the query. 1121 */ 1122 public void removeQuery() { 1123 1124 m_searchObject.setQuery(null); 1125 m_handler.onRemoveQuery(); 1126 updateResultsTab(false); 1127 ValueChangeEvent.fire(this, m_searchObject); 1128 } 1129 1130 /** 1131 * Removes the search scope. 1132 */ 1133 public void removeScope() { 1134 1135 m_searchObject.setScope(null); 1136 m_handler.onRemoveScope(); 1137 updateResultsTab(false); 1138 ValueChangeEvent.fire(this, m_searchObject); 1139 } 1140 1141 /** 1142 * Removes the given full text search criteria from the search object.<p> 1143 * 1144 * @param key the key of the parameter to remove 1145 */ 1146 public void removeTextSearchParameter(String key) { 1147 1148 try { 1149 ParamType type = ParamType.valueOf(key); 1150 switch (type) { 1151 case language: 1152 m_searchObject.setLocale(getStartLocale()); 1153 break; 1154 case expired: 1155 m_searchObject.setIncludeExpired(false); 1156 break; 1157 case creation: 1158 m_searchObject.setDateCreatedEnd(-1L); 1159 m_searchObject.setDateCreatedStart(-1L); 1160 break; 1161 case modification: 1162 m_searchObject.setDateModifiedEnd(-1L); 1163 m_searchObject.setDateModifiedStart(-1L); 1164 break; 1165 default: 1166 } 1167 m_handler.onRemoveSearchParam(type); 1168 updateResultsTab(false); 1169 ValueChangeEvent.fire(this, m_searchObject); 1170 } catch (IllegalArgumentException e) { 1171 // should not happen 1172 } 1173 } 1174 1175 /** 1176 * Remove the type from the search object.<p> 1177 * 1178 * @param resourceType the resource type as id 1179 */ 1180 public void removeType(String resourceType) { 1181 1182 m_searchObject.removeType(resourceType); 1183 m_searchObjectChanged = true; 1184 ValueChangeEvent.fire(this, m_searchObject); 1185 } 1186 1187 /** 1188 * Removes the type from the search object.<p> 1189 * 1190 * @param key the type 1191 */ 1192 public void removeTypeParam(String key) { 1193 1194 List<String> selectedTypes = m_searchObject.getTypes(); 1195 if (selectedTypes.contains(key)) { 1196 m_handler.onClearTypes(Collections.singletonList(key)); 1197 selectedTypes.remove(key); 1198 updateResultsTab(false); 1199 ValueChangeEvent.fire(this, m_searchObject); 1200 } 1201 } 1202 1203 /** 1204 * Saves the tree state for a given tree on the server.<p> 1205 * 1206 * @param treeName the tree name 1207 * @param siteRoot the site root 1208 * @param openItemIds the structure ids of opened items 1209 */ 1210 public void saveTreeState(final String treeName, final String siteRoot, final Set<CmsUUID> openItemIds) { 1211 1212 CmsRpcAction<Void> treeStateAction = new CmsRpcAction<Void>() { 1213 1214 @Override 1215 public void execute() { 1216 1217 start(600, false); 1218 getGalleryService().saveTreeOpenState(treeName, getTreeToken(), siteRoot, openItemIds, this); 1219 } 1220 1221 @Override 1222 protected void onResponse(Void result) { 1223 1224 stop(false); 1225 } 1226 }; 1227 treeStateAction.execute(); 1228 1229 } 1230 1231 /** 1232 * Searches for a specific element and opens it's preview if found.<p> 1233 * 1234 * @param path the element path 1235 * @param nextAction the next action to execute after the search data for the element has been loaded into the gallery dialog 1236 */ 1237 public void searchElement(final String path, final Runnable nextAction) { 1238 1239 m_dialogBean.setCurrentElement(path); 1240 m_dialogBean.setStartTab(GalleryTabId.cms_tab_results); 1241 m_dialogBean.setTreeToken(getTreeToken()); 1242 1243 CmsRpcAction<CmsGallerySearchBean> searchAction = new CmsRpcAction<CmsGallerySearchBean>() { 1244 1245 @Override 1246 public void execute() { 1247 1248 start(200, true); 1249 getGalleryService().getSearch(m_dialogBean, this); 1250 } 1251 1252 @Override 1253 protected void onResponse(CmsGallerySearchBean result) { 1254 1255 stop(false); 1256 m_searchObject = result; 1257 m_handler.onInitialSearch(result, m_dialogBean, CmsGalleryController.this, false); 1258 if (nextAction != null) { 1259 nextAction.run(); 1260 } 1261 } 1262 1263 }; 1264 searchAction.execute(); 1265 } 1266 1267 /** 1268 * Selects the given resource and sets its path into the xml-content field or editor link.<p> 1269 * 1270 * @param resourcePath the resource path 1271 * @param structureId the structure id 1272 * @param title the resource title 1273 * @param resourceType the resource type 1274 */ 1275 public void selectResource(String resourcePath, CmsUUID structureId, String title, String resourceType) { 1276 1277 String provider = getProviderName(resourceType); 1278 if (provider == null) { 1279 // use {@link org.opencms.ade.galleries.client.preview.CmsBinaryPreviewProvider} as default to select a resource 1280 provider = I_CmsBinaryPreviewProvider.PREVIEW_NAME; 1281 } 1282 if (m_previewFactoryRegistration.containsKey(provider)) { 1283 m_previewFactoryRegistration.get(provider).getPreview(m_handler.m_galleryDialog).selectResource( 1284 resourcePath, 1285 structureId, 1286 title); 1287 1288 } else { 1289 CmsDebugLog.getInstance().printLine("No provider available"); 1290 } 1291 } 1292 1293 /** 1294 * Selects the result tab.<p> 1295 */ 1296 public void selectResultTab() { 1297 1298 m_handler.selectResultTab(); 1299 } 1300 1301 /** 1302 * Sets the function that provides the container information. 1303 * 1304 * @param containerInfoProvider the container info provider 1305 */ 1306 public void setContainerInfoProvider(Supplier<CmsGalleryContainerInfo> containerInfoProvider) { 1307 1308 if (containerInfoProvider == null) { 1309 containerInfoProvider = () -> null; 1310 } 1311 m_containerInfoProvider = containerInfoProvider; 1312 } 1313 1314 /** 1315 * Sets the controller handler for gallery dialog.<p> 1316 * 1317 * @param handler the handler to set 1318 */ 1319 public void setHandler(CmsGalleryControllerHandler handler) { 1320 1321 m_handler = handler; 1322 } 1323 1324 /** 1325 * Sets if the search should include expired or unreleased resources.<p> 1326 * 1327 * @param includeExpired if the search should include expired or unreleased resources 1328 * @param fireEvent true if a change event should be fired after setting the value 1329 */ 1330 public void setIncludeExpired(boolean includeExpired, boolean fireEvent) { 1331 1332 m_searchObject.setIncludeExpired(includeExpired); 1333 m_searchObjectChanged = true; 1334 if (fireEvent) { 1335 ValueChangeEvent.fire(this, m_searchObject); 1336 } 1337 1338 } 1339 1340 /** 1341 * Stores the result view type.<p> 1342 * 1343 * @param resultViewType the result view type 1344 */ 1345 public void setResultViewType(final String resultViewType) { 1346 1347 CmsRpcAction<Void> action = new CmsRpcAction<Void>() { 1348 1349 @Override 1350 public void execute() { 1351 1352 getGalleryService().saveResultViewType(resultViewType, this); 1353 } 1354 1355 @Override 1356 protected void onResponse(Void result) { 1357 1358 // nothing to do 1359 } 1360 1361 }; 1362 action.execute(); 1363 } 1364 1365 /** 1366 * Sets the search object changed flag to <code>true</code>.<p> 1367 */ 1368 public void setSearchObjectChanged() { 1369 1370 m_searchObjectChanged = true; 1371 } 1372 1373 /** 1374 * Sets the "Show site selector" option.<p> 1375 * 1376 * @param isShowSiteSelector the new value for the option 1377 */ 1378 public void setShowSiteSelector(boolean isShowSiteSelector) { 1379 1380 m_isShowSiteSelector = isShowSiteSelector; 1381 } 1382 1383 /** 1384 * Sets the start site.<p> 1385 * 1386 * @param startSite the start site 1387 */ 1388 public void setStartSite(String startSite) { 1389 1390 m_startSite = startSite; 1391 } 1392 1393 /** 1394 * Sets the template context info provider. 1395 * 1396 * @param provider the template context info provider 1397 */ 1398 public void setTemplateContextInfoProvider(Supplier<CmsTemplateContextInfo> provider) { 1399 1400 m_templateContextInfoProvider = provider; 1401 } 1402 1403 /** 1404 * Sorts the categories according to given parameters and updates the list.<p> 1405 * 1406 * @param sortParams the sort parameters 1407 * @param filter the filter to apply before sorting 1408 */ 1409 public void sortCategories(String sortParams, String filter) { 1410 1411 List<CmsCategoryBean> categories; 1412 SortParams sort = SortParams.valueOf(sortParams); 1413 switch (sort) { 1414 case tree: 1415 m_handler.onUpdateCategoriesTree(m_dialogBean.getCategories(), m_searchObject.getCategories()); 1416 break; 1417 case title_asc: 1418 categories = getFilteredCategories(filter); 1419 Collections.sort(categories, new CmsComparatorTitle(true)); 1420 m_handler.onUpdateCategoriesList(categories, m_searchObject.getCategories()); 1421 break; 1422 case title_desc: 1423 categories = getFilteredCategories(filter); 1424 Collections.sort(categories, new CmsComparatorTitle(false)); 1425 m_handler.onUpdateCategoriesList(categories, m_searchObject.getCategories()); 1426 break; 1427 case type_asc: 1428 case type_desc: 1429 case path_asc: 1430 case path_desc: 1431 case dateLastModified_asc: 1432 case dateLastModified_desc: 1433 1434 default: 1435 } 1436 } 1437 1438 /** 1439 * Sorts the galleries according to given parameters and updates the list.<p> 1440 * 1441 * @param sortParams the sort parameters 1442 * @param filter the filter to apply before sorting 1443 */ 1444 public void sortGalleries(String sortParams, String filter) { 1445 1446 List<CmsGalleryFolderBean> galleries; 1447 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(filter)) { 1448 galleries = new ArrayList<CmsGalleryFolderBean>(); 1449 for (CmsGalleryFolderBean galleryBean : m_dialogBean.getGalleries()) { 1450 if (galleryBean.matchesFilter(filter)) { 1451 galleries.add(galleryBean); 1452 } 1453 } 1454 } else { 1455 galleries = m_dialogBean.getGalleries(); 1456 } 1457 SortParams sort = SortParams.valueOf(sortParams); 1458 boolean grouped = false; 1459 switch (sort) { 1460 case title_asc: 1461 Collections.sort(galleries, new CmsComparatorTitle(true)); 1462 break; 1463 case title_desc: 1464 Collections.sort(galleries, new CmsComparatorTitle(false)); 1465 break; 1466 case type_asc: 1467 Collections.sort(galleries, new CmsComparatorType(true)); 1468 break; 1469 case type_desc: 1470 Collections.sort(galleries, new CmsComparatorType(false)); 1471 break; 1472 case path_asc: 1473 Collections.sort(galleries, new CmsComparatorPath(true)); 1474 break; 1475 case path_desc: 1476 Collections.sort(galleries, new CmsComparatorPath(false)); 1477 break; 1478 case grouped: 1479 Collections.sort( 1480 galleries, 1481 ( 1482 a, 1483 b) -> ComparisonChain.start().compare(a.getGroup(), b.getGroup()).compare( 1484 a.getPath(), 1485 b.getPath()).result()); 1486 grouped = true; 1487 break; 1488 case grouped_title: 1489 Collections.sort( 1490 galleries, 1491 ( 1492 a, 1493 b) -> ComparisonChain.start().compare(a.getGroup(), b.getGroup()).compare( 1494 a.getTitle(), 1495 b.getTitle()).result()); 1496 grouped = true; 1497 break; 1498 case tree: 1499 m_handler.onUpdateGalleryTree(galleryListToTree(galleries), m_searchObject.getGalleries()); 1500 return; 1501 case dateLastModified_asc: 1502 case dateLastModified_desc: 1503 default: 1504 // not supported 1505 return; 1506 } 1507 m_handler.onUpdateGalleries(galleries, m_searchObject.getGalleries(), grouped); 1508 } 1509 1510 /** 1511 * Sorts the results according to given parameters and updates the list.<p> 1512 * 1513 * @param sortParams the sort parameters 1514 */ 1515 public void sortResults(final String sortParams) { 1516 1517 m_searchObject.setSortOrder(sortParams); 1518 updateResultsTab(false); 1519 } 1520 1521 /** 1522 * Sorts the types according to given parameters and updates the list.<p> 1523 * 1524 * @param sortParams the sort parameters 1525 */ 1526 public void sortTypes(String sortParams) { 1527 1528 List<CmsResourceTypeBean> types = getSearchTypes(); 1529 SortParams sort = SortParams.valueOf(sortParams); 1530 switch (sort) { 1531 case title_asc: 1532 Collections.sort(types, new CmsComparatorTitle(true)); 1533 break; 1534 case title_desc: 1535 Collections.sort(types, new CmsComparatorTitle(false)); 1536 break; 1537 case type_asc: 1538 Collections.sort(types, new CmsComparatorType(true)); 1539 break; 1540 case type_desc: 1541 Collections.sort(types, new CmsComparatorType(false)); 1542 break; 1543 case dateLastModified_asc: 1544 case dateLastModified_desc: 1545 case path_asc: 1546 case path_desc: 1547 case tree: 1548 default: 1549 // not supported 1550 return; 1551 } 1552 m_handler.onUpdateTypes(types, m_searchObject.getTypes()); 1553 } 1554 1555 /** 1556 * Updates the size of the active tab.<p> 1557 */ 1558 public void updateActiveTabSize() { 1559 1560 m_handler.m_galleryDialog.updateSizes(); 1561 1562 } 1563 1564 /** 1565 * Updates the content of the categories tab.<p> 1566 */ 1567 public void updateCategoriesTab() { 1568 1569 if (m_dialogBean.getCategories() == null) { 1570 loadCategories(); 1571 } else { 1572 m_handler.onCategoriesTabSelection(); 1573 } 1574 } 1575 1576 /** 1577 * Updates the content of the galleries(folders) tab.<p> 1578 */ 1579 public void updateGalleriesTab() { 1580 1581 if (m_dialogBean.getGalleries() == null) { 1582 loadGalleries(); 1583 } else { 1584 m_handler.onGalleriesTabSelection(); 1585 } 1586 } 1587 1588 /** 1589 * Updates the gallery data.<p> 1590 * 1591 * @param data the gallery data 1592 */ 1593 public void updateGalleryData(CmsGalleryDataBean data) { 1594 1595 m_dialogBean = data; 1596 m_handler.updateGalleryData(m_searchObject, data, this); 1597 } 1598 1599 /** 1600 * Updates the gallery index and triggers a new search afterwards.<p> 1601 */ 1602 public void updateIndex() { 1603 1604 CmsRpcAction<Void> action = new CmsRpcAction<Void>() { 1605 1606 @Override 1607 public void execute() { 1608 1609 start(200, true); 1610 getGalleryService().updateIndex(this); 1611 } 1612 1613 @Override 1614 protected void onResponse(Void result) { 1615 1616 stop(false); 1617 updateResultsTab(false); 1618 m_handler.hideShowPreviewButton(true); 1619 } 1620 }; 1621 action.execute(); 1622 } 1623 1624 /** 1625 * Updates the content of the results tab.<p> 1626 * 1627 * @param isNextPage signals if the next page should be loaded 1628 */ 1629 public void updateResultsTab(final boolean isNextPage) { 1630 1631 // if the RPC call will be sent the search object is in a unchanged state 1632 m_searchObjectChanged = false; 1633 if (!m_handler.hasResultsTab()) { 1634 1635 return; 1636 } 1637 if (m_searchObject.isEmpty()) { 1638 1639 // don't search: notify the user that at least one search criteria should be selected 1640 if ((m_handler.m_galleryDialog.getResultsTab() == null) 1641 || m_handler.m_galleryDialog.getResultsTab().isSelected()) { 1642 1643 m_handler.showFirstTab(); 1644 } 1645 } else { 1646 1647 // perform the search 1648 1649 /** The RPC search action for the gallery dialog. */ 1650 CmsRpcAction<CmsGallerySearchBean> searchAction = new CmsRpcAction<CmsGallerySearchBean>() { 1651 1652 private int m_callId; 1653 1654 /** 1655 * @see org.opencms.gwt.client.rpc.CmsRpcAction#execute() 1656 */ 1657 @Override 1658 public void execute() { 1659 1660 start(0, true); 1661 m_currentCallId++; 1662 m_callId = m_currentCallId; 1663 m_loading = true; 1664 1665 CmsGallerySearchBean preparedObject = prepareSearchObject(); 1666 1667 if (isNextPage) { 1668 preparedObject.setPage(preparedObject.getLastPage() + 1); 1669 } else { 1670 preparedObject.setPage(1); 1671 } 1672 getGalleryService().getSearch(preparedObject, this); 1673 } 1674 1675 /** 1676 * @see org.opencms.gwt.client.rpc.CmsRpcAction#onResponse(java.lang.Object) 1677 */ 1678 @Override 1679 public void onResponse(CmsGallerySearchBean searchObj) { 1680 1681 stop(false); 1682 if (m_callId != m_currentCallId) { 1683 return; 1684 } 1685 if (!isNextPage) { 1686 m_handler.hideShowPreviewButton(true); 1687 } 1688 m_loading = false; 1689 m_searchObject.setResults(searchObj.getResults()); 1690 m_searchObject.setResultCount(searchObj.getResultCount()); 1691 m_searchObject.setReplacedResults(searchObj.hasReplacedResults()); 1692 m_searchObject.setSortOrder(searchObj.getSortOrder()); 1693 m_searchObject.setPage(searchObj.getPage()); 1694 m_searchObject.setLastPage(searchObj.getLastPage()); 1695 m_searchObject.setNoUploadReason(searchObj.getNoUploadReason()); 1696 m_handler.onResultTabSelection(m_searchObject); 1697 1698 } 1699 }; 1700 searchAction.execute(); 1701 } 1702 } 1703 1704 /** 1705 * Updates the content of the types tab.<p> 1706 */ 1707 public void updatesTypesTab() { 1708 1709 m_handler.onTypesTabSelection(); 1710 } 1711 1712 /** 1713 * Returns the sitemap service instance.<p> 1714 * 1715 * @return the sitemap service instance 1716 */ 1717 protected I_CmsVfsServiceAsync getVfsService() { 1718 1719 if (m_vfsService == null) { 1720 m_vfsService = CmsCoreProvider.getVfsService(); 1721 } 1722 return m_vfsService; 1723 } 1724 1725 /** 1726 * Deletes a resource.<p> 1727 * 1728 * @param resourcePath the path of the resource to delete 1729 */ 1730 protected void internalDeleteResource(final String resourcePath) { 1731 1732 CmsRpcAction<Void> action = new CmsRpcAction<Void>() { 1733 1734 @Override 1735 public void execute() { 1736 1737 start(0, false); 1738 getGalleryService().deleteResource(resourcePath, this); 1739 } 1740 1741 @Override 1742 protected void onResponse(Void result) { 1743 1744 stop(false); 1745 updateResultsTab(false); 1746 } 1747 }; 1748 action.execute(); 1749 } 1750 1751 /** 1752 * Removes a tab id from the internal list of tab ids.<p> 1753 * 1754 * @param tabId the id of the tab to remove 1755 */ 1756 protected void removeTab(GalleryTabId tabId) { 1757 1758 if (m_tabIds != null) { 1759 List<GalleryTabId> tabs = new ArrayList<GalleryTabId>(Arrays.asList(m_tabIds)); 1760 if (tabs.contains(tabId)) { 1761 m_tabIds = new GalleryTabId[tabs.size() - 1]; 1762 tabs.remove(tabId); 1763 m_tabIds = tabs.toArray(new GalleryTabId[tabs.size()]); 1764 } 1765 } 1766 } 1767 1768 /** 1769 * Removes the types tab from the list of configured tabs.<p> 1770 * This will only take effect when executed before tab initialization.<p> 1771 */ 1772 protected void removeTypesTab() { 1773 1774 removeTab(GalleryTabId.cms_tab_types); 1775 } 1776 1777 /** 1778 * Does the initial search if not already pre-fetched.<p> 1779 */ 1780 void initialSearch() { 1781 1782 CmsRpcAction<CmsGallerySearchBean> searchAction = new CmsRpcAction<CmsGallerySearchBean>() { 1783 1784 @Override 1785 public void execute() { 1786 1787 start(0, true); 1788 m_dialogBean.setTreeToken(getTreeToken()); 1789 getGalleryService().getSearch(m_dialogBean, this); 1790 } 1791 1792 @Override 1793 protected void onResponse(CmsGallerySearchBean result) { 1794 1795 stop(false); 1796 m_searchObject = result; 1797 m_handler.onInitialSearch(m_searchObject, m_dialogBean, CmsGalleryController.this, true); 1798 } 1799 }; 1800 searchAction.execute(); 1801 } 1802 1803 /** 1804 * Returns a consistent search object to be used for the search.<p> 1805 * 1806 * For the search at least one resource type should be provided. 1807 * The corresponding resource types will be added to the search object, if no or only gallery folder are selected. 1808 * 1809 * @return the search object 1810 */ 1811 CmsGallerySearchBean prepareSearchObject() { 1812 1813 CmsGallerySearchBean preparedSearchObj = new CmsGallerySearchBean(m_searchObject); 1814 preparedSearchObj.setReferencePath(m_dialogBean.getReferenceSitePath()); 1815 // add the available types to the search object used for next search, 1816 // if the criteria for types are empty 1817 if (CmsClientCollectionUtil.isEmptyOrNull(m_searchObject.getTypes())) { 1818 // no galleries is selected, provide all available types 1819 if (CmsClientCollectionUtil.isEmptyOrNull(m_searchObject.getGalleries())) { 1820 // additionally provide all available gallery folders if in 'widget' and 'editor' dialog-mode and no folder has been selected 1821 if (((m_dialogMode == I_CmsGalleryProviderConstants.GalleryMode.widget) 1822 || (m_dialogMode == I_CmsGalleryProviderConstants.GalleryMode.editor)) 1823 && CmsClientCollectionUtil.isEmptyOrNull(m_searchObject.getFolders())) { 1824 ArrayList<String> availableGalleries = new ArrayList<String>(); 1825 for (CmsGalleryFolderBean galleryPath : m_dialogBean.getGalleries()) { 1826 availableGalleries.add(galleryPath.getPath()); 1827 } 1828 preparedSearchObj.setGalleries(availableGalleries); 1829 } 1830 ArrayList<String> availableTypes = new ArrayList<String>(); 1831 for (CmsResourceTypeBean type : m_dialogBean.getTypes()) { 1832 // exclude deactivated types 1833 if (!type.isDeactivated()) { 1834 availableTypes.add(type.getType()); 1835 } 1836 } 1837 preparedSearchObj.setServerSearchTypes(availableTypes); 1838 // at least one gallery is selected 1839 } else { 1840 1841 // get the resource types associated with the selected galleries 1842 HashSet<String> galleryTypes = new HashSet<String>(); 1843 for (CmsGalleryFolderBean gallery : m_dialogBean.getGalleries()) { 1844 if (m_searchObject.getGalleries().contains(gallery.getPath())) { 1845 galleryTypes.addAll(gallery.getContentTypes()); 1846 } 1847 } 1848 1849 HashSet<String> availableTypes = new HashSet<String>(); 1850 for (CmsResourceTypeBean type : m_dialogBean.getTypes()) { 1851 availableTypes.add(type.getType()); 1852 } 1853 1854 preparedSearchObj.setServerSearchTypes( 1855 new ArrayList<String>(CmsClientCollectionUtil.intersection(availableTypes, galleryTypes))); 1856 } 1857 } else { 1858 preparedSearchObj.setServerSearchTypes(m_searchObject.getTypes()); 1859 } 1860 if (m_galleriesChanged) { 1861 preparedSearchObj.setGalleriesChanged(true); 1862 m_galleriesChanged = false; 1863 } 1864 preparedSearchObj.setContainerInfo(m_containerInfoProvider.get()); 1865 preparedSearchObj.setTemplateContextInfo(m_templateContextInfoProvider.get()); 1866 return preparedSearchObj; 1867 1868 } 1869 1870 /** 1871 * Converts categories tree to a list of info beans.<p> 1872 * 1873 * @param categoryList the category list 1874 * @param entries the tree entries 1875 */ 1876 private void categoryTreeToList(List<CmsCategoryBean> categoryList, List<CmsCategoryTreeEntry> entries) { 1877 1878 if (entries == null) { 1879 return; 1880 } 1881 // skipping the root tree entry where the path property is empty 1882 for (CmsCategoryTreeEntry entry : entries) { 1883 CmsCategoryBean bean = new CmsCategoryBean(entry); 1884 categoryList.add(bean); 1885 categoryTreeToList(categoryList, entry.getChildren()); 1886 } 1887 } 1888 1889 /** 1890 * Creates a tree structure from the given gallery folder list.<p> 1891 * The tree may have several entries at root level.<p> 1892 * 1893 * @param galleries the gallery folder list 1894 * 1895 * @return the list of tree entries 1896 */ 1897 private List<CmsGalleryTreeEntry> galleryListToTree(List<CmsGalleryFolderBean> galleries) { 1898 1899 List<CmsGalleryTreeEntry> result = new ArrayList<CmsGalleryTreeEntry>(); 1900 Collections.sort(galleries, new CmsComparatorPath(true)); 1901 CmsGalleryTreeEntry previous = null; 1902 for (CmsGalleryFolderBean folderBean : galleries) { 1903 CmsGalleryTreeEntry current = new CmsGalleryTreeEntry(folderBean); 1904 CmsGalleryTreeEntry parent = null; 1905 if (previous != null) { 1906 parent = lookForParent(previous, current.getPath()); 1907 } 1908 if (parent != null) { 1909 parent.addChild(current); 1910 } else { 1911 result.add(current); 1912 } 1913 previous = current; 1914 } 1915 return result; 1916 } 1917 1918 /** 1919 * Gets the list of categories.<p> 1920 * 1921 * @return a list of category beans 1922 */ 1923 private List<CmsCategoryBean> getCategoryList() { 1924 1925 List<CmsCategoryBean> result = new ArrayList<CmsCategoryBean>(); 1926 categoryTreeToList(result, m_dialogBean.getCategories()); 1927 return result; 1928 } 1929 1930 /** 1931 * Helper method for getting the default (sub)site root for a list of site selector options.<p> 1932 * 1933 * @param options the list of options 1934 * 1935 * @return the default (sub)site root 1936 */ 1937 private String getDefaultSiteRoot(List<CmsSiteSelectorOption> options) { 1938 1939 if (m_startSite != null) { 1940 return m_startSite; 1941 } else if ((options != null) && (!options.isEmpty())) { 1942 String defaultOption = options.get(0).getSiteRoot(); 1943 for (CmsSiteSelectorOption option : options) { 1944 if (option.getType().equals(CmsSiteSelectorOption.Type.currentSubsite)) { 1945 return option.getSiteRoot(); 1946 } 1947 if (option.isCurrentSite()) { 1948 defaultOption = option.getSiteRoot(); 1949 } 1950 } 1951 return defaultOption; 1952 } else { 1953 return CmsCoreProvider.get().getSiteRoot(); 1954 } 1955 } 1956 1957 /** 1958 * Gets the filtered list of categories.<p> 1959 * 1960 * @param filter the search string to use for filtering 1961 * 1962 * @return the filtered category beans 1963 */ 1964 private List<CmsCategoryBean> getFilteredCategories(String filter) { 1965 1966 List<CmsCategoryBean> result; 1967 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(filter)) { 1968 result = new ArrayList<CmsCategoryBean>(); 1969 for (CmsCategoryBean category : getCategoryList()) { 1970 if (category.matchesFilter(filter)) { 1971 result.add(category); 1972 } 1973 } 1974 } else { 1975 result = getCategoryList(); 1976 } 1977 return result; 1978 } 1979 1980 /** 1981 * Returns the preview provider name for the given resource type, or <code>null</code> if none available.<p> 1982 * 1983 * @param resourceType the resource type 1984 * 1985 * @return the preview provider name 1986 */ 1987 private String getProviderName(String resourceType) { 1988 1989 for (CmsResourceTypeBean typeBean : m_dialogBean.getTypes()) { 1990 if (typeBean.getType().equals(resourceType)) { 1991 return typeBean.getPreviewProviderName(); 1992 } 1993 } 1994 return null; 1995 } 1996 1997 /** 1998 * Loading all available categories.<p> 1999 */ 2000 private void loadCategories() { 2001 2002 CmsRpcAction<List<CmsCategoryTreeEntry>> action = new CmsRpcAction<List<CmsCategoryTreeEntry>>() { 2003 2004 @Override 2005 public void execute() { 2006 2007 start(200, true); 2008 CmsCoreProvider.getService().getCategoriesForSitePath(m_dialogBean.getReferenceSitePath(), this); 2009 } 2010 2011 @Override 2012 protected void onResponse(List<CmsCategoryTreeEntry> result) { 2013 2014 m_dialogBean.setCategories(result); 2015 m_handler.setCategoriesTabContent(result, new ArrayList<String>()); 2016 m_handler.onCategoriesTabSelection(); 2017 stop(false); 2018 } 2019 }; 2020 action.execute(); 2021 } 2022 2023 /** 2024 * Loading all available galleries.<p> 2025 */ 2026 private void loadGalleries() { 2027 2028 CmsRpcAction<List<CmsGalleryFolderBean>> action = new CmsRpcAction<List<CmsGalleryFolderBean>>() { 2029 2030 @Override 2031 public void execute() { 2032 2033 start(200, true); 2034 List<String> types = new ArrayList<String>(); 2035 for (CmsResourceTypeBean type : m_dialogBean.getTypes()) { 2036 types.add(type.getType()); 2037 } 2038 2039 // not sure if this ever gets called in practice 2040 getGalleryService().getGalleries("/", types, this); 2041 } 2042 2043 @Override 2044 protected void onResponse(List<CmsGalleryFolderBean> result) { 2045 2046 m_dialogBean.setGalleries(result); 2047 m_handler.setGalleriesTabContent(result, m_searchObject.getGalleries(), false); 2048 m_handler.onGalleriesTabSelection(); 2049 stop(false); 2050 } 2051 }; 2052 action.execute(); 2053 } 2054 2055 /** 2056 * Looks for an ancestor tree entry for the given path.<p> 2057 * 2058 * @param possibleParent the possible parent entry 2059 * @param targetPath the target path 2060 * 2061 * @return the parent entry or <code>null</code> if there is none 2062 */ 2063 private CmsGalleryTreeEntry lookForParent(CmsGalleryTreeEntry possibleParent, String targetPath) { 2064 2065 if (targetPath.startsWith(possibleParent.getPath())) { 2066 return possibleParent; 2067 } 2068 if (possibleParent.getParent() != null) { 2069 return lookForParent(possibleParent.getParent(), targetPath); 2070 } 2071 return null; 2072 } 2073 2074}