001/*
002 *  Copyright 2018 Anyware Services
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 */
016package org.ametys.web.frontoffice.search.metamodel.impl;
017
018import java.util.ArrayList;
019import java.util.Collection;
020import java.util.Collections;
021import java.util.List;
022import java.util.Optional;
023import java.util.function.Function;
024import java.util.stream.Collectors;
025
026import org.apache.avalon.framework.configuration.Configurable;
027import org.apache.avalon.framework.configuration.Configuration;
028import org.apache.avalon.framework.configuration.ConfigurationException;
029import org.apache.avalon.framework.service.ServiceException;
030import org.apache.avalon.framework.service.ServiceManager;
031import org.apache.avalon.framework.service.Serviceable;
032import org.apache.commons.collections4.CollectionUtils;
033
034import org.ametys.cms.content.ContentHelper;
035import org.ametys.cms.contenttype.ContentTypesHelper;
036import org.ametys.cms.search.query.AndQuery;
037import org.ametys.cms.search.query.ContentTypeQuery;
038import org.ametys.cms.search.query.DocumentTypeQuery;
039import org.ametys.cms.search.query.Query;
040import org.ametys.runtime.i18n.I18nizableText;
041import org.ametys.web.frontoffice.search.instance.model.SearchContext.LangQueryProducer;
042import org.ametys.web.frontoffice.search.metamodel.AdditionalParameterValueMap;
043import org.ametys.web.frontoffice.search.metamodel.FacetDefinition;
044import org.ametys.web.frontoffice.search.metamodel.Returnable;
045import org.ametys.web.frontoffice.search.metamodel.ReturnableExtensionPoint;
046import org.ametys.web.frontoffice.search.metamodel.ReturnableSaxer;
047import org.ametys.web.frontoffice.search.metamodel.SortDefinition;
048import org.ametys.web.frontoffice.search.metamodel.context.ContextQueriesWrapper;
049import org.ametys.web.indexing.solr.SolrWebFieldNames;
050import org.ametys.web.repository.page.Page;
051import org.ametys.web.repository.site.SiteManager;
052import org.ametys.web.search.query.PageContentQuery;
053import org.ametys.web.search.query.SitemapQuery;
054
055/**
056 * {@link Returnable} for {@link Page}s
057 */
058public class PageReturnable implements Returnable, Serviceable, Configurable
059{
060    /** Avalon Role */
061    public static final String ROLE = PageReturnable.class.getName();
062    
063    /** The prefix for the ids of facets and sorts */
064    protected static final String __PREFIX_ID = "PageReturnable$";
065    
066    /** The sites manager */
067    protected SiteManager _siteManager;
068    /** The content returnable */
069    protected Returnable _contentReturnable;
070    
071    /** The helper to handler content types */
072    protected ContentTypesHelper _contentTypesHelper;
073    /** The helper to handler contents */
074    protected ContentHelper _contentHelper;
075    /** The service manager. */
076    protected ServiceManager _manager;
077    
078    /** The label */
079    protected I18nizableText _label;
080    /** The saxer */
081    protected ReturnableSaxer _saxer;
082    
083    
084    @Override
085    public void service(ServiceManager manager) throws ServiceException
086    {
087        _manager = manager;
088        _siteManager = (SiteManager) manager.lookup(SiteManager.ROLE);
089        ReturnableExtensionPoint resultTypeEP = (ReturnableExtensionPoint) manager.lookup(ReturnableExtensionPoint.ROLE);
090        _contentReturnable = resultTypeEP.getExtension(ContentReturnable.ROLE);
091        
092        _contentTypesHelper = (ContentTypesHelper) manager.lookup(ContentTypesHelper.ROLE);
093        _contentHelper = (ContentHelper) manager.lookup(ContentHelper.ROLE);
094    }
095    
096    @Override
097    public void configure(Configuration configuration) throws ConfigurationException
098    {
099        _label = I18nizableText.parseI18nizableText(configuration.getChild("label"), "plugin.web");
100    }
101    
102    @Override
103    public String getId()
104    {
105        return ROLE;
106    }
107    
108    @Override
109    public I18nizableText getLabel()
110    {
111        return _label;
112    }
113    
114    @Override
115    public boolean selectedByDefault()
116    {
117        return true;
118    }
119    
120    @Override
121    public Query filterReturnedDocumentQuery(Collection<ContextQueriesWrapper> contextQueriesWrappers, AdditionalParameterValueMap additionalParameterValues)
122    {
123        Collection<String> contentTypes = additionalParameterValues.getValue(ContentSearchable.PARAMETER_CONTENT_TYPES);
124        
125        // site property is indexed on page documents
126        Function<Query, Query> siteQueryJoiner = Function.identity();
127        // A SitemapQuery is on pages
128        Function<Query, Query> sitemapQueryJoiner = Function.identity();
129        // lang query
130        LangQueryProducer langQueryProducer = new LangQueryProducer(SitemapQuery.class, false);
131        // tag query is on contents => ignore it by passing an empty optional
132        Query pageContextQuery = ContextQueriesWrapper.getQuery(contextQueriesWrappers, Optional.of(siteQueryJoiner), Optional.of(sitemapQueryJoiner), Optional.of(langQueryProducer), Optional.empty());
133        
134        List<Query> queries = new ArrayList<>();
135        queries.add(new DocumentTypeQuery(SolrWebFieldNames.TYPE_PAGE));
136        if (CollectionUtils.isNotEmpty(contentTypes))
137        {
138            queries.add(new PageContentQuery(new ContentTypeQuery(contentTypes)));
139        }
140        queries.add(pageContextQuery);
141        return new AndQuery(queries);
142    }
143    
144    @Override
145    public ReturnableSaxer getSaxer(Collection<Returnable> allReturnables, AdditionalParameterValueMap additionalParameterValues)
146    {
147        if (_saxer == null)
148        {
149            _saxer = new PageSaxer(this);
150        }
151        return _saxer;
152    }
153    
154    @Override
155    public Collection<FacetDefinition> getFacets(AdditionalParameterValueMap additionalParameterValues)
156    {
157        Collection<FacetDefinition> contentFacets = _contentReturnable.getFacets(additionalParameterValues);
158        Collection<FacetDefinition> facetDefs = contentFacets.stream()
159                .filter(ContentFacetDefinition.class::isInstance)
160                .map(ContentFacetDefinition.class::cast)
161                .map(contentFacetDefinition -> new PageContentFacetDefinition(contentFacetDefinition, this))
162                .collect(Collectors.toList());
163        
164        return facetDefs;
165    }
166    
167    @Override
168    public Collection<SortDefinition> getSorts(AdditionalParameterValueMap additionalParameterValues)
169    {
170        return Collections.emptySet();
171    }
172}