001/* 002 * Copyright 2018 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.web.frontoffice.search.requesttime.impl; 017 018import java.io.IOException; 019import java.util.Collection; 020import java.util.Optional; 021 022import org.apache.avalon.framework.configuration.Configurable; 023import org.apache.avalon.framework.configuration.Configuration; 024import org.apache.avalon.framework.configuration.ConfigurationException; 025import org.apache.cocoon.ProcessingException; 026import org.apache.cocoon.xml.AttributesImpl; 027import org.apache.cocoon.xml.XMLUtils; 028import org.apache.commons.lang.StringUtils; 029import org.xml.sax.ContentHandler; 030import org.xml.sax.SAXException; 031 032import org.ametys.web.WebConstants; 033import org.ametys.web.frontoffice.search.instance.SearchServiceInstance; 034import org.ametys.web.frontoffice.search.instance.model.Link; 035import org.ametys.web.frontoffice.search.instance.model.ResultDisplay; 036import org.ametys.web.frontoffice.search.instance.model.ResultDisplayType; 037import org.ametys.web.frontoffice.search.metamodel.AdditionalParameterValueMap; 038import org.ametys.web.frontoffice.search.metamodel.AdditionalSearchServiceParameter; 039import org.ametys.web.frontoffice.search.requesttime.SearchComponent; 040import org.ametys.web.frontoffice.search.requesttime.SearchComponentArguments; 041import org.ametys.web.repository.page.Page; 042import org.ametys.web.repository.page.ZoneItem; 043import org.ametys.web.service.ServiceParameter; 044 045/** 046 * {@link SearchComponent} executing in two parts: opening 'search' tag and SAXing general data, then closing 'search' tag. 047 */ 048public class SaxGeneralDataSearchComponent implements SearchComponent, Configurable 049{ 050 private static final String __IS_AJAX_PARAMETER_NAME = "ajax"; 051 052 private int _part; 053 054 @Override 055 public void configure(Configuration configuration) throws ConfigurationException 056 { 057 _part = configuration.getChild("part").getValueAsInteger(); 058 } 059 060 @Override 061 public int priority() 062 { 063 return _part == 1 ? MAX_PRIORITY + 1000 : MIN_PRIORITY - 1000; 064 } 065 066 @Override 067 public boolean supports(SearchComponentArguments args) 068 { 069 return !args.generatorParameters().getParameterAsBoolean(DISABLE_DEFAULT_SAX_PARAMETER_NAME, false); 070 } 071 072 @Override 073 public void execute(SearchComponentArguments args) throws Exception 074 { 075 ContentHandler contentHandler = args.contentHandler(); 076 if (_part == 1) 077 { 078 String currentSiteName = args.currentSite().getName(); 079 String lang = args.currentLang(); 080 Page page = args.currentPage(); 081 082 AttributesImpl attrs = new AttributesImpl(); 083 attrs.addCDATAAttribute("site", currentSiteName); 084 attrs.addCDATAAttribute("lang", lang); 085 attrs.addCDATAAttribute("ajax", args.generatorParameters().getParameter(__IS_AJAX_PARAMETER_NAME, "false")); 086 087 XMLUtils.startElement(contentHandler, "search", attrs); 088 089 ZoneItem zoneItem = (ZoneItem) args.request().getAttribute(WebConstants.REQUEST_ATTR_ZONEITEM); 090 saxServiceIdentifiers(args, zoneItem); 091 saxCacheable(args, zoneItem); 092 saxAdditionalParameters(args); 093 saxAdditionalInfos(args); 094 095 // The search url 096 String url = lang + "/" + page.getPathInSitemap() + ".html"; 097 if (args.isDebug()) 098 { 099 url = DebugSearchComponent.appendDebugRequestParameters(url, args); 100 } 101 XMLUtils.createElement(contentHandler, "url", url); 102 103 SearchServiceInstance serviceInstance = args.serviceInstance(); 104 ResultDisplay resultDisplay = serviceInstance.getResultDisplay(); 105 // Display the form and results on same page? 106 ResultDisplayType resultDisplayType = resultDisplay.getType(); 107 XMLUtils.createElement(contentHandler, "result-display-type", resultDisplayType.name()); 108 109 XMLUtils.createElement(contentHandler, "header", serviceInstance.getTitle()); 110 XMLUtils.createElement(contentHandler, "result-page", resultDisplayType == ResultDisplayType.ON_PAGE ? resultDisplay.resultPage().get().getId() : ""); 111 XMLUtils.createElement(contentHandler, "compute-counts", Boolean.toString(serviceInstance.computeCriteriaCounts())); 112 XMLUtils.createElement(contentHandler, "launch-search-at-startup", Boolean.toString(resultDisplay.launchSearchAtStartup().orElse(false))); 113 saxRSSFeedURL(contentHandler, serviceInstance, zoneItem); 114 Link link = serviceInstance.getLink(); 115 Optional<Page> linkTarget = link.getTarget(); 116 if (linkTarget.isPresent()) 117 { 118 XMLUtils.startElement(contentHandler, "link"); 119 XMLUtils.createElement(contentHandler, "page", linkTarget.get().getId()); 120 XMLUtils.createElement(contentHandler, "title", link.getTitle()); 121 XMLUtils.endElement(contentHandler, "link"); 122 } 123 } 124 else 125 { 126 XMLUtils.endElement(contentHandler, "search"); 127 } 128 } 129 130 /** 131 * Generate the service identifiers: service group ID, ZoneItem ID, ... 132 * @param args The arguments 133 * @param zoneItem The zone item 134 * @throws SAXException if an error occurs SAXing data. 135 * @throws IOException if an error occurs SAXing data. 136 * @throws ProcessingException if a processing error occurs. 137 */ 138 protected void saxServiceIdentifiers(SearchComponentArguments args, ZoneItem zoneItem) throws SAXException, IOException, ProcessingException 139 { 140 ContentHandler contentHandler = args.contentHandler(); 141 142 String serviceGroupId = args.serviceInstance().getResultDisplay().serviceGroupId(); 143 144 // The service group ID. 145 if (StringUtils.isNotEmpty(serviceGroupId)) 146 { 147 XMLUtils.createElement(contentHandler, "group-id", serviceGroupId); 148 } 149 150 // Generate the ZoneItem ID if it exists. 151 if (zoneItem != null) 152 { 153 AttributesImpl atts = new AttributesImpl(); 154 atts.addCDATAAttribute("id", zoneItem.getId()); 155 XMLUtils.createElement(contentHandler, "zone-item", atts); 156 } 157 } 158 159 /** 160 * Generate the "cacheable" status of the service instance 161 * @param args The arguments 162 * @param zoneItem The zone item 163 * @throws SAXException if an error occurs SAXing data. 164 */ 165 protected void saxCacheable(SearchComponentArguments args, ZoneItem zoneItem) throws SAXException 166 { 167 boolean cacheable = zoneItem == null ? false : args.service().isCacheable(args.currentPage(), zoneItem); 168 XMLUtils.createElement(args.contentHandler(), "cacheable", Boolean.toString(cacheable)); 169 } 170 171 /** 172 * Generate the value of the {@link AdditionalSearchServiceParameter}s 173 * @param args The arguments 174 * @throws SAXException if an error occurs SAXing data. 175 */ 176 protected void saxAdditionalParameters(SearchComponentArguments args) throws SAXException 177 { 178 ContentHandler contentHandler = args.contentHandler(); 179 SearchServiceInstance serviceInstance = args.serviceInstance(); 180 Collection<AdditionalSearchServiceParameter> additionalParameters = serviceInstance.getAdditionalParameters(); 181 AdditionalParameterValueMap additionalParameterValues = serviceInstance.getAdditionalParameterValues(); 182 183 XMLUtils.startElement(contentHandler, "additionalParameters"); 184 for (AdditionalSearchServiceParameter additionalParameter : additionalParameters) 185 { 186 ServiceParameter serviceParameter = additionalParameter.getParameter(); 187 String name = serviceParameter.getName(); 188 Object value = additionalParameterValues.getValue(name); 189 XMLUtils.createElement(contentHandler, name, String.valueOf(value)); 190 } 191 XMLUtils.endElement(contentHandler, "additionalParameters"); 192 } 193 194 /** 195 * Generate any additional information. 196 * @param args The arguments 197 * @throws SAXException if an error occurs SAXing data. 198 * @throws IOException if an error occurs SAXing data. 199 * @throws ProcessingException if a processing error occurs. 200 */ 201 protected void saxAdditionalInfos(SearchComponentArguments args) throws SAXException, IOException, ProcessingException 202 { 203 // Nothing to do here. 204 } 205 206 /** 207 * Generate the URL for RSS feed 208 * @param contentHandler The content handler 209 * @param serviceInstance The service instance 210 * @param zoneItem The zone item 211 * @throws SAXException if an error occurs SAXing data. 212 */ 213 protected void saxRSSFeedURL(ContentHandler contentHandler, SearchServiceInstance serviceInstance, ZoneItem zoneItem) throws SAXException 214 { 215 if (serviceInstance.handleRss() && zoneItem != null) 216 { 217 // Split protocol and id 218 String[] zoneItemId = zoneItem.getId().split("://"); 219 String url = "_plugins/web/" + zoneItemId[0] + "/" + zoneItemId[1] + "/search-rss.xml"; 220 221 XMLUtils.createElement(contentHandler, "RSSFeedURL", url); 222 } 223 } 224}