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