001/* 002 * (C) Copyright 2014 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl-2.1.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * Thomas Roger 016 */ 017 018package org.nuxeo.search.ui.seam; 019 020import static org.apache.commons.lang.StringUtils.isNotBlank; 021import static org.apache.commons.logging.LogFactory.getLog; 022import static org.jboss.seam.ScopeType.CONVERSATION; 023import static org.jboss.seam.annotations.Install.FRAMEWORK; 024import static org.nuxeo.ecm.webapp.helpers.EventNames.LOCAL_CONFIGURATION_CHANGED; 025import static org.nuxeo.ecm.webapp.helpers.EventNames.USER_ALL_DOCUMENT_TYPES_SELECTION_CHANGED; 026 027import java.io.Serializable; 028import java.io.UnsupportedEncodingException; 029import java.util.ArrayList; 030import java.util.List; 031import java.util.Map; 032 033import javax.faces.application.FacesMessage; 034import javax.faces.component.UIComponent; 035import javax.faces.component.UIViewRoot; 036import javax.faces.context.FacesContext; 037import javax.faces.model.SelectItem; 038import javax.faces.model.SelectItemGroup; 039import javax.faces.validator.ValidatorException; 040 041import org.apache.commons.lang.StringUtils; 042import org.apache.commons.logging.Log; 043import org.jboss.seam.annotations.Begin; 044import org.jboss.seam.annotations.In; 045import org.jboss.seam.annotations.Install; 046import org.jboss.seam.annotations.Name; 047import org.jboss.seam.annotations.Observer; 048import org.jboss.seam.annotations.Scope; 049import org.jboss.seam.annotations.intercept.BypassInterceptors; 050import org.jboss.seam.faces.FacesMessages; 051import org.jboss.seam.international.StatusMessage; 052import org.nuxeo.ecm.core.api.CoreSession; 053import org.nuxeo.ecm.core.api.DocumentModel; 054import org.nuxeo.ecm.core.api.IdRef; 055import org.nuxeo.ecm.core.api.PathRef; 056import org.nuxeo.ecm.core.api.impl.DocumentLocationImpl; 057import org.nuxeo.ecm.platform.contentview.jsf.ContentView; 058import org.nuxeo.ecm.platform.contentview.jsf.ContentViewHeader; 059import org.nuxeo.ecm.platform.contentview.jsf.ContentViewService; 060import org.nuxeo.ecm.platform.contentview.jsf.ContentViewState; 061import org.nuxeo.ecm.platform.contentview.jsf.ContentViewStateImpl; 062import org.nuxeo.ecm.platform.contentview.json.JSONContentViewState; 063import org.nuxeo.ecm.platform.contentview.seam.ContentViewActions; 064import org.nuxeo.ecm.platform.ui.web.api.NavigationContext; 065import org.nuxeo.ecm.platform.ui.web.api.WebActions; 066import org.nuxeo.ecm.platform.ui.web.rest.RestHelper; 067import org.nuxeo.ecm.platform.ui.web.util.BaseURL; 068import org.nuxeo.ecm.platform.ui.web.util.ComponentUtils; 069import org.nuxeo.ecm.platform.url.DocumentViewImpl; 070import org.nuxeo.ecm.platform.url.api.DocumentView; 071import org.nuxeo.ecm.platform.url.api.DocumentViewCodecManager; 072import org.nuxeo.ecm.webapp.action.ActionContextProvider; 073import org.nuxeo.ecm.webapp.documentsLists.DocumentsListsManager; 074import org.nuxeo.ecm.webapp.helpers.EventNames; 075import org.nuxeo.runtime.api.Framework; 076import org.nuxeo.search.ui.SearchUIService; 077 078/** 079 * Seam bean handling Search main tab actions. 080 * 081 * @since 6.0 082 */ 083@Name("searchUIActions") 084@Scope(CONVERSATION) 085@Install(precedence = FRAMEWORK) 086public class SearchUIActions implements Serializable { 087 088 private static final long serialVersionUID = 1L; 089 090 private static final Log log = getLog(SearchUIActions.class); 091 092 public static final String SAVED_SEARCHES_LABEL = "label.saved.searches"; 093 094 public static final String SHARED_SEARCHES_LABEL = "label.shared.searches"; 095 096 public static final String SEARCH_FILTERS_LABEL = "label.search.filters"; 097 098 public static final String SEARCH_SAVED_LABEL = "label.search.saved"; 099 100 public static final String MAIN_TABS_SEARCH = "MAIN_TABS:search"; 101 102 public static final String SEARCH_VIEW_ID = "/search/search.xhtml"; 103 104 public static final String SEARCH_CODEC = "docpathsearch"; 105 106 public static final String SIMPLE_SEARCH_CONTENT_VIEW_NAME = "simple_search"; 107 108 public static final String NXQL_SEARCH_CONTENT_VIEW_NAME = "nxql_search"; 109 110 public static final String DEFAULT_NXQL_QUERY = "SELECT * FROM Document" 111 + " WHERE ecm:mixinType != 'HiddenInNavigation'" + " AND ecm:isProxy = 0 AND ecm:isCheckedInVersion = 0" 112 + " AND ecm:currentLifeCycleState != 'deleted'"; 113 114 public static final String CONTENT_VIEW_NAME_PARAMETER = "contentViewName"; 115 116 public static final String CURRENT_PAGE_PARAMETER = "currentPage"; 117 118 public static final String PAGE_SIZE_PARAMETER = "pageSize"; 119 120 public static final String CONTENT_VIEW_STATE_PARAMETER = "state"; 121 122 public static final String SEARCH_TERM_PARAMETER = "searchTerm"; 123 124 @In(create = true) 125 protected transient NavigationContext navigationContext; 126 127 @In(create = true, required = false) 128 protected transient CoreSession documentManager; 129 130 @In(create = true, required = false) 131 protected transient ActionContextProvider actionContextProvider; 132 133 @In(create = true) 134 protected transient WebActions webActions; 135 136 @In(create = true) 137 protected RestHelper restHelper; 138 139 @In(create = true) 140 protected ContentViewActions contentViewActions; 141 142 @In(create = true) 143 protected ContentViewService contentViewService; 144 145 @In(create = true) 146 protected DocumentsListsManager documentsListsManager; 147 148 @In(create = true, required = false) 149 protected FacesMessages facesMessages; 150 151 @In(create = true) 152 protected Map<String, String> messages; 153 154 protected String simpleSearchKeywords = ""; 155 156 protected String nxqlQuery = DEFAULT_NXQL_QUERY; 157 158 protected List<ContentViewHeader> contentViewHeaders; 159 160 protected String currentContentViewName; 161 162 protected String currentSelectedSavedSearchId; 163 164 protected String currentPage; 165 166 protected String pageSize; 167 168 protected String searchTerm; 169 170 protected String savedSearchTitle; 171 172 public String getSearchMainTab() { 173 return MAIN_TABS_SEARCH; 174 } 175 176 public void setSearchMainTab(String tabs) { 177 webActions.setCurrentTabIds(!StringUtils.isBlank(tabs) ? tabs : MAIN_TABS_SEARCH); 178 } 179 180 public String getSearchViewTitle() { 181 if (currentSelectedSavedSearchId != null) { 182 DocumentModel savedSearch = documentManager.getDocument(new IdRef(currentSelectedSavedSearchId)); 183 return savedSearch.getTitle(); 184 } else if (currentContentViewName != null) { 185 ContentView cv = contentViewActions.getContentView(currentContentViewName); 186 String title = cv.getTranslateTitle() ? messages.get(cv.getTitle()) : cv.getTitle(); 187 return isNotBlank(title) ? title : currentContentViewName; 188 } 189 return null; 190 } 191 192 /** 193 * Returns true if the user is viewing SEARCH. 194 */ 195 public boolean isOnSearchView() { 196 if (FacesContext.getCurrentInstance() == null) { 197 return false; 198 } 199 200 UIViewRoot viewRoot = FacesContext.getCurrentInstance().getViewRoot(); 201 if (viewRoot != null) { 202 String viewId = viewRoot.getViewId(); 203 // FIXME find a better way to update the current document only 204 // if we are on SEARCH 205 if (SEARCH_VIEW_ID.equals(viewId)) { 206 return true; 207 } 208 } 209 return false; 210 } 211 212 public String getJSONContentViewState() throws UnsupportedEncodingException { 213 ContentView contentView = contentViewActions.getContentView(currentContentViewName); 214 ContentViewService contentViewService = Framework.getService(ContentViewService.class); 215 ContentViewState state = contentViewService.saveContentView(contentView); 216 return JSONContentViewState.toJSON(state, true); 217 } 218 219 public String getCurrentContentViewName() { 220 if (currentContentViewName == null) { 221 List<ContentViewHeader> contentViewHeaders = getContentViewHeaders(); 222 if (!contentViewHeaders.isEmpty()) { 223 currentContentViewName = contentViewHeaders.get(0).getName(); 224 } 225 } 226 return currentContentViewName; 227 } 228 229 public void setCurrentContentViewName(String contentViewName) { 230 this.currentContentViewName = contentViewName; 231 } 232 233 public String getCurrentSelectedSavedSearchId() { 234 return currentSelectedSavedSearchId != null ? currentSelectedSavedSearchId : currentContentViewName; 235 } 236 237 public void setCurrentSelectedSavedSearchId(String selectedSavedSearchId) throws UnsupportedEncodingException { 238 resetCurrentContentViewWorkingList(); 239 240 for (ContentViewHeader contentViewHeader : contentViewHeaders) { 241 if (contentViewHeader.getName().equals(selectedSavedSearchId)) { 242 contentViewActions.reset(currentContentViewName); 243 currentContentViewName = selectedSavedSearchId; 244 currentSelectedSavedSearchId = null; 245 return; 246 } 247 } 248 DocumentModel savedSearch = documentManager.getDocument(new IdRef(selectedSavedSearchId)); 249 loadSavedSearch(savedSearch); 250 } 251 252 protected void resetCurrentContentViewWorkingList() { 253 if (currentContentViewName != null) { 254 ContentView contentView = contentViewActions.getContentView(currentContentViewName); 255 documentsListsManager.resetWorkingList(contentView.getSelectionListName()); 256 } 257 } 258 259 public void loadSavedSearch(DocumentModel searchDocument) throws UnsupportedEncodingException { 260 SearchUIService searchUIService = Framework.getService(SearchUIService.class); 261 ContentViewState contentViewState = searchUIService.loadSearch(searchDocument); 262 if (contentViewState != null) { 263 ContentView contentView = contentViewActions.restoreContentView(contentViewState); 264 currentContentViewName = contentView.getName(); 265 } 266 currentSelectedSavedSearchId = searchDocument.getId(); 267 } 268 269 public List<ContentViewHeader> getContentViewHeaders() { 270 if (contentViewHeaders == null) { 271 SearchUIService searchUIService = Framework.getService(SearchUIService.class); 272 contentViewHeaders = searchUIService.getContentViewHeaders(actionContextProvider.createActionContext(), 273 navigationContext.getCurrentDocument()); 274 } 275 return contentViewHeaders; 276 } 277 278 public void clearSearch() { 279 if (currentContentViewName != null) { 280 contentViewActions.reset(currentContentViewName); 281 resetCurrentContentViewWorkingList(); 282 } 283 } 284 285 public void refreshAndRewind() { 286 String contentViewName = getCurrentContentViewName(); 287 if (contentViewName != null) { 288 contentViewActions.refreshAndRewind(contentViewName); 289 resetCurrentContentViewWorkingList(); 290 } 291 } 292 293 public void refreshAndRewindAndResetAggregates() { 294 contentViewActions.resetAggregates(getCurrentContentViewName()); 295 refreshAndRewind(); 296 } 297 298 /* 299 * ----- Load / Save searches ----- 300 */ 301 302 public List<SelectItem> getAllSavedSearchesSelectItems() { 303 List<SelectItem> items = new ArrayList<>(); 304 305 // Add flagged content views 306 SelectItemGroup flaggedGroup = new SelectItemGroup(messages.get(SEARCH_FILTERS_LABEL)); 307 List<ContentViewHeader> flaggedSavedSearches = getContentViewHeaders(); 308 List<SelectItem> flaggedSavedSearchesItems = convertCVToSelectItems(flaggedSavedSearches); 309 flaggedGroup.setSelectItems(flaggedSavedSearchesItems.toArray(new SelectItem[flaggedSavedSearchesItems.size()])); 310 items.add(flaggedGroup); 311 312 // Add saved searches 313 List<DocumentModel> userSavedSearches = getSavedSearches(); 314 if (!userSavedSearches.isEmpty()) { 315 SelectItemGroup userGroup = new SelectItemGroup(messages.get(SAVED_SEARCHES_LABEL)); 316 317 List<SelectItem> userSavedSearchesItems = convertToSelectItems(userSavedSearches); 318 userGroup.setSelectItems(userSavedSearchesItems.toArray(new SelectItem[userSavedSearchesItems.size()])); 319 items.add(userGroup); 320 } 321 322 // Add shared searches 323 List<DocumentModel> otherUsersSavedFacetedSearches = getSharedSearches(); 324 if (!otherUsersSavedFacetedSearches.isEmpty()) { 325 List<SelectItem> otherUsersSavedSearchesItems = convertToSelectItems(otherUsersSavedFacetedSearches); 326 SelectItemGroup allGroup = new SelectItemGroup(messages.get(SHARED_SEARCHES_LABEL)); 327 allGroup.setSelectItems(otherUsersSavedSearchesItems.toArray(new SelectItem[otherUsersSavedSearchesItems.size()])); 328 items.add(allGroup); 329 } 330 return items; 331 } 332 333 protected List<DocumentModel> getSavedSearches() { 334 SearchUIService searchUIService = Framework.getService(SearchUIService.class); 335 return searchUIService.getCurrentUserSavedSearches(documentManager); 336 } 337 338 protected List<DocumentModel> getSharedSearches() { 339 SearchUIService searchUIService = Framework.getService(SearchUIService.class); 340 return searchUIService.getSharedSavedSearches(documentManager); 341 } 342 343 protected List<SelectItem> convertToSelectItems(List<DocumentModel> docs) { 344 List<SelectItem> items = new ArrayList<>(); 345 for (DocumentModel doc : docs) { 346 items.add(new SelectItem(doc.getId(), doc.getTitle(), "")); 347 } 348 return items; 349 } 350 351 protected List<SelectItem> convertCVToSelectItems(List<ContentViewHeader> contentViewHeaders) { 352 List<SelectItem> items = new ArrayList<>(); 353 for (ContentViewHeader contentViewHeader : contentViewHeaders) { 354 items.add(new SelectItem(contentViewHeader.getName(), messages.get(contentViewHeader.getTitle()), "")); 355 } 356 return items; 357 } 358 359 public String getSavedSearchTitle() { 360 return savedSearchTitle; 361 } 362 363 public void setSavedSearchTitle(String savedSearchTitle) { 364 this.savedSearchTitle = savedSearchTitle; 365 } 366 367 public String saveSearch() { 368 ContentView contentView = contentViewActions.getContentView(getCurrentContentViewName()); 369 if (contentView != null) { 370 ContentViewState state = contentViewService.saveContentView(contentView); 371 SearchUIService searchUIService = Framework.getService(SearchUIService.class); 372 DocumentModel savedSearch = searchUIService.saveSearch(documentManager, state, savedSearchTitle); 373 currentSelectedSavedSearchId = savedSearch.getId(); 374 375 savedSearchTitle = null; 376 facesMessages.add(StatusMessage.Severity.INFO, messages.get(SEARCH_SAVED_LABEL)); 377 378 // Events.instance().raiseEvent(EventNames.DOCUMENT_CHILDREN_CHANGED, 379 // uws); 380 381 } 382 return null; 383 } 384 385 /** 386 * Retsurns true if current search can be saved. 387 * <p> 388 * Returns false if current content view is waiting for a first execution. 389 * 390 * @since 7.4 391 */ 392 public boolean getCanSaveSearch() { 393 ContentView contentView = contentViewActions.getContentView(getCurrentContentViewName()); 394 if (contentView != null) { 395 boolean res = !contentView.isWaitForExecution() || contentView.isExecuted(); 396 return res; 397 } 398 return false; 399 } 400 401 public void cancelSaveSearch() { 402 savedSearchTitle = null; 403 } 404 405 /* 406 * ----- Permanent links ----- 407 */ 408 409 public void setState(String state) throws UnsupportedEncodingException { 410 if (isNotBlank(state)) { 411 Long finalPageSize = null; 412 if (!StringUtils.isBlank(pageSize)) { 413 try { 414 finalPageSize = Long.valueOf(pageSize); 415 } catch (NumberFormatException e) { 416 log.warn(String.format("Unable to parse '%s' parameter with value '%s'", PAGE_SIZE_PARAMETER, 417 pageSize)); 418 } 419 } 420 421 Long finalCurrentPage = null; 422 if (!StringUtils.isBlank(currentPage)) { 423 try { 424 finalCurrentPage = Long.valueOf(currentPage); 425 } catch (NumberFormatException e) { 426 log.warn(String.format("Unable to parse '%s' parameter with value '%s'", CURRENT_PAGE_PARAMETER, 427 currentPage)); 428 } 429 } 430 431 String cvName = getCurrentContentViewName(); 432 List<ContentViewHeader> contentViewHeaders = getContentViewHeaders(); 433 if (cvName != null && contentViewHeaders != null) { 434 boolean canRestore = false; 435 for (ContentViewHeader contentViewHeader : getContentViewHeaders()) { 436 if (cvName.equals(contentViewHeader.getName())) { 437 canRestore = true; 438 } 439 } 440 441 if (canRestore) { 442 contentViewActions.restoreContentView(getCurrentContentViewName(), finalCurrentPage, finalPageSize, 443 null, state); 444 } else { 445 invalidateContentViewsName(); 446 } 447 } 448 } 449 } 450 451 public String getCurrentPage() { 452 return currentPage; 453 } 454 455 public void setCurrentPage(String currentPage) { 456 this.currentPage = currentPage; 457 } 458 459 public String getPageSize() { 460 return pageSize; 461 } 462 463 public void setPageSize(String pageSize) { 464 this.pageSize = pageSize; 465 } 466 467 public void setSearchTerm(String searchTerm) throws UnsupportedEncodingException { 468 // If the search term is not defined, we don't do the logic 469 if (!StringUtils.isEmpty(searchTerm)) { 470 // By default, the "simple_search" content view is used 471 currentContentViewName = SIMPLE_SEARCH_CONTENT_VIEW_NAME; 472 // Create a ContentViewState 473 ContentView cv = contentViewService.getContentView(SIMPLE_SEARCH_CONTENT_VIEW_NAME); 474 DocumentModel searchDocumentModel = cv.getSearchDocumentModel(); 475 // set the search term 476 searchDocumentModel.setPropertyValue("default_search:ecm_fulltext", searchTerm); 477 ContentViewState state = new ContentViewStateImpl(); 478 state.setSearchDocumentModel(searchDocumentModel); 479 state.setContentViewName(getCurrentContentViewName()); 480 ContentView ccv = contentViewActions.restoreContentView(state); 481 ccv.setExecuted(true); 482 } 483 } 484 485 /** 486 * Compute a permanent link for the current search. 487 */ 488 public String getSearchPermanentLinkUrl() throws UnsupportedEncodingException { 489 // do not try to compute an URL if we don't have any CoreSession 490 if (documentManager == null) { 491 return null; 492 } 493 494 return generateSearchUrl(true); 495 } 496 497 /** 498 * @return the URL of the search tab with the search term defined. 499 */ 500 public String getSearchTabUrl(String searchTerm) throws UnsupportedEncodingException { 501 // do not try to compute an URL if we don't have any CoreSession 502 if (documentManager == null) { 503 return null; 504 } 505 // Set the value of the searched term 506 this.searchTerm = searchTerm; 507 508 return generateSearchUrl(false); 509 } 510 511 /** 512 * Create the url to access the Search tab. 513 * 514 * @param withState If set to true, the state is added in the parameters. 515 */ 516 protected String generateSearchUrl(boolean withState) throws UnsupportedEncodingException { 517 String currentContentViewName = getCurrentContentViewName(); 518 DocumentModel currentDocument = navigationContext.getCurrentDocument(); 519 DocumentView docView = computeDocumentView(currentDocument); 520 docView.setViewId("search"); 521 docView.addParameter(CONTENT_VIEW_NAME_PARAMETER, currentContentViewName); 522 // Add the state if needed 523 if (withState) { 524 docView.addParameter(CONTENT_VIEW_STATE_PARAMETER, getJSONContentViewState()); 525 } 526 527 DocumentViewCodecManager documentViewCodecManager = Framework.getService(DocumentViewCodecManager.class); 528 String url = documentViewCodecManager.getUrlFromDocumentView(SEARCH_CODEC, docView, true, BaseURL.getBaseURL()); 529 530 return RestHelper.addCurrentConversationParameters(url); 531 } 532 533 protected DocumentView computeDocumentView(DocumentModel doc) { 534 return new DocumentViewImpl(new DocumentLocationImpl(documentManager.getRepositoryName(), 535 doc != null ? new PathRef(doc.getPathAsString()) : null)); 536 } 537 538 /* 539 * ----- Simple Search ----- 540 */ 541 public String getSimpleSearchKeywords() { 542 return simpleSearchKeywords; 543 } 544 545 public void setSimpleSearchKeywords(String simpleSearchKeywords) { 546 this.simpleSearchKeywords = simpleSearchKeywords; 547 } 548 549 public void validateSimpleSearchKeywords(FacesContext context, UIComponent component, Object value) { 550 if (!(value instanceof String) || StringUtils.isEmpty(((String) value).trim())) { 551 FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, ComponentUtils.translate(context, 552 "feedback.search.noKeywords"), null); 553 // also add global message 554 context.addMessage(null, message); 555 throw new ValidatorException(message); 556 } 557 String[] keywords = ((String) value).trim().split(" "); 558 for (String keyword : keywords) { 559 if (keyword.startsWith("*")) { 560 // Can't begin search with * character 561 FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, ComponentUtils.translate(context, 562 "feedback.search.star"), null); 563 // also add global message 564 context.addMessage(null, message); 565 throw new ValidatorException(message); 566 } 567 } 568 } 569 570 public String doSimpleSearch() { 571 setSearchMainTab(null); 572 currentContentViewName = SIMPLE_SEARCH_CONTENT_VIEW_NAME; 573 ContentView contentView = contentViewActions.getContentView(SIMPLE_SEARCH_CONTENT_VIEW_NAME); 574 DocumentModel searchDoc = contentView.getSearchDocumentModel(); 575 searchDoc.setPropertyValue("defaults:ecm_fulltext", simpleSearchKeywords); 576 refreshAndRewind(); 577 return "search"; 578 } 579 580 /* 581 * ----- NXQL Search ----- 582 */ 583 public String getNxqlQuery() { 584 return nxqlQuery; 585 } 586 587 public void setNxqlQuery(String nxqlQuery) { 588 this.nxqlQuery = nxqlQuery; 589 } 590 591 public boolean isNxqlSearchSelected() { 592 return NXQL_SEARCH_CONTENT_VIEW_NAME.equals(currentContentViewName); 593 } 594 595 @Begin(id = "#{conversationIdGenerator.currentOrNewMainConversationId}", join = true) 596 public String loadPermanentLink(DocumentView docView) { 597 restHelper.initContextFromRestRequest(docView); 598 return "search"; 599 } 600 601 @Observer(value = LOCAL_CONFIGURATION_CHANGED) 602 public void invalidateContentViewsName() { 603 clearSearch(); 604 contentViewHeaders = null; 605 currentContentViewName = null; 606 } 607 608 @Observer(value = USER_ALL_DOCUMENT_TYPES_SELECTION_CHANGED) 609 public void invalidateContentViewsNameIfChanged() { 610 List<ContentViewHeader> temp = new ArrayList<>( 611 Framework.getLocalService(SearchUIService.class).getContentViewHeaders( 612 actionContextProvider.createActionContext(), navigationContext.getCurrentDocument())); 613 if (temp != null) { 614 if (!temp.equals(contentViewHeaders)) { 615 invalidateContentViewsName(); 616 } 617 if (!temp.isEmpty()) { 618 String s = temp.get(0).getName(); 619 if (s != null && !s.equals(currentContentViewName)) { 620 invalidateContentViewsName(); 621 } 622 } 623 } 624 } 625 626 /** 627 * Reset attributes. 628 */ 629 @Observer(value = { EventNames.FLUSH_EVENT }, create = false) 630 @BypassInterceptors 631 public void resetOnFlush() { 632 contentViewHeaders = null; 633 currentSelectedSavedSearchId = null; 634 currentContentViewName = null; 635 nxqlQuery = DEFAULT_NXQL_QUERY; 636 simpleSearchKeywords = ""; 637 } 638 639 public String getSearchTermParameter() { 640 return SEARCH_TERM_PARAMETER; 641 } 642}