001/* 002 * (C) Copyright 2010-2016 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Anahide Tchertchian 018 */ 019package org.nuxeo.ecm.platform.contentview.jsf; 020 021import static org.apache.commons.lang3.StringUtils.isBlank; 022 023import java.util.ArrayList; 024import java.util.List; 025import java.util.Map; 026 027import javax.faces.context.ExternalContext; 028import javax.faces.context.FacesContext; 029 030import org.apache.commons.lang3.StringUtils; 031import org.apache.commons.logging.Log; 032import org.apache.commons.logging.LogFactory; 033import org.jboss.seam.core.Events; 034import org.nuxeo.ecm.core.api.DocumentModel; 035import org.nuxeo.ecm.core.api.DocumentModelFactory; 036import org.nuxeo.ecm.core.api.PropertyException; 037import org.nuxeo.ecm.core.api.SortInfo; 038import org.nuxeo.ecm.core.api.model.impl.MapProperty; 039import org.nuxeo.ecm.platform.query.api.Aggregate; 040import org.nuxeo.ecm.platform.query.api.PageProvider; 041import org.nuxeo.ecm.platform.query.api.PageProviderChangedListener; 042import org.nuxeo.ecm.platform.query.api.QuickFilter; 043import org.nuxeo.ecm.platform.ui.web.util.ComponentTagUtils; 044import org.nuxeo.runtime.api.Framework; 045 046import com.google.common.base.Function; 047 048/** 049 * Default implementation for the content view object. 050 * <p> 051 * Provides simple getters for attributes defined in the XMap descriptor, except cache key which is computed from 052 * currrent {@link FacesContext} instance if cache key is an EL expression. 053 * <p> 054 * The page provider is initialized calling {@link ContentViewService#getPageProvider}. 055 * 056 * @author Anahide Tchertchian 057 * @since 5.4 058 */ 059public class ContentViewImpl implements ContentView, PageProviderChangedListener { 060 061 private static final long serialVersionUID = 1L; 062 063 private static final Log log = LogFactory.getLog(ContentViewImpl.class); 064 065 protected String name; 066 067 protected PageProvider<?> pageProvider; 068 069 protected String title; 070 071 protected boolean translateTitle; 072 073 protected String emptySentence; 074 075 protected boolean translateEmptySentence; 076 077 protected String iconPath; 078 079 protected boolean showTitle; 080 081 protected String selectionList; 082 083 protected String pagination; 084 085 protected List<String> actionCategories; 086 087 protected ContentViewLayout searchLayout; 088 089 protected List<ContentViewLayout> resultLayouts; 090 091 protected List<String> flags; 092 093 protected boolean currentResultLayoutSet = false; 094 095 protected ContentViewLayout currentResultLayout; 096 097 protected List<String> currentResultLayoutColumns; 098 099 protected String cacheKey; 100 101 protected Integer cacheSize; 102 103 protected List<String> refreshEventNames; 104 105 protected List<String> resetEventNames; 106 107 protected boolean useGlobalPageSize; 108 109 protected boolean showPageSizeSelector; 110 111 protected boolean showRefreshCommand; 112 113 protected boolean showFilterForm; 114 115 protected Long currentPageSize; 116 117 protected String[] queryParameters; 118 119 protected DocumentModel searchDocumentModel; 120 121 protected String searchDocumentModelBinding; 122 123 protected String searchDocumentModelType; 124 125 protected String resultColumnsBinding; 126 127 protected String resultLayoutBinding; 128 129 protected String pageSizeBinding; 130 131 protected String sortInfosBinding; 132 133 protected boolean waitForExecution = false; 134 135 protected String waitForExecutionSentence; 136 137 protected boolean executed = false; 138 139 /** 140 * @since 8.4 141 */ 142 protected List<QuickFilter> quickFilters; 143 144 public ContentViewImpl(String name, String title, boolean translateTitle, String iconPath, String selectionList, 145 String pagination, List<String> actionCategories, ContentViewLayout searchLayout, 146 List<ContentViewLayout> resultLayouts, List<String> flags, String cacheKey, Integer cacheSize, 147 List<String> refreshEventNames, List<String> resetEventNames, boolean useGlobalPageSize, 148 String[] queryParameters, String searchDocumentModelBinding, String searchDocumentModelType, 149 String resultColumnsBinding, String resultLayoutBinding, String sortInfosBinding, String pageSizeBinding, 150 boolean showTitle, boolean showPageSizeSelector, boolean showRefreshCommand, boolean showFilterForm, 151 String emptySentence, boolean translateEmptySentence) { 152 this.name = name; 153 this.title = title; 154 this.translateTitle = translateTitle; 155 this.iconPath = iconPath; 156 this.selectionList = selectionList; 157 this.pagination = pagination; 158 this.actionCategories = actionCategories; 159 this.searchLayout = searchLayout; 160 this.resultLayouts = resultLayouts; 161 this.flags = flags; 162 this.cacheKey = cacheKey; 163 this.cacheSize = cacheSize; 164 if (cacheSize != null && cacheSize.intValue() <= 0) { 165 // force a static cache key 166 this.cacheKey = "static_key_no_cache"; 167 } 168 this.refreshEventNames = refreshEventNames; 169 this.resetEventNames = resetEventNames; 170 this.useGlobalPageSize = useGlobalPageSize; 171 this.queryParameters = queryParameters; 172 this.searchDocumentModelBinding = searchDocumentModelBinding; 173 this.searchDocumentModelType = searchDocumentModelType; 174 this.resultColumnsBinding = resultColumnsBinding; 175 this.resultLayoutBinding = resultLayoutBinding; 176 this.pageSizeBinding = pageSizeBinding; 177 this.sortInfosBinding = sortInfosBinding; 178 this.showTitle = showTitle; 179 this.showPageSizeSelector = showPageSizeSelector; 180 this.showRefreshCommand = showRefreshCommand; 181 this.showFilterForm = showFilterForm; 182 this.emptySentence = emptySentence; 183 this.translateEmptySentence = translateEmptySentence; 184 } 185 186 @Override 187 public String getName() { 188 return name; 189 } 190 191 @Override 192 public String getTitle() { 193 return title; 194 } 195 196 @Override 197 public boolean getTranslateTitle() { 198 return translateTitle; 199 } 200 201 @Override 202 public String getIconPath() { 203 return iconPath; 204 } 205 206 @Override 207 public String getSelectionListName() { 208 return selectionList; 209 } 210 211 @Override 212 public String getPagination() { 213 return pagination; 214 } 215 216 @Override 217 public List<String> getActionsCategories() { 218 return actionCategories; 219 } 220 221 @Override 222 public ContentViewLayout getSearchLayout() { 223 return searchLayout; 224 } 225 226 @Override 227 public List<ContentViewLayout> getResultLayouts() { 228 return resultLayouts; 229 } 230 231 @Override 232 public ContentViewLayout getCurrentResultLayout() { 233 // resolve binding if it is set 234 if (!currentResultLayoutSet && !StringUtils.isBlank(resultLayoutBinding)) { 235 Object res = resolveWithSearchDocument( 236 ctx -> ComponentTagUtils.resolveElExpression(ctx, resultLayoutBinding)); 237 if (res != null && res instanceof String) { 238 setCurrentResultLayout((String) res); 239 currentResultLayoutSet = true; 240 } 241 } 242 if (currentResultLayout == null && resultLayouts != null && !resultLayouts.isEmpty()) { 243 // resolve first current result layout 244 return resultLayouts.get(0); 245 } 246 return currentResultLayout; 247 } 248 249 @Override 250 public void setCurrentResultLayout(final ContentViewLayout layout) { 251 setCurrentResultLayout(layout, true); 252 } 253 254 public void setCurrentResultLayout(final ContentViewLayout layout, boolean resetLayoutColumn) { 255 if (!isBlank(resultLayoutBinding) && ComponentTagUtils.isStrictValueReference(resultLayoutBinding)) { 256 resolveWithSearchDocument(ctx -> { 257 ComponentTagUtils.applyValueExpression(ctx, resultLayoutBinding, 258 layout == null ? null : layout.getName()); 259 return null; 260 }); 261 } 262 // still set current result layout value 263 currentResultLayoutSet = true; 264 currentResultLayout = layout; 265 266 if (resetLayoutColumn) { 267 // reset corresponding columns 268 setCurrentResultLayoutColumns(null); 269 } 270 } 271 272 protected Object resolveWithSearchDocument(Function<FacesContext, Object> func) { 273 FacesContext ctx = FacesContext.getCurrentInstance(); 274 if (getSearchDocumentModel() == null) { 275 return func.apply(ctx); 276 } else { 277 Object previousSearchDocValue = addSearchDocumentToELContext(ctx); 278 try { 279 return func.apply(ctx); 280 } finally { 281 removeSearchDocumentFromELContext(ctx, previousSearchDocValue); 282 } 283 } 284 } 285 286 @Override 287 public void setCurrentResultLayout(String resultLayoutName) { 288 if (resultLayoutName != null) { 289 for (ContentViewLayout layout : resultLayouts) { 290 if (resultLayoutName.equals(layout.getName())) { 291 setCurrentResultLayout(layout, false); 292 } 293 } 294 } 295 } 296 297 @Override 298 public boolean hasResultLayoutBinding() { 299 return !isBlank(resultLayoutBinding); 300 } 301 302 /** 303 * Returns cached page provider if it exists or build a new one if parameters have changed. 304 * <p> 305 * The search document, current page and page size are set on the page provider anyway. Sort infos are not set again 306 * if page provider was not built again (e.g if parameters did not change) to avoid erasing sort infos already held 307 * by it. 308 */ 309 @Override 310 public PageProvider<?> getPageProvider(DocumentModel searchDocument, List<SortInfo> sortInfos, Long pageSize, 311 Long currentPage, Object... params) { 312 // do not return any page provider if filter has not been done yet 313 if (isWaitForExecution() && !isExecuted()) { 314 return null; 315 } 316 317 // resolve search doc so that it can be used in EL expressions defined 318 // in XML configuration 319 boolean setSearchDoc = false; 320 DocumentModel finalSearchDocument = null; 321 if (searchDocument != null) { 322 setSearchDoc = true; 323 finalSearchDocument = searchDocument; 324 } else if (searchDocumentModel == null) { 325 setSearchDoc = true; 326 if (pageProvider != null) { 327 // try to retrieve it on current page provider 328 finalSearchDocument = pageProvider.getSearchDocumentModel(); 329 } 330 if (finalSearchDocument == null) { 331 // initialize it and set it => do not need to set it again 332 finalSearchDocument = getSearchDocumentModel(); 333 setSearchDoc = false; 334 } 335 } else { 336 finalSearchDocument = searchDocumentModel; 337 } 338 if (setSearchDoc) { 339 // set it on content view so that it can be used when resolving EL 340 // expressions 341 setSearchDocumentModel(finalSearchDocument); 342 } 343 344 // fallback on local parameters if defined in the XML configuration 345 if (params == null) { 346 params = getQueryParameters(); 347 } 348 if (sortInfos == null) { 349 sortInfos = resolveSortInfos(); 350 } 351 // allow to pass negative integers instead of null: EL transforms 352 // numbers into value 0 for numbers 353 if (pageSize != null && pageSize.longValue() < 0) { 354 pageSize = null; 355 } 356 if (currentPage != null && currentPage.longValue() < 0) { 357 currentPage = null; 358 } 359 if (pageSize == null) { 360 if (currentPageSize != null && currentPageSize.longValue() >= 0) { 361 pageSize = currentPageSize; 362 } 363 if (pageSize == null) { 364 pageSize = resolvePageSize(); 365 } 366 } 367 368 // parameters changed => reset provider. 369 // do not force setting of sort infos as they can be set directly on 370 // the page provider and this method will be called after so they could 371 // be lost. 372 if (pageProvider == null || pageProvider.hasChangedParameters(params)) { 373 // make the service build the provider 374 ContentViewService service = Framework.getService(ContentViewService.class); 375 pageProvider = service.getPageProvider(getName(), sortInfos, pageSize, currentPage, finalSearchDocument, 376 params); 377 } else { 378 if (pageSize != null) { 379 pageProvider.setPageSize(pageSize.longValue()); 380 } 381 if (currentPage != null) { 382 pageProvider.setCurrentPage(currentPage.longValue()); 383 } 384 } 385 386 pageProvider.setQuickFilters(new ArrayList<>()); 387 388 // Register listener to be notified when the page has changed on the 389 // page provider 390 pageProvider.setPageProviderChangedListener(this); 391 return pageProvider; 392 } 393 394 @Override 395 public PageProvider<?> getPageProviderWithParams(Object... params) { 396 return getPageProvider(null, null, null, null, params); 397 } 398 399 @Override 400 public PageProvider<?> getPageProvider() { 401 return getPageProviderWithParams((Object[]) null); 402 } 403 404 @Override 405 public PageProvider<?> getCurrentPageProvider() { 406 return pageProvider; 407 } 408 409 @Override 410 public void resetPageProvider() { 411 pageProvider = null; 412 } 413 414 @Override 415 public void refreshPageProvider() { 416 if (pageProvider != null) { 417 pageProvider.refresh(); 418 } 419 setExecuted(true); 420 } 421 422 @Override 423 public void refreshAndRewindPageProvider() { 424 if (pageProvider != null) { 425 pageProvider.refresh(); 426 pageProvider.firstPage(); 427 } 428 setExecuted(true); 429 } 430 431 @Override 432 public String getCacheKey() { 433 FacesContext context = FacesContext.getCurrentInstance(); 434 Object value = ComponentTagUtils.resolveElExpression(context, cacheKey); 435 if (value != null && !(value instanceof String)) { 436 log.error("Error processing expression '" + cacheKey + "', result is not a String: " + value); 437 } 438 return (String) value; 439 } 440 441 @Override 442 public Integer getCacheSize() { 443 return cacheSize; 444 } 445 446 @Override 447 public Object[] getQueryParameters() { 448 if (queryParameters == null) { 449 return null; 450 } 451 FacesContext context = FacesContext.getCurrentInstance(); 452 Object previousSearchDocValue = addSearchDocumentToELContext(context); 453 try { 454 Object[] res = new Object[queryParameters.length]; 455 for (int i = 0; i < queryParameters.length; i++) { 456 res[i] = ComponentTagUtils.resolveElExpression(context, queryParameters[i]); 457 } 458 return res; 459 } finally { 460 removeSearchDocumentFromELContext(context, previousSearchDocValue); 461 } 462 } 463 464 @Override 465 public List<String> getRefreshEventNames() { 466 return refreshEventNames; 467 } 468 469 @Override 470 public List<String> getResetEventNames() { 471 return resetEventNames; 472 } 473 474 @Override 475 public boolean getUseGlobalPageSize() { 476 return useGlobalPageSize; 477 } 478 479 @Override 480 public Long getCurrentPageSize() { 481 // take actual value on page provider first in case it's reached its 482 // max page size 483 if (pageProvider != null) { 484 long pageSize = pageProvider.getPageSize(); 485 long maxPageSize = pageProvider.getMaxPageSize(); 486 if (pageSize > 0 && maxPageSize > 0 && maxPageSize < pageSize) { 487 return Long.valueOf(maxPageSize); 488 } 489 return Long.valueOf(pageSize); 490 } 491 if (currentPageSize != null && currentPageSize.longValue() >= 0) { 492 return currentPageSize; 493 } 494 return null; 495 } 496 497 @Override 498 public void setCurrentPageSize(Long pageSize) { 499 currentPageSize = pageSize; 500 raiseEvent(CONTENT_VIEW_PAGE_SIZE_CHANGED_EVENT); 501 } 502 503 @Override 504 public DocumentModel getSearchDocumentModel() { 505 if (searchDocumentModel == null) { 506 if (searchDocumentModelBinding != null) { 507 // initialize from binding 508 FacesContext context = FacesContext.getCurrentInstance(); 509 Object value = ComponentTagUtils.resolveElExpression(context, searchDocumentModelBinding); 510 if (value != null && !(value instanceof DocumentModel)) { 511 log.error("Error processing expression '" + searchDocumentModelBinding 512 + "', result is not a DocumentModel: " + value); 513 } else { 514 setSearchDocumentModel((DocumentModel) value); 515 } 516 } 517 if (searchDocumentModel == null) { 518 // generate a bare document model of given type 519 String docType = getSearchDocumentModelType(); 520 if (docType != null) { 521 DocumentModel bareDoc = DocumentModelFactory.createDocumentModel(docType); 522 setSearchDocumentModel(bareDoc); 523 } 524 } 525 } 526 return searchDocumentModel; 527 } 528 529 @Override 530 public void setSearchDocumentModel(DocumentModel searchDocumentModel) { 531 this.searchDocumentModel = searchDocumentModel; 532 if (pageProvider != null) { 533 pageProvider.setSearchDocumentModel(searchDocumentModel); 534 } 535 } 536 537 @Override 538 public void resetSearchDocumentModel() { 539 searchDocumentModel = null; 540 if (pageProvider != null) { 541 pageProvider.setSearchDocumentModel(null); 542 } 543 } 544 545 @Override 546 public String getSearchDocumentModelType() { 547 return searchDocumentModelType; 548 } 549 550 @Override 551 public List<String> getFlags() { 552 return flags; 553 } 554 555 @Override 556 @SuppressWarnings({ "unchecked", "rawtypes" }) 557 public List<String> getCurrentResultLayoutColumns() { 558 // always resolve binding if it is set 559 if (!StringUtils.isBlank(resultColumnsBinding)) { 560 Object res = resolveWithSearchDocument(ctx -> { 561 Object value = ComponentTagUtils.resolveElExpression(ctx, resultColumnsBinding); 562 if (value != null && !(value instanceof List)) { 563 log.error("Error processing expression '" + resultColumnsBinding + "', result is not a List: " 564 + value); 565 } 566 return value; 567 }); 568 if (res != null && res instanceof List) { 569 return ((List) res).isEmpty() ? null : (List) res; 570 } 571 } 572 return currentResultLayoutColumns; 573 } 574 575 @Override 576 public void setCurrentResultLayoutColumns(final List<String> resultColumns) { 577 if (isBlank(resultColumnsBinding) || !ComponentTagUtils.isStrictValueReference(resultColumnsBinding)) { 578 // set local values 579 currentResultLayoutColumns = resultColumns; 580 } else { 581 resolveWithSearchDocument(ctx -> { 582 ComponentTagUtils.applyValueExpression(ctx, resultColumnsBinding, resultColumns); 583 return null; 584 }); 585 } 586 } 587 588 @Override 589 public boolean hasResultLayoutColumnsBinding() { 590 return !isBlank(resultColumnsBinding); 591 } 592 593 @SuppressWarnings({ "unchecked", "rawtypes" }) 594 protected List<SortInfo> resolveSortInfos() { 595 if (sortInfosBinding == null) { 596 return null; 597 } 598 FacesContext context = FacesContext.getCurrentInstance(); 599 Object previousSearchDocValue = addSearchDocumentToELContext(context); 600 try { 601 Object value = ComponentTagUtils.resolveElExpression(context, sortInfosBinding); 602 if (value != null && !(value instanceof List)) { 603 log.error("Error processing expression '" + sortInfosBinding + "', result is not a List: '" + value 604 + "'"); 605 } 606 if (value == null) { 607 return null; 608 } 609 List<SortInfo> res = new ArrayList<>(); 610 List listValue = (List) value; 611 for (Object listItem : listValue) { 612 if (listItem instanceof SortInfo) { 613 res.add((SortInfo) listItem); 614 } else if (listItem instanceof Map) { 615 // XXX: MapProperty does not implement containsKey, so 616 // resolve 617 // value instead 618 if (listItem instanceof MapProperty) { 619 try { 620 listItem = ((MapProperty) listItem).getValue(); 621 } catch (ClassCastException | PropertyException e) { 622 log.error("Cannot resolve sort info item: " + listItem, e); 623 } 624 } 625 Map map = (Map) listItem; 626 SortInfo sortInfo = SortInfo.asSortInfo(map); 627 if (sortInfo != null) { 628 res.add(sortInfo); 629 } else { 630 log.error("Cannot resolve sort info item: " + listItem); 631 } 632 } else { 633 log.error("Cannot resolve sort info item: " + listItem); 634 } 635 } 636 if (res.isEmpty()) { 637 return null; 638 } 639 return res; 640 } finally { 641 removeSearchDocumentFromELContext(context, previousSearchDocValue); 642 } 643 } 644 645 protected Long resolvePageSize() { 646 if (pageSizeBinding == null) { 647 return null; 648 } 649 FacesContext context = FacesContext.getCurrentInstance(); 650 Object previousSearchDocValue = addSearchDocumentToELContext(context); 651 try { 652 Object value = ComponentTagUtils.resolveElExpression(context, pageSizeBinding); 653 if (value == null) { 654 return null; 655 } 656 if (value instanceof String) { 657 try { 658 return Long.valueOf((String) value); 659 } catch (NumberFormatException e) { 660 log.error("Error processing expression '" + pageSizeBinding + "', result is not a Long: '" + value 661 + "'"); 662 } 663 } else if (value instanceof Number) { 664 return Long.valueOf(((Number) value).longValue()); 665 } 666 return null; 667 } finally { 668 removeSearchDocumentFromELContext(context, previousSearchDocValue); 669 } 670 } 671 672 protected Object addSearchDocumentToELContext(FacesContext facesContext) { 673 ExternalContext econtext = null; 674 if (facesContext != null) { 675 econtext = facesContext.getExternalContext(); 676 } 677 if (facesContext == null || econtext == null) { 678 log.error("JSF context is null: cannot expose variable '" + SEARCH_DOCUMENT_EL_VARIABLE 679 + "' for content view '" + getName() + "'"); 680 return null; 681 } 682 Map<String, Object> requestMap = econtext.getRequestMap(); 683 Object previousValue = requestMap.get(SEARCH_DOCUMENT_EL_VARIABLE); 684 requestMap.put(SEARCH_DOCUMENT_EL_VARIABLE, searchDocumentModel); 685 return previousValue; 686 } 687 688 protected void removeSearchDocumentFromELContext(FacesContext facesContext, Object previousValue) { 689 if (facesContext == null) { 690 // ignore 691 return; 692 } 693 ExternalContext econtext = facesContext.getExternalContext(); 694 if (econtext != null) { 695 Map<String, Object> requestMap = econtext.getRequestMap(); 696 requestMap.remove(SEARCH_DOCUMENT_EL_VARIABLE); 697 if (previousValue != null) { 698 requestMap.put(SEARCH_DOCUMENT_EL_VARIABLE, previousValue); 699 } 700 } else { 701 log.error("External context is null: cannot dispose variable '" + SEARCH_DOCUMENT_EL_VARIABLE 702 + "' for content view '" + getName() + "'"); 703 } 704 } 705 706 @Override 707 public boolean getShowPageSizeSelector() { 708 return showPageSizeSelector; 709 } 710 711 @Override 712 public boolean getShowRefreshCommand() { 713 return showRefreshCommand; 714 } 715 716 @Override 717 public boolean getShowFilterForm() { 718 return showFilterForm; 719 } 720 721 @Override 722 public boolean getShowTitle() { 723 return showTitle; 724 } 725 726 @Override 727 public String getEmptySentence() { 728 return emptySentence; 729 } 730 731 @Override 732 public boolean getTranslateEmptySentence() { 733 return translateEmptySentence; 734 } 735 736 @Override 737 public String toString() { 738 final StringBuilder buf = new StringBuilder(); 739 buf.append("ContentViewImpl") 740 .append(" {") 741 .append(" name=") 742 .append(name) 743 .append(", title=") 744 .append(title) 745 .append(", translateTitle=") 746 .append(translateTitle) 747 .append(", iconPath=") 748 .append(iconPath) 749 .append(", selectionList=") 750 .append(selectionList) 751 .append(", pagination=") 752 .append(pagination) 753 .append(", actionCategories=") 754 .append(actionCategories) 755 .append(", searchLayout=") 756 .append(searchLayout) 757 .append(", resultLayouts=") 758 .append(resultLayouts) 759 .append(", currentResultLayout=") 760 .append(currentResultLayout) 761 .append(", flags=") 762 .append(flags) 763 .append(", cacheKey=") 764 .append(cacheKey) 765 .append(", cacheSize=") 766 .append(cacheSize) 767 .append(", currentPageSize=") 768 .append(currentPageSize) 769 .append(", refreshEventNames=") 770 .append(refreshEventNames) 771 .append(", resetEventNames=") 772 .append(resetEventNames) 773 .append(", useGlobalPageSize=") 774 .append(useGlobalPageSize) 775 .append(", searchDocumentModel=") 776 .append(searchDocumentModel) 777 .append('}'); 778 return buf.toString(); 779 } 780 781 /* 782 * ----- PageProviderChangedListener ----- 783 */ 784 785 protected void raiseEvent(String eventName, Object... params) { 786 if (Events.exists()) { 787 Events.instance().raiseEvent(eventName, params); 788 } 789 } 790 791 protected void raiseEvent(String eventName) { 792 raiseEvent(eventName, name); 793 } 794 795 @Override 796 public void pageChanged(PageProvider<?> pageProvider) { 797 raiseEvent(CONTENT_VIEW_PAGE_CHANGED_EVENT); 798 } 799 800 @Override 801 public void refreshed(PageProvider<?> pageProvider) { 802 raiseEvent(CONTENT_VIEW_REFRESH_EVENT); 803 } 804 805 @SuppressWarnings("rawtypes") 806 @Override 807 public void resetPageProviderAggregates() { 808 if (pageProvider != null && pageProvider.hasAggregateSupport()) { 809 Map<String, ? extends Aggregate> aggs = pageProvider.getAggregates(); 810 for (Aggregate agg : aggs.values()) { 811 agg.resetSelection(); 812 } 813 } 814 } 815 816 @Override 817 public String getWaitForExecutionSentence() { 818 return waitForExecutionSentence; 819 } 820 821 /** 822 * @since 7.4 823 */ 824 public void setWaitForExecutionSentence(String waitForExecutionSentence) { 825 this.waitForExecutionSentence = waitForExecutionSentence; 826 } 827 828 @Override 829 public boolean isWaitForExecution() { 830 return waitForExecution; 831 } 832 833 /** 834 * @since 7.4 835 */ 836 public void setWaitForExecution(boolean waitForExecution) { 837 this.waitForExecution = waitForExecution; 838 } 839 840 @Override 841 public boolean isExecuted() { 842 return executed; 843 } 844 845 @Override 846 public void setExecuted(boolean executed) { 847 this.executed = executed; 848 } 849 850 /** 851 * @since 8.4 852 */ 853 public void setQuickFilters(List<QuickFilter> quickFilters) { 854 this.quickFilters = quickFilters; 855 } 856 857 /** 858 * @since 8.4 859 */ 860 public List<QuickFilter> getQuickFilters() { 861 return this.quickFilters; 862 } 863}