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.ui.apps.datesearch; 029 030import org.opencms.file.CmsObject; 031import org.opencms.file.CmsResource; 032import org.opencms.file.CmsResourceFilter; 033import org.opencms.file.types.I_CmsResourceType; 034import org.opencms.jsp.search.config.parser.simplesearch.daterestrictions.CmsDateRangeRestriction; 035import org.opencms.loader.CmsLoaderException; 036import org.opencms.main.CmsException; 037import org.opencms.main.CmsLog; 038import org.opencms.main.OpenCms; 039import org.opencms.search.CmsSearchException; 040import org.opencms.search.CmsSearchResource; 041import org.opencms.search.fields.CmsSearchField; 042import org.opencms.search.solr.CmsSolrIndex; 043import org.opencms.search.solr.CmsSolrQuery; 044import org.opencms.search.solr.CmsSolrResultList; 045import org.opencms.ui.A_CmsUI; 046import org.opencms.ui.CmsVaadinUtils; 047import org.opencms.ui.I_CmsDialogContext; 048import org.opencms.ui.I_CmsDialogContext.ContextType; 049import org.opencms.ui.apps.CmsAppWorkplaceUi; 050import org.opencms.ui.apps.I_CmsContextProvider; 051import org.opencms.ui.apps.Messages; 052import org.opencms.ui.apps.lists.CmsListManager; 053import org.opencms.ui.apps.lists.CmsResultTable; 054import org.opencms.ui.components.CmsAvailabilitySelector; 055import org.opencms.ui.components.CmsComponentState; 056import org.opencms.ui.components.CmsDateField; 057import org.opencms.ui.components.CmsErrorDialog; 058import org.opencms.ui.components.CmsFileTable; 059import org.opencms.ui.components.CmsFileTableDialogContext; 060import org.opencms.ui.components.CmsFolderSelector; 061import org.opencms.ui.components.CmsResourceTable.I_ResourcePropertyProvider; 062import org.opencms.ui.components.CmsResourceTableProperty; 063import org.opencms.ui.components.CmsResultFacets; 064import org.opencms.ui.components.CmsResultFilterComponent; 065import org.opencms.ui.components.CmsSiteSelector; 066import org.opencms.ui.components.CmsTypeSelector; 067import org.opencms.ui.components.I_CmsResultFacetsManager; 068import org.opencms.ui.components.OpenCmsTheme; 069import org.opencms.ui.contextmenu.CmsResourceContextMenuBuilder; 070import org.opencms.util.CmsStringUtil; 071import org.opencms.util.CmsUUID; 072import org.opencms.workplace.explorer.CmsExplorerTypeSettings; 073import org.opencms.workplace.explorer.CmsResourceUtil; 074 075import java.time.LocalDateTime; 076import java.util.ArrayList; 077import java.util.Collection; 078import java.util.Date; 079import java.util.HashMap; 080import java.util.LinkedHashMap; 081import java.util.List; 082import java.util.Locale; 083import java.util.Map; 084import java.util.Set; 085 086import org.apache.commons.logging.Log; 087import org.apache.solr.client.solrj.SolrQuery.ORDER; 088import org.apache.solr.client.solrj.response.FacetField.Count; 089import org.apache.solr.client.solrj.util.ClientUtils; 090 091import com.vaadin.shared.ui.datefield.DateTimeResolution; 092import com.vaadin.ui.Component; 093import com.vaadin.ui.FormLayout; 094import com.vaadin.ui.TextField; 095import com.vaadin.v7.data.Item; 096import com.vaadin.v7.data.Property.ValueChangeEvent; 097import com.vaadin.v7.data.Property.ValueChangeListener; 098import com.vaadin.v7.data.util.filter.Or; 099import com.vaadin.v7.data.util.filter.SimpleStringFilter; 100import com.vaadin.v7.event.FieldEvents.TextChangeEvent; 101import com.vaadin.v7.event.FieldEvents.TextChangeListener; 102import com.vaadin.v7.ui.Table; 103import com.vaadin.v7.ui.Table.CellStyleGenerator; 104import com.vaadin.v7.ui.VerticalLayout; 105 106/** 107 * Component that realizes a content finder. 108 */ 109@SuppressWarnings("deprecation") 110public class CmsDateSearchComposite implements I_ResourcePropertyProvider, I_CmsResultFacetsManager { 111 112 /** 113 * The filter component of the content finder. 114 */ 115 @SuppressWarnings("serial") 116 private class FilterComponent extends VerticalLayout { 117 118 /** The site selector. */ 119 CmsSiteSelector m_siteSelector; 120 121 /** The folder selector. */ 122 CmsFolderSelector m_folderSelector; 123 124 /** The type selector. */ 125 CmsTypeSelector m_typeSelector; 126 127 /** The date from selector. */ 128 CmsDateField m_dateFrom; 129 130 /** The date to selector. */ 131 CmsDateField m_dateTo; 132 133 /** The availability selector. */ 134 CmsAvailabilitySelector m_availabilitySelector; 135 136 /** The result facets component. */ 137 CmsResultFacets m_resultFacets; 138 139 /** The form layout. */ 140 FormLayout m_formLayout; 141 142 /** The text search. */ 143 TextField m_textSearchField; 144 145 /** 146 * Creates a new filter component. 147 */ 148 FilterComponent() { 149 150 setMargin(true); 151 setSpacing(true); 152 m_formLayout = new FormLayout(); 153 m_formLayout.setMargin(true); 154 m_formLayout.setSpacing(true); 155 m_formLayout.addStyleName("o-formlayout-narrow"); 156 initSiteSelector(); 157 initFolderSelector(); 158 initTypeSelector(); 159 initDateFrom(); 160 initDateTo(); 161 initTextSearchField(); 162 initExpiredSelector(); 163 initResultFacets(); 164 m_formLayout.addComponent(new VerticalLayout()); // fix layout bug 165 addComponent(m_formLayout); 166 } 167 168 /** 169 * Returns the selected category. 170 * @return the selected category 171 */ 172 String getSelectedCategory() { 173 174 List<String> categories = m_resultFacets.getSelectedFieldFacets().get(CmsSearchField.FIELD_CATEGORY_EXACT); 175 if ((categories != null) && !categories.isEmpty()) { 176 return categories.get(0); 177 } 178 return null; 179 } 180 181 /** 182 * Updates the type selector. 183 */ 184 void updateTypeSelector() { 185 186 m_typeSelector.updateTypes(getAvailableTypes()); 187 } 188 189 /** 190 * Initializes the date from selector. 191 */ 192 private void initDateFrom() { 193 194 m_dateFrom = new CmsDateField(); 195 m_dateFrom.setWidthFull(); 196 String caption = CmsVaadinUtils.getMessageText(Messages.GUI_DATE_SEARCH_DATE_FROM_0); 197 m_dateFrom.setCaption(caption); 198 m_dateFrom.setResolution(DateTimeResolution.DAY); 199 m_dateFrom.addValueChangeListener(new com.vaadin.data.HasValue.ValueChangeListener<LocalDateTime>() { 200 201 public void valueChange(com.vaadin.data.HasValue.ValueChangeEvent<LocalDateTime> event) { 202 203 search(true, true); 204 } 205 }); 206 m_formLayout.addComponent(m_dateFrom); 207 } 208 209 /** 210 * Initializes the date to selector. 211 */ 212 private void initDateTo() { 213 214 m_dateTo = new CmsDateField(); 215 m_dateTo.setWidthFull(); 216 String caption = CmsVaadinUtils.getMessageText(Messages.GUI_DATE_SEARCH_DATE_TO_0); 217 m_dateTo.setCaption(caption); 218 m_dateTo.setResolution(DateTimeResolution.DAY); 219 m_dateTo.addValueChangeListener(new com.vaadin.data.HasValue.ValueChangeListener<LocalDateTime>() { 220 221 public void valueChange(com.vaadin.data.HasValue.ValueChangeEvent<LocalDateTime> event) { 222 223 search(true, true); 224 } 225 }); 226 m_formLayout.addComponent(m_dateTo); 227 } 228 229 /** 230 * Initializes the expired resources selector. 231 */ 232 private void initExpiredSelector() { 233 234 m_availabilitySelector = new CmsAvailabilitySelector(); 235 m_availabilitySelector.addValueChangeListener(event -> { 236 search(true, true); 237 }); 238 m_formLayout.addComponent(m_availabilitySelector); 239 } 240 241 /** 242 * Initializes the folder selector. 243 */ 244 private void initFolderSelector() { 245 246 m_folderSelector = new CmsFolderSelector(); 247 m_folderSelector.addValueChangeListener(new ValueChangeListener() { 248 249 public void valueChange(ValueChangeEvent event) { 250 251 search(true, true); 252 } 253 }); 254 m_formLayout.addComponent(m_folderSelector); 255 } 256 257 /** 258 * Initializes the result facets component. 259 */ 260 private void initResultFacets() { 261 262 m_resultFacets = new CmsResultFacets(CmsDateSearchComposite.this); 263 m_resultFacets.setWidthFull(); 264 m_resultFacets.setMargin(false); 265 m_resultFacets.setSpacing(true); 266 m_formLayout.addComponent(m_resultFacets); 267 } 268 269 /** 270 * Initializes the site selector. 271 */ 272 private void initSiteSelector() { 273 274 m_siteSelector = new CmsSiteSelector(); 275 m_siteSelector.setWidthFull(); 276 m_siteSelector.addValueChangeListener(event -> { 277 search(true, true); 278 }); 279 m_formLayout.addComponent(m_siteSelector); 280 } 281 282 /** 283 * Initializes the text search field. 284 */ 285 private void initTextSearchField() { 286 287 m_textSearchField = new TextField(); 288 m_textSearchField.setCaption(CmsVaadinUtils.getMessageText(Messages.GUI_LISTMANAGER_SEARCH_0)); 289 m_textSearchField.setWidthFull(); 290 m_textSearchField.addValueChangeListener(event -> { 291 search(true, true); 292 }); 293 m_formLayout.addComponent(m_textSearchField); 294 } 295 296 /** 297 * Initializes the type selector. 298 */ 299 private void initTypeSelector() { 300 301 m_typeSelector = new CmsTypeSelector(); 302 m_typeSelector.addValueChangeListener(event -> { 303 search(true, true); 304 }); 305 m_formLayout.addComponent(m_typeSelector); 306 } 307 } 308 309 /** 310 * The result component of the content finder. 311 */ 312 @SuppressWarnings("serial") 313 private class ResultComponent extends VerticalLayout { 314 315 /** Layout showing empty type message. */ 316 VerticalLayout m_infoEmptyType; 317 318 /** Layout showing empty result message. */ 319 VerticalLayout m_infoEmptyResult; 320 321 /** The file table. */ 322 CmsResultTable m_resultTable; 323 324 /** 325 * Creates a new result component. 326 */ 327 ResultComponent() { 328 329 setSizeFull(); 330 initInfoEmptyType(); 331 initInfoEmptyResult(); 332 initResultTable(); 333 } 334 335 /** 336 * Shows the empty result info layout. 337 */ 338 void showInfoEmptyResult() { 339 340 m_resultTable.setVisible(false); 341 m_infoEmptyType.setVisible(false); 342 m_infoEmptyResult.setVisible(true); 343 } 344 345 /** 346 * Shows the empty type info layout. 347 */ 348 void showInfoEmptyType() { 349 350 m_infoEmptyResult.setVisible(false); 351 m_resultTable.setVisible(false); 352 m_infoEmptyType.setVisible(true); 353 } 354 355 /** 356 * Updates the result table for given resources. 357 * @param resources the resources 358 */ 359 void updateResultTable(List<CmsResource> resources) { 360 361 m_infoEmptyType.setVisible(false); 362 m_infoEmptyResult.setVisible(false); 363 m_resultTable.fillTable(getCmsObject(), resources, true, false, true); 364 m_resultTable.setVisible(true); 365 } 366 367 /** 368 * Initializes the empty result info layout. 369 */ 370 private void initInfoEmptyResult() { 371 372 m_infoEmptyResult = CmsVaadinUtils.getInfoLayout(Messages.GUI_DATE_SEARCH_EMPTY_RESULT_0); 373 m_infoEmptyResult.setVisible(false); 374 addComponent(m_infoEmptyResult); 375 } 376 377 /** 378 * Initializes the empty type info layout. 379 */ 380 private void initInfoEmptyType() { 381 382 m_infoEmptyType = CmsVaadinUtils.getInfoLayout(Messages.GUI_DATE_SEARCH_EMPTY_TYPE_0); 383 m_infoEmptyType.setVisible(false); 384 addComponent(m_infoEmptyType); 385 } 386 387 /** 388 * Initializes the result table. 389 */ 390 private void initResultTable() { 391 392 LinkedHashMap<CmsResourceTableProperty, Integer> tableColumns = new LinkedHashMap<CmsResourceTableProperty, Integer>(); 393 for (Map.Entry<CmsResourceTableProperty, Integer> columnsEntry : CmsFileTable.DEFAULT_TABLE_PROPERTIES.entrySet()) { 394 if (columnsEntry.getKey().equals(CmsResourceTableProperty.PROPERTY_RESOURCE_TYPE)) { 395 tableColumns.put(CmsListManager.INSTANCEDATE_PROPERTY, Integer.valueOf(0)); 396 } 397 tableColumns.put(columnsEntry.getKey(), columnsEntry.getValue()); 398 } 399 m_resultTable = new CmsResultTable(null, tableColumns) { 400 401 /** 402 * Path, title, and type columns shall be visible and not collapsed. 403 * @see org.opencms.ui.components.CmsFileTable#applyWorkplaceAppSettings() 404 */ 405 @Override 406 public void applyWorkplaceAppSettings() { 407 408 super.applyWorkplaceAppSettings(); 409 m_fileTable.setColumnCollapsed(CmsResourceTableProperty.PROPERTY_SIZE, true); 410 m_fileTable.setColumnCollapsed(CmsResourceTableProperty.PROPERTY_DATE_MODIFIED, true); 411 m_fileTable.setColumnCollapsed(CmsListManager.INSTANCEDATE_PROPERTY, false); 412 } 413 414 /** 415 * Filter by path, title. 416 * @see org.opencms.ui.components.CmsFileTable#filterTable(java.lang.String) 417 */ 418 @Override 419 public void filterTable(String search) { 420 421 m_container.removeAllContainerFilters(); 422 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(search)) { 423 m_container.addContainerFilter( 424 new Or( 425 new SimpleStringFilter( 426 CmsResourceTableProperty.PROPERTY_SITE_PATH, 427 search, 428 true, 429 false), 430 new SimpleStringFilter(CmsResourceTableProperty.PROPERTY_TITLE, search, true, false))); 431 } 432 if ((m_fileTable.getValue() != null) & !((Set<?>)m_fileTable.getValue()).isEmpty()) { 433 m_fileTable.setCurrentPageFirstItemId(((Set<?>)m_fileTable.getValue()).iterator().next()); 434 } 435 } 436 }; 437 m_resultTable.applyWorkplaceAppSettings(); 438 m_resultTable.addPropertyProvider(CmsDateSearchComposite.this); 439 m_resultTable.setContextProvider(new I_CmsContextProvider() { 440 441 /** 442 * @see org.opencms.ui.apps.I_CmsContextProvider#getDialogContext() 443 */ 444 public I_CmsDialogContext getDialogContext() { 445 446 CmsFileTableDialogContext context = new CmsFileTableDialogContext( 447 CmsDateSearchConfiguration.APP_ID, 448 ContextType.fileTable, 449 m_resultTable, 450 m_resultTable.getSelectedResources()) { 451 452 /** 453 * @see org.opencms.ui.components.CmsFileTableDialogContext#finish(java.util.Collection) 454 */ 455 @Override 456 public void finish(Collection<CmsUUID> ids) { 457 458 if (m_resultTable.getSelectedItems() == null) { 459 super.finish(ids); 460 } else { 461 String itemId = m_resultTable.getCurrentPageFirstItemId(); 462 search(false, false); 463 m_resultTable.setCurrentPageFirstItemId(itemId); 464 closeWindow(); 465 } 466 } 467 }; 468 return context; 469 } 470 }); 471 m_resultTable.addAdditionalStyleGenerator(new CellStyleGenerator() { 472 473 public String getStyle(Table source, Object itemId, Object propertyId) { 474 475 String style = ""; 476 Item item = source.getItem(itemId); 477 if (CmsResourceTableProperty.PROPERTY_TITLE.equals(propertyId) 478 && ((item.getItemProperty(CmsResourceTableProperty.PROPERTY_RELEASED_NOT_EXPIRED) == null) 479 || ((Boolean)item.getItemProperty( 480 CmsResourceTableProperty.PROPERTY_RELEASED_NOT_EXPIRED).getValue()).booleanValue())) { 481 style += OpenCmsTheme.IN_NAVIGATION + " "; 482 } 483 return style; 484 } 485 486 }); 487 m_resultTable.setSizeFull(); 488 m_resultTable.setMenuBuilder(new CmsResourceContextMenuBuilder()); 489 m_resultTable.setVisible(false); 490 addComponent(m_resultTable); 491 } 492 } 493 494 /** 495 * The search component of the content finder. 496 */ 497 @SuppressWarnings("serial") 498 private class ResultFilterComponent extends CmsResultFilterComponent { 499 500 /** 501 * Creates a new search component. 502 */ 503 ResultFilterComponent() { 504 505 super(); 506 addTextChangeListener(new TextChangeListener() { 507 508 public void textChange(TextChangeEvent event) { 509 510 m_resultComponent.m_resultTable.filterTable(event.getText()); 511 512 } 513 }); 514 } 515 } 516 517 /** The log object for this class. */ 518 static final Log LOG = CmsLog.getLog(CmsDateSearchComposite.class); 519 520 /** The maximum number of results. */ 521 static final int MAX_RESULTS = 5000; 522 523 /** The filter component for this content finder. */ 524 FilterComponent m_filterComponent; 525 526 /** The result component for this content finder. */ 527 ResultComponent m_resultComponent; 528 529 /** The search component for this content finder. */ 530 CmsResultFilterComponent m_resultFilterComponent; 531 532 /** 533 * Creates a new content finder component. 534 */ 535 public CmsDateSearchComposite() { 536 537 m_filterComponent = new FilterComponent(); 538 m_filterComponent.updateTypeSelector(); 539 m_resultComponent = new ResultComponent(); 540 m_resultFilterComponent = new ResultFilterComponent(); 541 connectComponents(); 542 m_resultComponent.showInfoEmptyType(); 543 } 544 545 /** 546 * @see org.opencms.ui.components.CmsResourceTable.I_ResourcePropertyProvider#addItemProperties(com.vaadin.v7.data.Item, org.opencms.file.CmsObject, org.opencms.file.CmsResource, java.util.Locale) 547 */ 548 @SuppressWarnings("javadoc") 549 public void addItemProperties(Item resourceItem, CmsObject cms, CmsResource resource, Locale locale) { 550 551 if (resourceItem.getItemProperty(CmsResourceTableProperty.PROPERTY_TITLE) != null) { 552 CmsResourceUtil resUtil = new CmsResourceUtil(cms, resource); 553 String title = resUtil.getGalleryTitle(locale); 554 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(title)) { 555 resourceItem.getItemProperty(CmsResourceTableProperty.PROPERTY_TITLE).setValue(title); 556 } 557 } 558 if ((resource instanceof CmsSearchResource) 559 && (resourceItem.getItemProperty(CmsListManager.INSTANCEDATE_PROPERTY) != null)) { 560 List<String> contentLocales = ((CmsSearchResource)resource).getDocument().getMultivaluedFieldAsStringList( 561 CmsSearchField.FIELD_CONTENT_LOCALES); 562 if (contentLocales != null) { 563 for (String contentLocale : contentLocales) { 564 String dateFieldKey = CmsSearchField.FIELD_INSTANCEDATE + "_" + contentLocale + "_dt"; 565 Date date = ((CmsSearchResource)resource).getDateField(dateFieldKey); 566 if (date != null) { 567 resourceItem.getItemProperty(CmsListManager.INSTANCEDATE_PROPERTY).setValue(date); 568 } 569 } 570 } 571 } 572 } 573 574 /** 575 * Returns the filter component of this content finder. 576 * @return the filter component of this content finder 577 */ 578 public Component getFilterComponent() { 579 580 return m_filterComponent; 581 } 582 583 /** 584 * Returns the result component of this content finder. 585 * @return the result component of this content finder 586 */ 587 public Component getResultComponent() { 588 589 return m_resultComponent; 590 } 591 592 /** 593 * Returns the result filter component of this content finder. 594 * @return the result filter component of this content finder 595 */ 596 public Component getResultFilterComponent() { 597 598 return m_resultFilterComponent; 599 } 600 601 /** 602 * Executes the search. 603 * @param updateState whether to update the app state 604 * @param resetSelectedFacets whether to reset the selected facets 605 */ 606 public void search(boolean updateState, boolean resetSelectedFacets) { 607 608 if (resetSelectedFacets) { 609 m_filterComponent.m_resultFacets.resetFacets(); 610 m_filterComponent.m_resultFacets.setVisible(false); 611 } 612 if (updateState) { 613 CmsComponentState componentState = new CmsComponentState(); 614 componentState.setSite((String)m_filterComponent.m_siteSelector.getValue()); 615 componentState.setFolder(m_filterComponent.m_folderSelector.getValue()); 616 componentState.setResourceType((I_CmsResourceType)m_filterComponent.m_typeSelector.getValue()); 617 componentState.setDateFrom(m_filterComponent.m_dateFrom.getDate()); 618 componentState.setDateTo(m_filterComponent.m_dateTo.getDate()); 619 componentState.setAvailability(m_filterComponent.m_availabilitySelector.getValue().getFirst()); 620 componentState.setQuery(m_filterComponent.m_textSearchField.getValue()); 621 componentState.setCategory(m_filterComponent.getSelectedCategory()); 622 CmsAppWorkplaceUi.get().changeCurrentAppState(componentState.generateStateString()); 623 } 624 if (m_filterComponent.m_typeSelector.getValue() == null) { 625 m_resultComponent.showInfoEmptyType(); 626 } else { 627 CmsSolrResultList solrResultList = search(null); 628 List<CmsResource> results = new ArrayList<CmsResource>(solrResultList); 629 if (results.isEmpty()) { 630 m_resultComponent.showInfoEmptyResult(); 631 } else { 632 m_resultComponent.updateResultTable(results); 633 Map<String, Boolean> checkedCategoryFacets = new HashMap<String, Boolean>(); 634 if (!m_filterComponent.m_resultFacets.getSelectedFieldFacets().isEmpty()) { 635 checkedCategoryFacets.put( 636 m_filterComponent.m_resultFacets.getSelectedFieldFacets().get( 637 CmsSearchField.FIELD_CATEGORY_EXACT).get(0), 638 Boolean.TRUE); 639 } 640 m_filterComponent.m_resultFacets.displayFacetResult( 641 solrResultList, 642 checkedCategoryFacets, 643 null, 644 null, 645 getCmsObject()); 646 m_filterComponent.m_resultFacets.setVisible(true); 647 } 648 } 649 } 650 651 /** 652 * @see org.opencms.ui.components.I_CmsResultFacetsManager#search(java.util.Map, java.util.Map) 653 */ 654 public void search(Map<String, List<String>> fieldFacets, Map<String, List<String>> rangeFacets) { 655 656 search(true, false); 657 } 658 659 /** 660 * Sets a component state. 661 * @param componentState the component state 662 */ 663 public void setState(CmsComponentState componentState) { 664 665 m_filterComponent.m_siteSelector.setValue(componentState.getSite()); 666 m_filterComponent.m_folderSelector.setValue(componentState.getFolder()); 667 m_filterComponent.m_typeSelector.setValue(componentState.getResourceType()); 668 m_filterComponent.m_dateFrom.setDate(componentState.getDateFrom()); 669 m_filterComponent.m_dateTo.setDate(componentState.getDateTo()); 670 m_filterComponent.m_availabilitySelector.setValue( 671 m_filterComponent.m_availabilitySelector.getOption(componentState.getAvailability())); 672 if (componentState.getCategory() != null) { 673 m_filterComponent.m_resultFacets.selectFieldFacet( 674 CmsSearchField.FIELD_CATEGORY_EXACT, 675 componentState.getCategory()); 676 } 677 m_filterComponent.m_textSearchField.setValue(componentState.getQuery()); 678 } 679 680 /** 681 * Returns the list of XML content types relevant for the content finder. 682 * @return the list of XML content types relevant for the content finder 683 */ 684 List<I_CmsResourceType> getAvailableTypes() { 685 686 CmsSolrResultList solrResultList = search(Integer.valueOf(0)); 687 List<I_CmsResourceType> result = new ArrayList<>(); 688 for (Count count : solrResultList.getFacetField(CmsSearchField.FIELD_TYPE).getValues()) { 689 String typeName = count.getName(); 690 CmsExplorerTypeSettings typeSetting = OpenCms.getWorkplaceManager().getExplorerTypeSetting(typeName); 691 if (typeSetting == null) { 692 continue; 693 } 694 try { 695 I_CmsResourceType resourceType = OpenCms.getResourceManager().getResourceType(typeName); 696 result.add(resourceType); 697 } catch (CmsLoaderException e) { 698 LOG.error(e.getLocalizedMessage(), e); 699 } 700 } 701 return result; 702 } 703 704 /** 705 * Returns the current CMS context of this content finder. 706 * @return the current CMS context of this content finder 707 */ 708 CmsObject getCmsObject() { 709 710 if ((m_filterComponent == null) || (m_filterComponent.m_folderSelector == null)) { 711 return A_CmsUI.getCmsObject(); 712 } 713 CmsObject folderSelectorCms = m_filterComponent.m_folderSelector.getCmsObject(); 714 return folderSelectorCms == null ? A_CmsUI.getCmsObject() : folderSelectorCms; 715 } 716 717 /** 718 * Builds the Solr query. 719 * @return the Solr query 720 */ 721 private CmsSolrQuery buildQuery() { 722 723 CmsSolrQuery query = new CmsSolrQuery(getCmsObject(), null); 724 query.setSort(CmsSearchField.FIELD_PATH, ORDER.asc); 725 query.addFacetField(CmsSearchField.FIELD_TYPE); 726 query.addFacetField(CmsSearchField.FIELD_CONTENT_LOCALES); 727 query.addFacetField("{!ex=ce}" + CmsSearchField.FIELD_CATEGORY_EXACT); 728 query.setFacetMinCount(1); 729 List<String> filterQueries = new ArrayList<String>(); 730 filterQueries.add(CmsSearchField.FIELD_CONTENT_LOCALES + ":*"); 731 String site = (String)m_filterComponent.m_siteSelector.getValue(); 732 String folder = m_filterComponent.m_folderSelector.getValue(); 733 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(folder)) { 734 String path = CmsStringUtil.joinPaths(site, folder); 735 filterQueries.add(CmsSearchField.FIELD_PARENT_FOLDERS + ":\"" + path + "\""); 736 } else { 737 if (site != null) { 738 site = site.endsWith("/") ? site : site + "/"; 739 } 740 filterQueries.add(CmsSearchField.FIELD_PARENT_FOLDERS + ":\"" + site + "\""); 741 } 742 I_CmsResourceType type = (I_CmsResourceType)m_filterComponent.m_typeSelector.getValue(); 743 if (type != null) { 744 filterQueries.add(CmsSearchField.FIELD_TYPE + ":" + type.getTypeName()); 745 } 746 Date dateFrom = m_filterComponent.m_dateFrom.getDate(); 747 Date dateTo = m_filterComponent.m_dateTo.getDate(); 748 String dateRangeQuery = null; 749 if ((dateFrom != null) || (dateTo != null)) { 750 List<String> dateRangeQueries = new ArrayList<String>(); 751 List<Locale> availableLocales = OpenCms.getLocaleManager().getAvailableLocales(getCmsObject(), folder); 752 for (Locale locale : availableLocales) { 753 CmsDateRangeRestriction restriction = new CmsDateRangeRestriction(dateFrom, dateTo); 754 dateRangeQueries.add( 755 CmsSearchField.FIELD_INSTANCEDATE_CURRENT_TILL 756 + "_" 757 + locale 758 + CmsSearchField.FIELD_POSTFIX_DATE 759 + ":" 760 + restriction.getRange()); 761 } 762 dateRangeQuery = "(" + String.join(" OR ", dateRangeQueries) + ")"; 763 filterQueries.add(dateRangeQuery); 764 } 765 if (!filterQueries.isEmpty()) { 766 if (m_filterComponent.m_availabilitySelector.isOptionWithout()) { 767 query.setFilterQueries(String.join(" AND ", filterQueries)); 768 } else if (m_filterComponent.m_availabilitySelector.isOptionOnly()) { 769 Date now = new Date(); 770 CmsDateRangeRestriction releasedRestriction = new CmsDateRangeRestriction(now, null); 771 CmsDateRangeRestriction expiredRestriction = new CmsDateRangeRestriction(null, now); 772 String releasedQuery = "released:" + releasedRestriction.getRange(); 773 String expiredQuery = "expired:" + expiredRestriction.getRange(); 774 String releasedOrExpiredQuery = releasedQuery + " OR " + expiredQuery; 775 String expiredOrReleasedQuery = expiredQuery + " OR " + releasedQuery; // fix to avoid rewrite of query 776 query.setFilterQueries( 777 String.join(" AND ", filterQueries), 778 releasedOrExpiredQuery, 779 expiredOrReleasedQuery); 780 } else { 781 String releasedQuery = "released:[* TO *]"; 782 String expiredQuery = "expired:[* TO *]"; 783 query.setFilterQueries(String.join(" AND ", filterQueries), releasedQuery, expiredQuery); 784 } 785 } 786 List<String> checkedCategories = m_filterComponent.m_resultFacets.getSelectedFieldFacets().get( 787 "category_exact"); 788 if ((checkedCategories != null) && !checkedCategories.isEmpty()) { 789 query.addFilterQuery( 790 "{!tag=ce}" + CmsSearchField.FIELD_CATEGORY_EXACT + ":\"" + checkedCategories.get(0) + "\""); 791 } 792 String textSearch = m_resultFilterComponent == null ? null : m_filterComponent.m_textSearchField.getValue(); 793 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(textSearch)) { 794 query.setQuery(ClientUtils.escapeQueryChars(textSearch)); 795 } 796 return query; 797 } 798 799 /** 800 * Connects all filter, search, and result components. 801 */ 802 @SuppressWarnings("serial") 803 private void connectComponents() { 804 805 // update the folder selector and locale selector when the site selector changes 806 m_filterComponent.m_siteSelector.addValueChangeListener(new ValueChangeListener() { 807 808 public void valueChange(ValueChangeEvent arg0) { 809 810 try { 811 CmsObject newCms = OpenCms.initCmsObject(A_CmsUI.getCmsObject()); 812 newCms.getRequestContext().setSiteRoot((String)m_filterComponent.m_siteSelector.getValue()); 813 m_filterComponent.m_folderSelector.setCmsObject(newCms); 814 m_filterComponent.m_folderSelector.setValue("/"); 815 m_filterComponent.updateTypeSelector(); 816 m_filterComponent.m_dateFrom.setValue(null); 817 m_filterComponent.m_dateTo.setValue(null); 818 m_filterComponent.m_availabilitySelector.reset(); 819 } catch (CmsException e) { 820 LOG.error(e.getLocalizedMessage(), e); 821 } 822 } 823 }); 824 // update the locale selector when the folder selector changes 825 m_filterComponent.m_folderSelector.addValueChangeListener(new ValueChangeListener() { 826 827 public void valueChange(ValueChangeEvent event) { 828 829 m_filterComponent.updateTypeSelector(); 830 m_filterComponent.m_dateFrom.setValue(null); 831 m_filterComponent.m_dateTo.setValue(null); 832 m_filterComponent.m_availabilitySelector.reset(); 833 } 834 }); 835 } 836 837 /** 838 * Executes the search and returns the results. 839 * @param rows the number of rows to return 840 * @return the results 841 */ 842 private CmsSolrResultList search(Integer rows) { 843 844 CmsSolrQuery query = buildQuery(); 845 boolean online = getCmsObject().getRequestContext().getCurrentProject().isOnlineProject(); 846 String indexName = online ? CmsSolrIndex.DEFAULT_INDEX_NAME_ONLINE : CmsSolrIndex.DEFAULT_INDEX_NAME_OFFLINE; 847 CmsSolrIndex index = OpenCms.getSearchManager().getIndexSolr(indexName); 848 query.setRows(rows == null ? Integer.valueOf(MAX_RESULTS) : rows); 849 try { 850 return index.search(getCmsObject(), query, true, null, true, CmsResourceFilter.ALL, MAX_RESULTS); 851 } catch (CmsSearchException e) { 852 CmsErrorDialog.showErrorDialog(e); 853 LOG.error(e.getLocalizedMessage(), e); 854 return null; 855 } 856 } 857}