/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package com.liferay.portal.search.web.internal.portlet.shared.search;
import com.liferay.portal.kernel.dao.search.DisplayTerms;
import com.liferay.portal.kernel.dao.search.SearchContainer;
import com.liferay.portal.kernel.model.Layout;
import com.liferay.portal.kernel.model.LayoutTypePortlet;
import com.liferay.portal.kernel.model.Portlet;
import com.liferay.portal.kernel.search.Document;
import com.liferay.portal.kernel.search.QueryConfig;
import com.liferay.portal.kernel.search.SearchContext;
import com.liferay.portal.kernel.search.facet.faceted.searcher.FacetedSearcherManager;
import com.liferay.portal.kernel.service.PortletPreferencesLocalService;
import com.liferay.portal.kernel.theme.ThemeDisplay;
import com.liferay.portal.kernel.util.PortletKeys;
import com.liferay.portal.search.web.internal.display.context.PortletRequestThemeDisplaySupplier;
import com.liferay.portal.search.web.internal.display.context.ThemeDisplaySupplier;
import com.liferay.portal.search.web.internal.portlet.shared.task.PortletSharedRequestHelper;
import com.liferay.portal.search.web.internal.search.request.SearchContainerBuilder;
import com.liferay.portal.search.web.internal.search.request.SearchContextBuilder;
import com.liferay.portal.search.web.internal.search.request.SearchRequestImpl;
import com.liferay.portal.search.web.portlet.shared.search.PortletSharedSearchContributor;
import com.liferay.portal.search.web.portlet.shared.search.PortletSharedSearchRequest;
import com.liferay.portal.search.web.portlet.shared.search.PortletSharedSearchResponse;
import com.liferay.portal.search.web.portlet.shared.task.PortletSharedTaskExecutor;
import com.liferay.portal.search.web.search.request.SearchRequest;
import com.liferay.portal.search.web.search.request.SearchResponse;
import com.liferay.portal.search.web.search.request.SearchSettings;
import com.liferay.portal.search.web.search.request.SearchSettingsContributor;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Stream;
import javax.portlet.PortletPreferences;
import javax.portlet.PortletRequest;
import javax.portlet.PortletURL;
import javax.portlet.RenderRequest;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.osgi.service.component.annotations.ReferencePolicyOption;
/**
* @author André de Oliveira
*/
@Component(service = PortletSharedSearchRequest.class)
public class PortletSharedSearchRequestImpl
implements PortletSharedSearchRequest {
@Override
public PortletSharedSearchResponse search(RenderRequest renderRequest) {
PortletSharedSearchResponse portletSharedSearchResponse =
portletSharedTaskExecutor.executeOnlyOnce(
() -> doSearch(renderRequest),
PortletSharedSearchResponse.class.getSimpleName(),
renderRequest);
return portletSharedSearchResponse;
}
@Reference(
cardinality = ReferenceCardinality.MULTIPLE,
policy = ReferencePolicy.DYNAMIC,
policyOption = ReferencePolicyOption.GREEDY,
unbind = "removePortletSharedSearchContributor"
)
protected void addPortletSharedSearchContributor(
PortletSharedSearchContributor portletSharedSearchContributor) {
Class<?> clazz = portletSharedSearchContributor.getClass();
String className = clazz.getName();
_portletSharedSearchContributors.put(
className, portletSharedSearchContributor);
}
protected SearchContainer<Document> buildSearchContainer(
SearchSettings searchSettings, RenderRequest renderRequest) {
Optional<String> paginationStartParameterNameOptional =
searchSettings.getPaginationStartParameterName();
Optional<Integer> paginationStartOptional =
searchSettings.getPaginationStart();
Optional<Integer> paginationDeltaOptional =
searchSettings.getPaginationDelta();
PortletRequest portletRequest = renderRequest;
DisplayTerms displayTerms = null;
DisplayTerms searchTerms = null;
String curParam = paginationStartParameterNameOptional.orElse(
SearchContainer.DEFAULT_CUR_PARAM);
int cur = paginationStartOptional.orElse(0);
int delta = paginationDeltaOptional.orElse(
SearchContainer.DEFAULT_DELTA);
PortletURL portletURL = new NullPortletURL();
List<String> headerNames = null;
String emptyResultsMessage = null;
String cssClass = null;
SearchContainer<Document> searchContainer = new SearchContainer<>(
portletRequest, displayTerms, searchTerms, curParam, cur, delta,
portletURL, headerNames, emptyResultsMessage, cssClass);
return searchContainer;
}
protected SearchContext buildSearchContext(ThemeDisplay themeDisplay) {
SearchContext searchContext = new SearchContext();
searchContext.setCompanyId(themeDisplay.getCompanyId());
searchContext.setLayout(themeDisplay.getLayout());
searchContext.setLocale(themeDisplay.getLocale());
searchContext.setTimeZone(themeDisplay.getTimeZone());
searchContext.setUserId(themeDisplay.getUserId());
QueryConfig queryConfig = searchContext.getQueryConfig();
queryConfig.setLocale(themeDisplay.getLocale());
return searchContext;
}
protected void contributeSearchSettings(
SearchRequest searchRequest, Stream<Portlet> portletsStream,
ThemeDisplay themeDisplay, RenderRequest renderRequest) {
Stream<Optional<SearchSettingsContributor>>
searchSettingsContributorOptionalsStream = portletsStream.map(
portlet -> getSearchSettingsContributor(
portlet, themeDisplay, renderRequest));
searchSettingsContributorOptionalsStream.forEach(
searchSettingsContributorOptional ->
searchSettingsContributorOptional.ifPresent(
searchRequest::addSearchSettingsContributor));
}
protected PortletSharedSearchResponse doSearch(
RenderRequest renderRequest) {
ThemeDisplay themeDisplay = getThemeDisplay(renderRequest);
SearchContextBuilder searchContextBuilder =
() -> buildSearchContext(themeDisplay);
SearchContainerBuilder searchContainerBuilder =
searchSettings -> buildSearchContainer(
searchSettings, renderRequest);
SearchRequest searchRequest = new SearchRequestImpl(
searchContextBuilder, searchContainerBuilder,
facetedSearcherManager);
Stream<Portlet> portletsStream = getExplicitlyAddedPortlets(
themeDisplay);
contributeSearchSettings(
searchRequest, portletsStream, themeDisplay, renderRequest);
SearchResponse searchResponse = searchRequest.search();
return new PortletSharedSearchResponseImpl(
searchResponse, portletSharedRequestHelper);
}
protected Stream<Portlet> getExplicitlyAddedPortlets(
ThemeDisplay themeDisplay) {
Layout layout = themeDisplay.getLayout();
LayoutTypePortlet layoutTypePortlet =
(LayoutTypePortlet)layout.getLayoutType();
List<Portlet> portlets = layoutTypePortlet.getExplicitlyAddedPortlets();
return portlets.stream();
}
protected Optional<PortletPreferences> getPortletPreferences(
ThemeDisplay themeDisplay, String portletId) {
PortletPreferences portletPreferences =
portletPreferencesLocalService.fetchPreferences(
themeDisplay.getCompanyId(), PortletKeys.PREFS_OWNER_ID_DEFAULT,
PortletKeys.PREFS_OWNER_TYPE_LAYOUT, themeDisplay.getPlid(),
portletId);
return Optional.ofNullable(portletPreferences);
}
protected Optional<PortletSharedSearchContributor>
getPortletSharedSearchContributor(String className) {
return Optional.ofNullable(
_portletSharedSearchContributors.get(className));
}
protected Optional<SearchSettingsContributor> getSearchSettingsContributor(
Portlet portlet, ThemeDisplay themeDisplay,
RenderRequest renderRequest) {
Optional<PortletSharedSearchContributor>
portletSharedSearchContributorOptional =
getPortletSharedSearchContributor(portlet.getPortletClass());
Optional<SearchSettingsContributor> searchSettingsContributorOptional =
portletSharedSearchContributorOptional.map(
portletSharedSearchContributor -> getSearchSettingsContributor(
portletSharedSearchContributor, portlet.getPortletId(),
themeDisplay, renderRequest));
return searchSettingsContributorOptional;
}
protected SearchSettingsContributor getSearchSettingsContributor(
PortletSharedSearchContributor portletSharedSearchContributor,
String portletId, ThemeDisplay themeDisplay,
RenderRequest renderRequest) {
Optional<PortletPreferences> portletPreferencesOptional =
getPortletPreferences(themeDisplay, portletId);
return searchSettings -> portletSharedSearchContributor.contribute(
new PortletSharedSearchSettingsImpl(
searchSettings, portletPreferencesOptional,
portletSharedRequestHelper, renderRequest));
}
protected ThemeDisplay getThemeDisplay(RenderRequest renderRequest) {
ThemeDisplaySupplier themeDisplaySupplier =
new PortletRequestThemeDisplaySupplier(renderRequest);
return themeDisplaySupplier.getThemeDisplay();
}
protected void removePortletSharedSearchContributor(
PortletSharedSearchContributor portletSharedSearchContributor) {
Class<?> clazz = portletSharedSearchContributor.getClass();
String className = clazz.getName();
_portletSharedSearchContributors.remove(className);
}
@Reference
protected FacetedSearcherManager facetedSearcherManager;
@Reference
protected PortletPreferencesLocalService portletPreferencesLocalService;
@Reference
protected PortletSharedRequestHelper portletSharedRequestHelper;
@Reference
protected PortletSharedTaskExecutor portletSharedTaskExecutor;
private final Map<String, PortletSharedSearchContributor>
_portletSharedSearchContributors = new HashMap<>();
}