001/*
002 *  Copyright 2016 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.cms.explorer;
017
018import java.io.IOException;
019import java.util.ArrayList;
020import java.util.List;
021import java.util.Map;
022
023import org.apache.avalon.framework.service.ServiceException;
024import org.apache.avalon.framework.service.ServiceManager;
025import org.apache.cocoon.ProcessingException;
026import org.apache.cocoon.environment.ObjectModelHelper;
027import org.apache.cocoon.environment.Request;
028import org.apache.cocoon.xml.XMLUtils;
029import org.apache.commons.lang.StringUtils;
030import org.xml.sax.SAXException;
031
032import org.ametys.cms.content.indexing.solr.SolrFieldNames;
033import org.ametys.cms.search.Sort;
034import org.ametys.cms.search.Sort.Order;
035import org.ametys.cms.search.query.AndQuery;
036import org.ametys.cms.search.query.DocumentTypeQuery;
037import org.ametys.cms.search.query.DublinCoreQuery;
038import org.ametys.cms.search.query.FilenameQuery;
039import org.ametys.cms.search.query.FullTextQuery;
040import org.ametys.cms.search.query.OrQuery;
041import org.ametys.cms.search.query.Query;
042import org.ametys.cms.search.query.Query.Operator;
043import org.ametys.cms.search.query.ResourceLocationQuery;
044import org.ametys.cms.search.query.UsersQuery;
045import org.ametys.cms.search.solr.SearcherFactory;
046import org.ametys.core.user.UserIdentity;
047import org.ametys.core.util.JSONUtils;
048import org.ametys.plugins.core.user.UserHelper;
049import org.ametys.plugins.explorer.ExplorerNode;
050import org.ametys.plugins.explorer.resources.Resource;
051import org.ametys.plugins.explorer.resources.generators.SearchGenerator;
052import org.ametys.plugins.repository.AmetysObjectIterable;
053
054/**
055 * Search resources in a specific explorer node.
056 */
057public class SearchResourcesGenerator extends SearchGenerator
058{
059    /** The searcher factory. */
060    protected SearcherFactory _searcherFactory;
061    
062    /** The JSON utils */
063    protected JSONUtils _jsonUtils;
064    
065    /** The user helper */
066    protected UserHelper _userHelper;
067    
068    @Override
069    public void service(ServiceManager sManager) throws ServiceException
070    {
071        super.service(sManager);
072        _searcherFactory = (SearcherFactory) sManager.lookup(SearcherFactory.ROLE);
073        _jsonUtils = (JSONUtils) sManager.lookup(JSONUtils.ROLE);
074        _userHelper = (UserHelper) manager.lookup(UserHelper.ROLE);
075    }
076    
077    @Override
078    public void generate() throws IOException, SAXException, ProcessingException
079    {
080        Request request = ObjectModelHelper.getRequest(objectModel);
081        
082        String id = request.getParameter("id");
083        String rootId = request.getParameter("rootId");
084        ExplorerNode node = _resolver.resolveById(id);
085        
086        Query query = getQuery(request, node, rootId);
087        
088        contentHandler.startDocument();
089        XMLUtils.startElement(contentHandler, "resources");
090        
091        try
092        {
093            Sort sort = new Sort(SolrFieldNames.TITLE_SORT, Order.ASC);
094            
095            AmetysObjectIterable<Resource> resources = _searcherFactory.create()
096                                                        .withQuery(query)
097                                                        .withFilterQueries(new DocumentTypeQuery(SolrFieldNames.TYPE_RESOURCE))
098                                                        .withSort(sort)
099                                                        .search();
100            
101            for (Resource resource : resources)
102            {
103                saxResource(resource);
104            }
105        }
106        catch (Exception e)
107        {
108            getLogger().error("Error searching resources in the explorer node " + id, e);
109            throw new ProcessingException("Error searching resources in the explorer node " + id, e);
110        }
111        
112        XMLUtils.endElement(contentHandler, "resources");
113        contentHandler.endDocument();
114    }
115    
116    /**
117     * Build the query object corresponding to the user search.
118     * @param request The user request.
119     * @param explorerNode The explorer node to search into.
120     * @param rootId The root ID, can be null to search all resources.
121     * @return the query object.
122     */
123    protected Query getQuery(Request request, ExplorerNode explorerNode, String rootId)
124    {
125        List<Query> queries = new ArrayList<>();
126        
127        if (explorerNode != null || StringUtils.isNotEmpty(rootId))
128        {
129            String path = explorerNode == null ? "" : explorerNode.getExplorerPath();
130            queries.add(new ResourceLocationQuery(rootId, path));
131        }
132        
133        // File name
134        String name = request.getParameter("name");
135        if (StringUtils.isNotEmpty(name))
136        {
137            queries.add(new FilenameQuery(name));
138        }
139        
140        // Full text
141        String fulltext = request.getParameter("fulltext");
142        if (StringUtils.isNotEmpty(fulltext))
143        {
144            queries.add(new FullTextQuery(fulltext, Operator.LIKE));
145        }
146        
147        String keywords = request.getParameter("keywords");
148        if (StringUtils.isNotEmpty(keywords))
149        {
150            Query subjectQuery = new DublinCoreQuery("subject", keywords);
151            Query descQuery = new DublinCoreQuery("description", keywords);
152            
153            queries.add(new OrQuery(subjectQuery, descQuery));
154        }
155        
156        String authorAsStr = request.getParameter("author");
157        Map<String, Object> json = _jsonUtils.convertJsonToMap(authorAsStr);
158        UserIdentity author = _userHelper.json2userIdentity(json);
159        if (null != author)
160        {
161            queries.add(new UsersQuery(SolrFieldNames.RESOURCE_CREATOR, author));
162        }
163        
164        return new AndQuery(queries);
165    }
166}