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