001/*
002 *  Copyright 2019 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.odfweb.service.search;
017
018import java.util.List;
019
020import org.apache.cocoon.components.ContextHelper;
021import org.apache.cocoon.environment.Request;
022import org.apache.cocoon.xml.AttributesImpl;
023import org.apache.cocoon.xml.XMLUtils;
024import org.apache.commons.lang3.StringUtils;
025import org.slf4j.Logger;
026import org.xml.sax.ContentHandler;
027import org.xml.sax.SAXException;
028
029import org.ametys.cms.contenttype.MetadataSet;
030import org.ametys.odf.program.Program;
031import org.ametys.odf.program.ProgramPart;
032import org.ametys.odf.program.SubProgram;
033import org.ametys.plugins.odfweb.repository.ProgramPage;
034import org.ametys.plugins.odfweb.service.search.ProgramReturnable.DisplaySubprogramMode;
035import org.ametys.plugins.repository.AmetysObject;
036import org.ametys.web.frontoffice.search.metamodel.ReturnableSaxer;
037import org.ametys.web.frontoffice.search.metamodel.impl.PageReturnable;
038import org.ametys.web.frontoffice.search.metamodel.impl.PageSaxer;
039import org.ametys.web.frontoffice.search.requesttime.SearchComponentArguments;
040import org.ametys.web.repository.page.Page;
041import org.ametys.web.repository.site.Site;
042
043/**
044 * {@link ReturnableSaxer} for {@link ProgramReturnable}
045 */
046public class ProgramSaxer extends PageSaxer
047{
048    private ProgramReturnable _programReturnable;
049    private DisplaySubprogramMode _displaySubprogramMode;
050
051    /**
052     * Constructor
053     * @param pageReturnable The page returnable (needed for superclass)
054     * @param programReturnable The associated returnable on programs
055     * @param displaySubprogramMode The mode for displaying (or not) subprograms
056     */
057    public ProgramSaxer(PageReturnable pageReturnable, ProgramReturnable programReturnable, DisplaySubprogramMode displaySubprogramMode)
058    {
059        super(pageReturnable);
060        _programReturnable = programReturnable;
061        _displaySubprogramMode = displaySubprogramMode;
062    }
063    
064    @Override
065    public boolean canSax(AmetysObject hit, Logger logger, SearchComponentArguments args)
066    {
067        return hit instanceof Program;
068    }
069    
070    @Override
071    public void sax(ContentHandler contentHandler, AmetysObject hit, Logger logger, SearchComponentArguments args) throws SAXException
072    {
073        Request request = ContextHelper.getRequest(_programReturnable._avalonContext);
074        try
075        {
076            Program program = (Program) hit;
077            ProgramPage programPage = _resolveProgramPage(program, args.currentSite());
078            _saxProgramPage(contentHandler, programPage, logger, args);
079            saxSubPrograms(contentHandler, program, programPage, logger, request);
080        }
081        finally
082        {
083            MatchingSubprogramSearchComponent._removeMatchingSubProgramIdsRequestAttribute(request);
084        }
085    }
086    
087    private ProgramPage _resolveProgramPage(Program program, Site currentSite)
088    {
089        return _programReturnable._odfPageResolver.getProgramPage(program, currentSite.getName());
090    }
091    
092    private Page _resolveSubProgramPage(Program program, ProgramPage programPage, SubProgram subProgram)
093    {
094        return _programReturnable._odfPageResolver.getSubProgramPage(subProgram, program, programPage.getSiteName());
095    }
096    
097    private String _getSubProgramPagePath(Page subProgramPage, String programPath)
098    {
099        return StringUtils.substringAfterLast(subProgramPage.getPathInSitemap(), programPath);
100    }
101    
102    private void _saxProgramPage(ContentHandler contentHandler, ProgramPage programPage, Logger logger, SearchComponentArguments args) throws SAXException
103    {
104        super.sax(contentHandler, programPage, logger, args);
105    }
106    
107    /**
108     * SAX the subprograms of the program
109     * @param contentHandler The content handler
110     * @param program The program
111     * @param programPage The program page
112     * @param logger A logger
113     * @param request The request
114     * @throws SAXException if a SAX error occured
115     */
116    protected void saxSubPrograms(ContentHandler contentHandler, Program program, ProgramPage programPage, Logger logger, Request request) throws SAXException
117    {
118        if (_displaySubprogramMode == DisplaySubprogramMode.NONE)
119        {
120            return;
121        }
122
123        List<String> matchingSubProgramIds = MatchingSubprogramSearchComponent._getMatchingSubProgramIds(request);
124        MetadataSet metadataSet = _programReturnable._subprogramContentType.getMetadataSetForView("index");
125        String programPath = programPage.getPathInSitemap();
126        
127        for (ProgramPart childProgramPart : program.getProgramPartChildren())
128        {
129            if (childProgramPart instanceof SubProgram)
130            {
131                SubProgram subProgram = (SubProgram) childProgramPart;
132                
133                boolean matchSearch = matchingSubProgramIds.contains(subProgram.getId());
134                if (_displaySubprogramMode != DisplaySubprogramMode.MATCHING_SEARCH_ONLY || matchSearch)
135                {
136                    AttributesImpl attrs = new AttributesImpl();
137                    Page subProgramPage = _resolveSubProgramPage(program, programPage, subProgram);
138                    attrs.addCDATAAttribute("path", _getSubProgramPagePath(subProgramPage, programPath));
139                    attrs.addCDATAAttribute("title", subProgram.getTitle());
140                    if (_displaySubprogramMode == DisplaySubprogramMode.ALL_WITH_HIGHLIGHT)
141                    {
142                        attrs.addCDATAAttribute("highlight", String.valueOf(matchSearch));
143                    }
144                    XMLUtils.startElement(contentHandler, "subprogram", attrs);
145
146                    try
147                    {
148                        _programReturnable._metadataManager.saxMetadata(contentHandler, subProgram, metadataSet, null);
149                    }
150                    catch (Exception e)
151                    {
152                        logger.error("An error occurred during saxing subprogram '" + subProgram.getId() + "' metadata", e);
153                    }
154                    
155                    XMLUtils.endElement(contentHandler, "subprogram");
156                }
157            }
158        }
159    }
160}