001/* 002 * Copyright 2022 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.calendar.search; 017 018import java.util.Collection; 019import java.util.Collections; 020import java.util.HashSet; 021import java.util.LinkedHashSet; 022import java.util.List; 023import java.util.Map; 024import java.util.Objects; 025import java.util.Set; 026import java.util.stream.Collectors; 027 028import org.apache.avalon.framework.parameters.Parameters; 029import org.apache.avalon.framework.service.ServiceException; 030import org.apache.avalon.framework.service.ServiceManager; 031import org.apache.cocoon.xml.AttributesImpl; 032import org.apache.cocoon.xml.XMLUtils; 033import org.xml.sax.ContentHandler; 034import org.xml.sax.SAXException; 035 036import org.ametys.cms.search.advanced.AbstractTreeNode; 037import org.ametys.cms.search.advanced.TreeLeaf; 038import org.ametys.cms.tag.CMSTag; 039import org.ametys.cms.tag.Tag; 040import org.ametys.cms.tag.TagProviderExtensionPoint; 041import org.ametys.plugins.calendar.icsreader.IcsEventHelper; 042import org.ametys.web.frontoffice.search.instance.SearchServiceInstance; 043import org.ametys.web.frontoffice.search.instance.model.FOSearchCriterion; 044import org.ametys.web.frontoffice.search.requesttime.SearchComponent; 045import org.ametys.web.frontoffice.search.requesttime.SearchComponentArguments; 046import org.ametys.web.frontoffice.search.requesttime.impl.SaxFormSearchComponent; 047import org.ametys.web.frontoffice.search.requesttime.input.SearchUserInputs; 048import org.ametys.web.repository.page.ZoneItem; 049 050/** 051 * {@link SearchComponent} for saxing form for calendar search service 052 * Reactivate default {@link SaxFormSearchComponent} (disabled by "disableDefaultSax" parameter) 053 */ 054public class CalendarSaxFormSearchComponent extends SaxFormSearchComponent 055{ 056 private IcsEventHelper _icsEventHelper; 057 private TagProviderExtensionPoint _tagProviderEP; 058 059 @Override 060 public void service(ServiceManager smanager) throws ServiceException 061 { 062 super.service(smanager); 063 _icsEventHelper = (IcsEventHelper) smanager.lookup(IcsEventHelper.ROLE); 064 _tagProviderEP = (TagProviderExtensionPoint) smanager.lookup(TagProviderExtensionPoint.ROLE); 065 } 066 067 @Override 068 public boolean supports(SearchComponentArguments args) 069 { 070 return CalendarSearchService.isActive(args); 071 } 072 073 @Override 074 public void execute(SearchComponentArguments args) throws Exception 075 { 076 ContentHandler contentHandler = args.contentHandler(); 077 SearchServiceInstance serviceInstance = args.serviceInstance(); 078 List<FOSearchCriterion> nonStaticCriteria = serviceInstance.getCriterionTree() 079 .map(AbstractTreeNode::getFlatLeaves) 080 .orElseGet(Collections::emptyList) 081 .stream() 082 .map(TreeLeaf::getValue) 083 .filter(c -> !c.getMode().isStatic()) 084 .collect(Collectors.toList()); 085 Parameters parameters = args.generatorParameters(); 086 087 XMLUtils.startElement(contentHandler, "form"); 088 089 XMLUtils.startElement(contentHandler, "fields"); 090 saxFormFields(contentHandler, parameters, nonStaticCriteria, args.currentLang(), args.currentSite(), serviceInstance.computeCriteriaCounts()); 091 XMLUtils.endElement(contentHandler, "fields"); 092 093 SearchUserInputs userInputs = args.userInputs(); 094 095 Map<String, Object> userCriteria = userInputs.criteria(); 096 XMLUtils.startElement(contentHandler, "values"); 097 saxFormValues(contentHandler, parameters, nonStaticCriteria, userCriteria); 098 XMLUtils.endElement(contentHandler, "values"); 099 100 String zoneItemId = args.serviceInstance().getId(); 101 ZoneItem zoneItem = (ZoneItem) _resolver.resolveById(zoneItemId); 102 103 if (CalendarSearchService.hasTagCategories(args.serviceInstance())) 104 { 105 List<String> categoryNames = CalendarSearchService.getTagCategories(serviceInstance); 106 Set<Tag> tagCategories = getTagCategories(categoryNames, args); 107 tagCategories.addAll(_icsEventHelper.getIcsTags(zoneItem, args.currentSite().getName())); 108 saxTagFacet(contentHandler, tagCategories, args); 109 } 110 111 XMLUtils.endElement(contentHandler, "form"); 112 } 113 114 /** 115 * Get the configured tag categories 116 * @param categoryNames The parent tag category 117 * @param args the search arguments 118 * @return the tags 119 */ 120 protected Set<Tag> getTagCategories(List<String> categoryNames, SearchComponentArguments args) 121 { 122 Set<Tag> tags = new HashSet<>(); 123 124 if (categoryNames != null && !categoryNames.isEmpty()) 125 { 126 Map<String, Object> params = Map.of("siteName", args.currentSite().getName()); 127 128 Set<CMSTag> tagCategories = categoryNames.stream() 129 .map(c -> _tagProviderEP.getTag(c, params)) 130 .filter(Objects::nonNull) 131 .collect(Collectors.toSet()); 132 133 for (CMSTag cmsTag : tagCategories) 134 { 135 tags.addAll(_getChildTags(cmsTag)); 136 } 137 } 138 139 return tags; 140 } 141 142 private Set<Tag> _getChildTags(Tag tag) 143 { 144 Set<Tag> allTags = new LinkedHashSet<>(); 145 146 Map<String, ? extends Tag> childTagsMap = tag.getTags(); 147 148 if (childTagsMap != null) 149 { 150 Collection<? extends Tag> childTags = childTagsMap.values(); 151 allTags.addAll(childTags); 152 153 for (Tag child : childTags) 154 { 155 allTags.addAll(_getChildTags(child)); 156 } 157 } 158 159 return allTags; 160 } 161 162 /** 163 * Generate the list of tags 164 * @param handler the content handler 165 * @param tags the list of tags 166 * @param args the search arguments 167 * @throws SAXException if an error occurs while saxing 168 */ 169 protected void saxTagFacet(ContentHandler handler, Collection<Tag> tags, SearchComponentArguments args) throws SAXException 170 { 171 List<String> selectedTags = CalendarSearchService.getSelectedTags(args); 172 173 XMLUtils.startElement(handler, "tag-facet"); 174 for (Tag tag : tags) 175 { 176 AttributesImpl attrs = new AttributesImpl(); 177 attrs.addCDATAAttribute("selected", String.valueOf(selectedTags.contains(tag.getName()))); 178 CalendarSearchService.saxTag(handler, attrs, tag); 179 } 180 XMLUtils.endElement(handler, "tag-facet"); 181 } 182 183}