001/* 002 * Copyright 2017 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.events; 017 018import java.io.IOException; 019import java.time.LocalDate; 020import java.time.ZoneId; 021import java.time.ZonedDateTime; 022import java.time.format.DateTimeFormatter; 023import java.util.ArrayList; 024import java.util.Collection; 025import java.util.List; 026import java.util.Optional; 027 028import org.apache.avalon.framework.service.ServiceException; 029import org.apache.avalon.framework.service.ServiceManager; 030import org.apache.cocoon.components.source.impl.SitemapSource; 031import org.apache.cocoon.generation.ServiceableGenerator; 032import org.apache.cocoon.xml.AttributesImpl; 033import org.apache.cocoon.xml.XMLUtils; 034import org.apache.excalibur.source.SourceResolver; 035import org.xml.sax.ContentHandler; 036import org.xml.sax.SAXException; 037 038import org.ametys.cms.filter.ContentFilterHelper; 039import org.ametys.cms.repository.Content; 040import org.ametys.core.util.IgnoreRootHandler; 041import org.ametys.runtime.i18n.I18nizableText; 042import org.ametys.runtime.model.type.ModelItemType; 043import org.ametys.runtime.model.type.ModelItemTypeConstants; 044import org.ametys.web.filter.WebContentFilter; 045import org.ametys.web.filter.WebContentFilterHelper; 046import org.ametys.web.repository.content.WebContent; 047import org.ametys.web.repository.page.Page; 048 049/** 050 * Abstract generator provinding methods to sax an event content 051 */ 052public abstract class AbstractEventGenerator extends ServiceableGenerator 053{ 054 /** The source resolver. */ 055 protected SourceResolver _resolver; 056 057 /** The content filter helper. */ 058 protected WebContentFilterHelper _filterHelper; 059 060 @Override 061 public void service(ServiceManager serviceManager) throws ServiceException 062 { 063 super.service(serviceManager); 064 _resolver = (SourceResolver) serviceManager.lookup(SourceResolver.ROLE); 065 _filterHelper = (WebContentFilterHelper) serviceManager.lookup(ContentFilterHelper.ROLE); 066 } 067 068 /** 069 * SAX a content 070 * 071 * @param handler The content handler to SAX into 072 * @param content The content. 073 * @param saxContentItSelf true to sax the content, false will only sax some meta 074 * @param filter The filter. Can be null if saxContentItSelf is false 075 * @param checkUserAccess True to check user access when saxing the content itself 076 * @throws SAXException If an error occurs while SAXing 077 * @throws IOException If an error occurs while retrieving content. 078 */ 079 public void saxContent(ContentHandler handler, Content content, boolean saxContentItSelf, WebContentFilter filter, boolean checkUserAccess) throws SAXException, IOException 080 { 081 List<String> params = new ArrayList<>(); 082 params.add(content.getTitle()); 083 084 AttributesImpl attrs = new AttributesImpl(); 085 086 String start = _getFormatedDateAttribute(content, EventsFilterHelper.START_DATE_META); 087 if (start != null) 088 { 089 params.add(start); 090 attrs.addCDATAAttribute("start", start); 091 } 092 093 String end = _getFormatedDateAttribute(content, EventsFilterHelper.END_DATE_META); 094 if (end != null) 095 { 096 params.add(end); 097 attrs.addCDATAAttribute("end", end); 098 } 099 100 XMLUtils.startElement(handler, "event", attrs); 101 102 String key = end == null ? "CALENDAR_SERVICE_AGENDA_EVENT_TITLE_SINGLE_DAY" : "CALENDAR_SERVICE_AGENDA_FROM_TO"; 103 I18nizableText description = new I18nizableText(null, key, params); 104 105 description.toSAX(handler, "description"); 106 107 if (saxContentItSelf) 108 { 109 // Link view. 110 XMLUtils.startElement(handler, "view"); 111 _filterHelper.saxContent(handler, content, filter.getView(), checkUserAccess); 112 XMLUtils.endElement(handler, "view"); 113 } 114 115 // XML full view. 116 saxXMLContent(handler, content, "main"); 117 118 if (content instanceof WebContent) 119 { 120 WebContent webContent = (WebContent) content; 121 122 XMLUtils.startElement(handler, "pages"); 123 Collection<Page> pages = webContent.getReferencingPages(); 124 for (Page page : pages) 125 { 126 AttributesImpl atts = new AttributesImpl(); 127 atts.addCDATAAttribute("id", page.getId()); 128 atts.addCDATAAttribute("name", page.getName()); 129 atts.addCDATAAttribute("lang", page.getSitemapName()); 130 atts.addCDATAAttribute("site", page.getSiteName()); 131 atts.addCDATAAttribute("path", page.getPathInSitemap()); 132 atts.addCDATAAttribute("title", page.getTitle()); 133 XMLUtils.createElement(handler, "page", atts); 134 } 135 XMLUtils.endElement(handler, "pages"); 136 } 137 XMLUtils.endElement(handler, "event"); 138 } 139 140 /** 141 * Retrieves the formated value of the date attribute of the given content 142 * @param content the content 143 * @param attributePath the path of the attribute. The attribute must be date or date time 144 * @return the formated value 145 */ 146 protected String _getFormatedDateAttribute(Content content, String attributePath) 147 { 148 ModelItemType attributeType = content.getType(attributePath); 149 150 if (ModelItemTypeConstants.DATE_TYPE_ID.equals(attributeType.getId())) 151 { 152 LocalDate date = content.getValue(attributePath); 153 return Optional.ofNullable(date).map(d -> d.format(DateTimeFormatter.ISO_LOCAL_DATE)).orElse(null); 154 } 155 else 156 { 157 ZonedDateTime date = content.getValue(attributePath); 158 return Optional.ofNullable(date).map(d -> d.withZoneSameInstant(ZoneId.systemDefault()).format(DateTimeFormatter.ISO_LOCAL_DATE)).orElse(null); 159 } 160 } 161 162 /** 163 * SAX a content in XML mode. 164 * 165 * @param handler The content handler to SAX into 166 * @param content The content to SAX 167 * @param viewName The view to use 168 * @throws SAXException If an error occurs while SAXing 169 * @throws IOException If an error occurs while retrieving content. 170 */ 171 public void saxXMLContent(ContentHandler handler, Content content, String viewName) throws SAXException, IOException 172 { 173 String uri = "cocoon://_content.xml?contentId=" + content.getId() + "&viewName=" + viewName; 174 SitemapSource src = null; 175 176 try 177 { 178 src = (SitemapSource) _resolver.resolveURI(uri); 179 src.toSAX(new IgnoreRootHandler(handler)); 180 } 181 finally 182 { 183 _resolver.release(src); 184 } 185 } 186}