001/*
002 *  Copyright 2025 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.odforientation;
017
018import java.io.IOException;
019import java.util.Collections;
020import java.util.List;
021import java.util.Optional;
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.generation.ServiceableGenerator;
029import org.apache.cocoon.xml.AttributesImpl;
030import org.apache.cocoon.xml.XMLUtils;
031import org.apache.commons.lang3.StringUtils;
032import org.xml.sax.SAXException;
033
034import org.ametys.cms.search.advanced.AbstractTreeNode;
035import org.ametys.cms.search.advanced.TreeLeaf;
036import org.ametys.core.util.LambdaUtils;
037import org.ametys.odf.enumeration.OdfReferenceTableEntry;
038import org.ametys.odf.enumeration.OdfReferenceTableHelper;
039import org.ametys.odf.enumeration.OdfReferenceTableHelper.SortField;
040import org.ametys.plugins.repository.AmetysObjectResolver;
041import org.ametys.web.frontoffice.search.SearchService;
042import org.ametys.web.frontoffice.search.instance.SearchServiceInstance;
043import org.ametys.web.frontoffice.search.instance.SearchServiceInstanceManager;
044import org.ametys.web.frontoffice.search.metamodel.impl.ContentReferencingSearchServiceCriterionDefinition;
045import org.ametys.web.repository.page.Page;
046import org.ametys.web.repository.page.Page.PageType;
047import org.ametys.web.repository.page.ZoneItem;
048import org.ametys.web.repository.page.ZoneItem.ZoneType;
049
050/**
051 * Generates the exhaustive list of orgunits
052 */
053public class OdfReferenceTableItemsGenerator extends ServiceableGenerator
054{
055    private AmetysObjectResolver _resolver;
056    private SearchServiceInstanceManager _searchServiceInstanceManager;
057    private OdfReferenceTableHelper _odfReferenceTableHelper;
058
059    @Override
060    public void service(ServiceManager serviceManager) throws ServiceException
061    {
062        super.service(serviceManager);
063        _resolver = (AmetysObjectResolver) serviceManager.lookup(AmetysObjectResolver.ROLE);
064        _searchServiceInstanceManager = (SearchServiceInstanceManager) serviceManager.lookup(SearchServiceInstanceManager.ROLE);
065        _odfReferenceTableHelper = (OdfReferenceTableHelper) serviceManager.lookup(OdfReferenceTableHelper.ROLE);
066    }
067    
068    @Override
069    public void generate() throws IOException, SAXException, ProcessingException
070    {
071        Request request = ObjectModelHelper.getRequest(objectModel);
072        
073        String lang = parameters.getParameter("lang", (String) request.getAttribute("sitemapLanguage"));
074        
075        ZoneItem zoneItem = (ZoneItem) request.getAttribute(ZoneItem.class.getName());
076        
077        String refTableId = zoneItem.getServiceParameters().getValue("refTableId");
078        
079        contentHandler.startDocument();
080        
081        XMLUtils.startElement(contentHandler, "items");
082        
083        List<OdfReferenceTableEntry> items = _odfReferenceTableHelper.getItems(refTableId, false, new SortField("order", true));
084        
085        items.stream().forEach(LambdaUtils.wrapConsumer(e -> {
086            
087            AttributesImpl attrs = new AttributesImpl();
088            attrs.addCDATAAttribute("id", e.getId());
089            attrs.addCDATAAttribute("code", e.getCode());
090            
091            XMLUtils.createElement(contentHandler, "item", attrs, e.getLabel(lang));
092        }));
093        
094        _saxSearchForm(zoneItem, refTableId);
095        
096        XMLUtils.endElement(contentHandler, "items");
097        
098        contentHandler.endDocument();
099    }
100    
101    private void _saxSearchForm(ZoneItem zoneItem, String refTableId) throws SAXException
102    {
103        String criterionInputName = _getRefTableCriterionInputName(zoneItem, refTableId);
104        if (criterionInputName != null)
105        {
106            XMLUtils.startElement(contentHandler, "search-form");
107            XMLUtils.createElement(contentHandler, "criterion", criterionInputName);
108            XMLUtils.endElement(contentHandler, "search-form");
109        }
110    }
111    
112    private String _getRefTableCriterionInputName(ZoneItem zoneItem, String refTableId)
113    {
114        String searchPageId = zoneItem.getServiceParameters().getValue("search-page");
115        if (StringUtils.isNotEmpty(searchPageId))
116        {
117            Page page = _resolver.resolveById(searchPageId);
118            if (page.getType() == PageType.CONTAINER) 
119            {
120                Optional< ? extends ZoneItem> searchZoneItem = page.getZones().stream()
121                    .flatMap(z -> z.getZoneItems().stream())
122                    .filter(zi -> zi.getType() == ZoneType.SERVICE)
123                    .filter(zi -> zi.getServiceId().equals(SearchService.ROLE))
124                    .findFirst();
125                    
126                if (searchZoneItem.isPresent())
127                {
128                    SearchServiceInstance serviceInstance = _searchServiceInstanceManager.get(searchZoneItem.get().getId());
129                    return serviceInstance.getCriterionTree()
130                            .map(AbstractTreeNode::getFlatLeaves)
131                            .orElseGet(Collections::emptyList)
132                            .stream()
133                            .map(TreeLeaf::getValue)
134                            .filter(c -> c.getCriterionDefinition() instanceof ContentReferencingSearchServiceCriterionDefinition && ((ContentReferencingSearchServiceCriterionDefinition) c.getCriterionDefinition()).getContentTypeId().equals(refTableId))
135                            .findFirst()
136                            .map(c -> c.getName())
137                            .orElseGet(null);
138                }
139            }
140        }
141        
142        getLogger().warn("No criteria found related to selected reference table '" + refTableId + "'");
143        return null;
144    }
145    
146}