001/*
002 *  Copyright 2020 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.plugins.workspaces.search.module;
017
018import java.util.Collections;
019import java.util.List;
020import java.util.stream.Collectors;
021
022import org.apache.cocoon.ProcessingException;
023import org.apache.cocoon.environment.Request;
024import org.apache.commons.lang3.StringUtils;
025import org.xml.sax.SAXException;
026
027import org.ametys.plugins.repository.AmetysObject;
028import org.ametys.plugins.repository.AmetysObjectIterable;
029import org.ametys.plugins.workspaces.project.objects.Project;
030
031/**
032 * Abstract generator for search module in the repository
033 *
034 */
035public abstract class AbstractXpathSearchModuleGenerator extends AbstractSearchModuleGenerator
036{
037
038    @Override
039    protected void saxHits(String siteName, String lang, String textfield, Request request, int offset, int limit, int minLimit) throws SAXException, ProcessingException
040    {
041        try
042        {
043            String query = getXPathQuery(siteName, lang, textfield, request, offset, limit);
044            if (StringUtils.isNotEmpty(query))
045            {
046                AmetysObjectIterable<AmetysObject> searchResults = _resolver.query(query);
047                long totalCount = searchResults.getSize();
048                
049                // I don't like this, but I did not found any better way
050                List<AmetysObject> results = searchResults.stream()
051                    .skip(offset)
052                    .limit(limit)
053                    .collect(Collectors.toList());
054                
055                saxHits(results, lang, offset, limit, minLimit, totalCount);
056            }
057            else
058            {
059                saxHits(Collections.EMPTY_LIST, lang, offset, limit, minLimit, 0);
060            }
061        }
062        catch (Exception e)
063        {
064            throw new ProcessingException("Unable to get search results", e);
065        }
066    }
067    
068    /**
069     * Get the xpath query on project
070     * @param projects the targeted projects
071     * @return the xpath query
072     */
073    protected String getProjectXPathQuery(List<Project> projects)
074    {
075        List<String> projectNames = projects.stream()
076                .map(Project::getName)
077                .map(name -> "fn:name() = '" + name + "'")
078                .collect(Collectors.toList());
079        
080        return "//element(*, ametys:project)" + (!projectNames.isEmpty() ? "[" + String.join(" or ", projectNames) + "]" : "");
081    }
082    
083    /**
084     * Get the Xpath query
085     * @param siteName the current site name
086     * @param lang the current language
087     * @param textfield the search input
088     * @param request the request
089     * @param offset the search offset
090     * @param limit the max number of results
091     * @return the search results
092     * @throws Exception if the search failed
093     */
094    protected abstract String getXPathQuery(String siteName, String lang, String textfield, Request request, int offset, int limit) throws Exception;
095    
096}