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.Locale; 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.LocaleUtils; 032import org.apache.commons.lang3.StringUtils; 033import org.xml.sax.SAXException; 034 035import org.ametys.cms.contenttype.ContentTypesHelper; 036import org.ametys.cms.repository.ContentTypeExpression; 037import org.ametys.cms.search.advanced.AbstractTreeNode; 038import org.ametys.cms.search.advanced.TreeLeaf; 039import org.ametys.core.util.LambdaUtils; 040import org.ametys.odf.orgunit.OrgUnit; 041import org.ametys.odf.orgunit.OrgUnitFactory; 042import org.ametys.odf.orgunit.RootOrgUnitProvider; 043import org.ametys.plugins.repository.AmetysObjectIterable; 044import org.ametys.plugins.repository.AmetysObjectResolver; 045import org.ametys.plugins.repository.query.QueryHelper; 046import org.ametys.plugins.repository.query.expression.Expression; 047import org.ametys.plugins.repository.query.expression.Expression.Operator; 048import org.ametys.runtime.model.View; 049import org.ametys.runtime.model.type.DataContext; 050import org.ametys.web.frontoffice.search.SearchService; 051import org.ametys.web.frontoffice.search.instance.SearchServiceInstance; 052import org.ametys.web.frontoffice.search.instance.SearchServiceInstanceManager; 053import org.ametys.web.repository.page.Page; 054import org.ametys.web.repository.page.Page.PageType; 055import org.ametys.web.repository.page.ZoneItem; 056import org.ametys.web.repository.page.ZoneItem.ZoneType; 057 058/** 059 * Generates the exhaustive list of orgunits 060 */ 061public class OrgUnitsGenerator extends ServiceableGenerator 062{ 063 private AmetysObjectResolver _resolver; 064 private RootOrgUnitProvider _rootOrgUnitProvider; 065 private ContentTypesHelper _cTypeHelper; 066 private SearchServiceInstanceManager _searchServiceInstanceManager; 067 068 @Override 069 public void service(ServiceManager serviceManager) throws ServiceException 070 { 071 super.service(serviceManager); 072 _resolver = (AmetysObjectResolver) serviceManager.lookup(AmetysObjectResolver.ROLE); 073 _rootOrgUnitProvider = (RootOrgUnitProvider) serviceManager.lookup(RootOrgUnitProvider.ROLE); 074 _cTypeHelper = (ContentTypesHelper) serviceManager.lookup(ContentTypesHelper.ROLE); 075 _searchServiceInstanceManager = (SearchServiceInstanceManager) serviceManager.lookup(SearchServiceInstanceManager.ROLE); 076 } 077 078 @Override 079 public void generate() throws IOException, SAXException, ProcessingException 080 { 081 Request request = ObjectModelHelper.getRequest(objectModel); 082 083 String lang = parameters.getParameter("lang", (String) request.getAttribute("sitemapLanguage")); 084 Locale defaultLocale = LocaleUtils.toLocale(lang); 085 086 ZoneItem zoneItem = (ZoneItem) request.getAttribute(ZoneItem.class.getName()); 087 088 String contentView = zoneItem.getServiceParameters().getValue("contentView"); 089 View view = _cTypeHelper.getView(contentView, new String[] {OrgUnitFactory.ORGUNIT_CONTENT_TYPE}, new String[0]); 090 091 092 contentHandler.startDocument(); 093 094 XMLUtils.startElement(contentHandler, "orgunits"); 095 096 Expression expr = new ContentTypeExpression(Operator.EQ, OrgUnitFactory.ORGUNIT_CONTENT_TYPE); 097 String xPathQuery = QueryHelper.getXPathQuery(null, OrgUnitFactory.ORGUNIT_NODETYPE, expr); 098 AmetysObjectIterable<OrgUnit> orgUnits = _resolver.query(xPathQuery); 099 100 orgUnits.stream().filter(ou -> !_rootOrgUnitProvider.isRoot(ou)).forEach(LambdaUtils.wrapConsumer(ou -> { 101 102 AttributesImpl attrs = new AttributesImpl(); 103 attrs.addCDATAAttribute("id", ou.getId()); 104 105 XMLUtils.startElement(contentHandler, "orgunit", attrs); 106 ou.dataToSAX(contentHandler, view, DataContext.newInstance().withLocale(defaultLocale).withEmptyValues(false)); 107 XMLUtils.endElement(contentHandler, "orgunit"); 108 })); 109 110 _saxSearchForm(zoneItem); 111 112 XMLUtils.endElement(contentHandler, "orgunits"); 113 114 contentHandler.endDocument(); 115 } 116 117 private void _saxSearchForm(ZoneItem zoneItem) throws SAXException 118 { 119 String criterionInputName = _getOrgUnitCriterionInputName(zoneItem); 120 if (criterionInputName != null) 121 { 122 XMLUtils.startElement(contentHandler, "search-form"); 123 XMLUtils.createElement(contentHandler, "criterion", criterionInputName); 124 XMLUtils.endElement(contentHandler, "search-form"); 125 } 126 } 127 128 private String _getOrgUnitCriterionInputName(ZoneItem zoneItem) 129 { 130 String searchPageId = zoneItem.getServiceParameters().getValue("search-page"); 131 if (StringUtils.isNotEmpty(searchPageId)) 132 { 133 Page page = _resolver.resolveById(searchPageId); 134 if (page.getType() == PageType.CONTAINER) 135 { 136 Optional< ? extends ZoneItem> searchZoneItem = page.getZones().stream() 137 .flatMap(z -> z.getZoneItems().stream()) 138 .filter(zi -> zi.getType() == ZoneType.SERVICE) 139 .filter(zi -> zi.getServiceId().equals(SearchService.ROLE)) 140 .findFirst(); 141 142 if (searchZoneItem.isPresent()) 143 { 144 SearchServiceInstance serviceInstance = _searchServiceInstanceManager.get(searchZoneItem.get().getId()); 145 return serviceInstance.getCriterionTree() 146 .map(AbstractTreeNode::getFlatLeaves) 147 .orElseGet(Collections::emptyList) 148 .stream() 149 .map(TreeLeaf::getValue) 150 .filter(c -> StringUtils.endsWith(c.getCriterionDefinition().getName(), "$org.ametys.plugins.odf.Content.abstractProgram$orgUnit")) 151 .findFirst() 152 .map(c -> c.getName()) 153 .orElseGet(null); 154 155 } 156 } 157 } 158 159 return null; 160 } 161 162}