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}