/*
* (C) Copyright 2014 Nuxeo SA (http://nuxeo.com/) and others.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Contributors:
* Thomas Roger
* Nelson Silva
*/
package org.nuxeo.search.ui;
import static org.nuxeo.search.ui.localconfiguration.Constants.SEARCH_CONFIGURATION_FACET;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nuxeo.ecm.core.api.CoreSession;
import org.nuxeo.ecm.core.api.DocumentModel;
import org.nuxeo.ecm.core.api.DocumentModelFactory;
import org.nuxeo.ecm.core.api.DocumentRef;
import org.nuxeo.ecm.core.api.SortInfo;
import org.nuxeo.ecm.core.api.localconfiguration.LocalConfigurationService;
import org.nuxeo.ecm.core.api.pathsegment.PathSegmentService;
import org.nuxeo.ecm.platform.actions.Action;
import org.nuxeo.ecm.platform.actions.ActionContext;
import org.nuxeo.ecm.platform.actions.ejb.ActionManager;
import org.nuxeo.ecm.platform.contentview.jsf.ContentViewHeader;
import org.nuxeo.ecm.platform.contentview.jsf.ContentViewService;
import org.nuxeo.ecm.platform.contentview.jsf.ContentViewState;
import org.nuxeo.ecm.platform.contentview.jsf.ContentViewStateImpl;
import org.nuxeo.ecm.platform.query.api.PageProvider;
import org.nuxeo.ecm.platform.query.api.PageProviderService;
import org.nuxeo.ecm.platform.userworkspace.api.UserWorkspaceService;
import org.nuxeo.runtime.api.Framework;
import org.nuxeo.search.ui.localconfiguration.SearchConfiguration;
/**
* @since 6.0
*/
public class SearchUIServiceImpl implements SearchUIService {
private static Log log = LogFactory.getLog(SearchUIServiceImpl.class);
public static final String SEARCH_CONTENT_VIEWS_CATEGORY = "SEARCH_CONTENT_VIEWS";
public static final String CONTENT_VIEW_NAME_PROPERTY = "contentViewName";
public static final String SAVED_SEARCHES_PROVIDER_NAME = "SAVED_SEARCHES";
public static final String SHARED_SEARCHES_PROVIDER_NAME = "SHARED_SAVED_SEARCHES";
public static final String CONTENT_VIEW_DISPLAY_FACET = "ContentViewDisplay";
@Override
public List<ContentViewHeader> getContentViewHeaders(ActionContext actionContext) {
return getContentViewHeaders(actionContext, null);
}
@Override
public List<ContentViewHeader> getContentViewHeaders(ActionContext actionContext, DocumentModel doc) {
ActionManager actionService = Framework.getService(ActionManager.class);
List<Action> actions = actionService.getActions(SEARCH_CONTENT_VIEWS_CATEGORY, actionContext);
List<String> contentViewNames = new ArrayList<>();
for (Action action : actions) {
String contentViewName = (String) action.getProperties().get(CONTENT_VIEW_NAME_PROPERTY);
if (contentViewName != null) {
contentViewNames.add(contentViewName);
}
}
contentViewNames = filterContentViewNames(contentViewNames, doc);
ContentViewService contentViewService = Framework.getService(ContentViewService.class);
List<ContentViewHeader> contentViewHeaders = new ArrayList<>();
for (String contentViewName : contentViewNames) {
ContentViewHeader contentViewHeader = contentViewService.getContentViewHeader(contentViewName);
if (contentViewHeader != null) {
contentViewHeaders.add(contentViewHeader);
}
}
return contentViewHeaders;
}
/**
* Returns the filtered content view names based on the local configuration if any.
*/
protected List<String> filterContentViewNames(List<String> contentViewNames, DocumentModel currentDoc) {
SearchConfiguration searchConfiguration = getSearchConfiguration(currentDoc);
return searchConfiguration == null ? contentViewNames
: searchConfiguration.filterAllowedContentViewNames(contentViewNames);
}
protected SearchConfiguration getSearchConfiguration(DocumentModel currentDoc) {
LocalConfigurationService localConfigurationService = Framework.getService(LocalConfigurationService.class);
return localConfigurationService.getConfiguration(SearchConfiguration.class, SEARCH_CONFIGURATION_FACET,
currentDoc);
}
public DocumentModel saveSearch(CoreSession session, ContentViewState searchContentViewState, String title) {
UserWorkspaceService userWorkspaceService = Framework.getService(UserWorkspaceService.class);
DocumentModel uws = userWorkspaceService.getCurrentUserPersonalWorkspace(session, null);
DocumentModel searchDoc = searchContentViewState.getSearchDocumentModel();
DocumentRef ref = searchDoc.getRef();
if (ref != null && session.exists(ref)) {
// already a saved search, init a new doc
DocumentModel bareDoc = DocumentModelFactory.createDocumentModel(searchDoc.getType());
bareDoc.copyContent(searchDoc);
searchDoc = bareDoc;
}
searchDoc.setPropertyValue("dc:title", title);
if (searchDoc.hasFacet(CONTENT_VIEW_DISPLAY_FACET)) {
searchDoc.setPropertyValue("cvd:contentViewName", searchContentViewState.getContentViewName());
searchDoc.setPropertyValue("saved:providerName", searchContentViewState.getPageProviderName());
searchDoc.setPropertyValue("saved:pageSize", searchContentViewState.getPageSize());
searchContentViewState.getPageSize();
List<SortInfo> sortInfos = searchContentViewState.getSortInfos();
if (sortInfos != null) {
ArrayList<Map<String, Serializable>> list = new ArrayList<>();
String sortBy = "", sortOrder = "";
for (SortInfo sortInfo : sortInfos) {
if (!sortBy.isEmpty()) {
sortBy += ",";
sortOrder += ",";
}
sortBy += sortInfo.getSortColumn();
sortOrder += sortInfo.getSortAscending() ? "ASC" : "DESC";
list.add(SortInfo.asMap(sortInfo));
}
searchDoc.setPropertyValue("cvd:sortInfos", list);
searchDoc.setPropertyValue("saved:sortBy", sortBy);
searchDoc.setPropertyValue("saved:sortOrder", sortOrder);
}
searchDoc.setPropertyValue("cvd:selectedLayoutColumns",
(Serializable) searchContentViewState.getResultColumns());
} else {
log.warn(String.format("Search document type %s is missing %s facet", searchDoc.getType(),
CONTENT_VIEW_DISPLAY_FACET));
}
PathSegmentService pathService = Framework.getService(PathSegmentService.class);
searchDoc.setPathInfo(uws.getPathAsString(), pathService.generatePathSegment(searchDoc));
searchDoc = session.createDocument(searchDoc);
session.save();
return searchDoc;
}
public List<DocumentModel> getCurrentUserSavedSearches(CoreSession session) {
return getDocuments(SAVED_SEARCHES_PROVIDER_NAME, session, session.getPrincipal().getName());
}
@SuppressWarnings("unchecked")
protected List<DocumentModel> getDocuments(String pageProviderName, CoreSession session, Object... parameters) {
PageProviderService pageProviderService = Framework.getService(PageProviderService.class);
Map<String, Serializable> properties = new HashMap<String, Serializable>();
properties.put("coreSession", (Serializable) session);
return ((PageProvider<DocumentModel>) pageProviderService.getPageProvider(pageProviderName, null, null, null,
properties, parameters)).getCurrentPage();
}
public List<DocumentModel> getSharedSavedSearches(CoreSession session) {
return getDocuments(SHARED_SEARCHES_PROVIDER_NAME, session, session.getPrincipal().getName());
}
@Override
@SuppressWarnings("unchecked")
public ContentViewState loadSearch(DocumentModel savedSearch) {
if (!savedSearch.hasFacet(CONTENT_VIEW_DISPLAY_FACET)) {
log.warn(String.format("Search document type %s is missing %s facet", savedSearch.getType(),
CONTENT_VIEW_DISPLAY_FACET));
return null;
}
ContentViewState state = new ContentViewStateImpl();
state.setContentViewName((String) savedSearch.getPropertyValue("cvd:contentViewName"));
state.setSearchDocumentModel(savedSearch);
state.setSortInfos(getSortInfos(savedSearch));
state.setResultColumns((List<String>) savedSearch.getPropertyValue("cvd:selectedLayoutColumns"));
return state;
}
@SuppressWarnings("unchecked")
List<SortInfo> getSortInfos(DocumentModel savedSearch) {
List<Map<String, Serializable>> list = (List<Map<String, Serializable>>) savedSearch.getPropertyValue(
"cvd:sortInfos");
List<SortInfo> sortInfos = new ArrayList<>();
for (Map<String, Serializable> info : list) {
sortInfos.add(SortInfo.asSortInfo(info));
}
return sortInfos;
}
}