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.Collection;
019import java.util.Collections;
020import java.util.Optional;
021import java.util.function.Function;
022
023import org.apache.avalon.framework.configuration.Configurable;
024import org.apache.avalon.framework.configuration.Configuration;
025import org.apache.avalon.framework.configuration.ConfigurationException;
026import org.apache.avalon.framework.service.ServiceException;
027import org.apache.avalon.framework.service.ServiceManager;
028import org.apache.avalon.framework.service.Serviceable;
029
030import org.ametys.cms.content.indexing.solr.SolrFieldNames;
031import org.ametys.cms.search.query.AndQuery;
032import org.ametys.cms.search.query.DocumentTypeQuery;
033import org.ametys.cms.search.query.OrQuery;
034import org.ametys.cms.search.query.Query;
035import org.ametys.cms.search.query.SolrNativeJoinQuery;
036import org.ametys.plugins.explorer.resources.Resource;
037import org.ametys.plugins.explorer.resources.metadata.TikaProvider;
038import org.ametys.runtime.i18n.I18nizableText;
039import org.ametys.web.frontoffice.search.metamodel.AdditionalParameterValueMap;
040import org.ametys.web.frontoffice.search.metamodel.FacetDefinition;
041import org.ametys.web.frontoffice.search.metamodel.Returnable;
042import org.ametys.web.frontoffice.search.metamodel.ReturnableSaxer;
043import org.ametys.web.frontoffice.search.metamodel.SortDefinition;
044import org.ametys.web.frontoffice.search.metamodel.context.ContextQueriesWrapper;
045import org.ametys.web.indexing.solr.SolrWebFieldNames;
046import org.ametys.web.search.query.ContentPageQuery;
047
048/**
049 * {@link Returnable} for {@link Resource}s
050 */
051public class ResourceReturnable implements Returnable, Serviceable, Configurable
052{
053    /** Avalon Role */
054    public static final String ROLE = ResourceReturnable.class.getName();
055    
056    /** The tika provider */
057    protected TikaProvider _tikaProvider;
058    
059    /** The label */
060    protected I18nizableText _label;
061    /** The saxer */
062    protected ReturnableSaxer _saxer;
063    
064    @Override
065    public void service(ServiceManager manager) throws ServiceException
066    {
067        _tikaProvider = (TikaProvider) manager.lookup(TikaProvider.ROLE);
068    }
069    
070    @Override
071    public void configure(Configuration configuration) throws ConfigurationException
072    {
073        _label = I18nizableText.parseI18nizableText(configuration.getChild("label"), "plugin.web");
074    }
075
076    @Override
077    public String getId()
078    {
079        return ROLE;
080    }
081    
082    @Override
083    public I18nizableText getLabel()
084    {
085        return _label;
086    }
087    
088    @Override
089    public boolean selectedByDefault()
090    {
091        return true;
092    }
093
094    @Override
095    public Query filterReturnedDocumentQuery(Collection<ContextQueriesWrapper> contextQueriesWrappers, AdditionalParameterValueMap additionalParameterValues)
096    {
097        return new OrQuery(
098                _filterVisibleContentAttachmentQuery(contextQueriesWrappers),
099                _filterVisiblePageAttachmentQuery(contextQueriesWrappers)
100        );
101    }
102    
103    private Query _filterVisibleContentAttachmentQuery(Collection<ContextQueriesWrapper> contextQueriesWrappers)
104    {
105        // site property is on contents via org.ametys.web.search.solr.field.SiteSearchField
106        Function<Query, Query> siteQueryJoiner = this::_queryOnContentAttachmentFromQueryOnContent;
107        // A SitemapQuery is on pages
108        Function<Query, Query> sitemapQueryJoiner = this::_queryOnContentAttachmentFromQueryOnPage;
109        // lang is not indexed on resources => ignore it by passing an empty optional
110        // tag query is on contents
111        Function<Query, Query> tagQueryJoiner = this::_queryOnContentAttachmentFromQueryOnContent;
112        Query contentAttachmentContextQuery = ContextQueriesWrapper.getQuery(contextQueriesWrappers, Optional.of(siteQueryJoiner), Optional.of(sitemapQueryJoiner), Optional.empty(), Optional.of(tagQueryJoiner));
113        
114        Query documentTypeQuery = new OrQuery(
115                new DocumentTypeQuery(SolrFieldNames.TYPE_CONTENT_ATTACHMENT_RESOURCE),
116//                new DocumentTypeQuery(SolrFieldNames.TYPE_CONTENT_ATTRIBUTE_RESOURCE),
117                new DocumentTypeQuery(SolrFieldNames.TYPE_RESOURCE)
118        );
119        
120        return new AndQuery(
121                documentTypeQuery,
122                contentAttachmentContextQuery
123        ); 
124    }
125    
126    private Query _queryOnContentAttachmentFromQueryOnContent(Query queryOnContent)
127    {
128        return new SolrNativeJoinQuery(SolrFieldNames.CONTENT_VISIBLE_ATTACHMENT_RESOURCE_IDS, SolrFieldNames.RESOURCE_ANCESTOR_AND_SELF_IDS, queryOnContent);
129    }
130    
131    private Query _queryOnContentAttachmentFromQueryOnPage(Query queryOnPage)
132    {
133        return _queryOnContentAttachmentFromQueryOnContent(new ContentPageQuery(queryOnPage));
134    }
135    
136    private Query _filterVisiblePageAttachmentQuery(Collection<ContextQueriesWrapper> contextQueriesWrappers)
137    {
138        // site property is indexed on pages
139        Function<Query, Query> siteQueryJoiner = this::_queryOnPageAttachment;
140        // A SitemapQuery is on pages
141        Function<Query, Query> sitemapQueryJoiner = this::_queryOnPageAttachment;
142        // lang is not indexed on resources => ignore it by passing an empty optional
143        // tag query is on contents => ignore it by passing an empty optional
144        Query pageAttachmentContextQuery = ContextQueriesWrapper.getQuery(contextQueriesWrappers, Optional.of(siteQueryJoiner), Optional.of(sitemapQueryJoiner), Optional.empty(), Optional.empty());
145        
146        Query documentTypeQuery = new OrQuery(
147                new DocumentTypeQuery(SolrWebFieldNames.TYPE_PAGE_RESOURCE),
148                new DocumentTypeQuery(SolrFieldNames.TYPE_RESOURCE)
149        );
150        
151        return new AndQuery(
152                documentTypeQuery,
153                pageAttachmentContextQuery
154        ); 
155    }
156    
157    private Query _queryOnPageAttachment(Query queryOnPage)
158    {
159        return new SolrNativeJoinQuery(SolrWebFieldNames.PAGE_VISIBLE_ATTACHMENT_RESOURCE_IDS, SolrFieldNames.RESOURCE_ANCESTOR_AND_SELF_IDS, queryOnPage);
160    }
161    
162    @Override
163    public ReturnableSaxer getSaxer(Collection<Returnable> allReturnables, AdditionalParameterValueMap additionalParameterValues)
164    {
165        if (_saxer == null)
166        {
167            _saxer = new ResourceSaxer(this);
168        }
169        return _saxer;
170    }
171    
172    @Override
173    public Collection<FacetDefinition> getFacets(AdditionalParameterValueMap additionalParameterValues)
174    {
175        return Collections.emptySet();
176    }
177    
178    @Override
179    public Collection<SortDefinition> getSorts(AdditionalParameterValueMap additionalParameterValues)
180    {
181        return Collections.emptySet();
182    }
183}