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