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}