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