001/*
002 *  Copyright 2015 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.web.content;
017
018import java.util.Collection;
019import java.util.Locale;
020import java.util.Map;
021import java.util.Set;
022
023import org.apache.avalon.framework.service.ServiceException;
024import org.apache.avalon.framework.service.ServiceManager;
025import org.apache.cocoon.xml.AttributesImpl;
026import org.apache.cocoon.xml.XMLUtils;
027import org.apache.commons.lang3.StringUtils;
028import org.xml.sax.SAXException;
029
030import org.ametys.cms.content.AdditionalContentPropertiesGenerator;
031import org.ametys.cms.repository.Content;
032import org.ametys.plugins.repository.AmetysObject;
033import org.ametys.plugins.repository.AmetysRepositoryException;
034import org.ametys.web.repository.SiteAwareAmetysObject;
035import org.ametys.web.repository.content.SharedContent;
036import org.ametys.web.repository.content.WebContent;
037import org.ametys.web.repository.content.shared.SharedContentManager;
038import org.ametys.web.repository.page.Page;
039import org.ametys.web.repository.page.SitemapElement;
040import org.ametys.web.repository.page.Zone;
041import org.ametys.web.repository.page.ZoneItem;
042
043/**
044 * Generates addition information on web content
045 */
046public class AdditionalWebContentPropertiesGenerator extends AdditionalContentPropertiesGenerator
047{
048
049    /** The shared content helper. */
050    protected SharedContentManager _sharedContentComponent;
051
052    @Override
053    public void service(ServiceManager serviceManager) throws ServiceException
054    {
055        super.service(serviceManager);
056        _sharedContentComponent = (SharedContentManager) serviceManager.lookup(SharedContentManager.ROLE);
057    }
058    
059    @Override
060    protected void _saxOtherProperties(Content content) throws SAXException
061    {
062        _saxContentPages(content);
063        _saxSharedContent(content);
064    }
065    
066    @Override
067    protected Map<String, Object> getContextualParameters(AmetysObject object)
068    {
069        Map<String, Object> contextualParameters = super.getContextualParameters(object);
070        if (object instanceof SiteAwareAmetysObject)
071        {
072            contextualParameters.put("siteName", ((SiteAwareAmetysObject) object).getSiteName());
073        }
074        return contextualParameters;
075    }
076
077    private void _saxSharedContent(Content content) throws SAXException
078    {
079        Locale locale = content.getLanguage() != null ? new Locale(content.getLanguage()) : null;
080        
081        Set<SharedContent> sharedContents = _sharedContentComponent.getSharedContents(content);
082
083        if (content instanceof SharedContent)
084        {
085            Content initialContent = ((SharedContent) content).getInitialContent();
086
087            if (initialContent != null)
088            {
089                AttributesImpl icAttrs = new AttributesImpl();
090
091                icAttrs.addCDATAAttribute("id", initialContent.getId());
092                icAttrs.addCDATAAttribute("title", initialContent.getTitle(locale));
093
094                XMLUtils.startElement(contentHandler, "initial-content", icAttrs);
095                if (initialContent instanceof WebContent)
096                {
097                    Collection<Page> pages = ((WebContent) initialContent).getReferencingPages();
098                    for (Page page : pages)
099                    {
100                        _saxPage(page, null, null);
101                    }
102                }
103                XMLUtils.endElement(contentHandler, "initial-content");
104            }
105        }
106
107        for (SharedContent sharedContent : sharedContents)
108        {
109            AttributesImpl sharedAttrs = new AttributesImpl();
110            sharedAttrs.addCDATAAttribute("contentId", sharedContent.getId());
111            sharedAttrs.addCDATAAttribute("title", sharedContent.getTitle(locale));
112
113            XMLUtils.startElement(contentHandler, "share", sharedAttrs);
114            for (Page page : sharedContent.getReferencingPages())
115            {
116                _saxPage(page, null, null);
117            }
118            XMLUtils.endElement(contentHandler, "share");
119        }
120    }
121
122    private void _saxContentPages(Content content) throws SAXException
123    {
124        XMLUtils.startElement(contentHandler, "pages");
125
126        if (content instanceof WebContent)
127        {
128            Collection<ZoneItem> zoneItems = ((WebContent) content).getReferencingZoneItems();
129
130            // For a shared content, we are mainly interested in references of the initial content!
131            if (content instanceof SharedContent && ((SharedContent) content).getInitialContent() instanceof WebContent)
132            {
133                zoneItems.addAll(((WebContent) ((SharedContent) content).getInitialContent()).getReferencingZoneItems());
134            }
135
136            for (ZoneItem zoneItem : zoneItems)
137            {
138                Zone zone = zoneItem.getZone();
139                SitemapElement page = zone.getSitemapElement();
140
141                _saxPage(page, zone, zoneItem);
142            }
143        }
144
145        XMLUtils.endElement(contentHandler, "pages");
146    }
147
148    private String _escape(String target)
149    {
150        if (target == null)
151        {
152            return "";
153        }
154        return target.replaceAll("&", "&amp;").replaceAll("\\\\", "\\\\\\\\").replaceAll("\"", "\\\\\"").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
155    }
156
157    /**
158     * SAX a content's page.
159     * @param sitemapElement the page to SAX.
160     * @param zone the zone the content is in.
161     * @param zoneItem the the zone item the content belongs to.
162     * @throws SAXException if an error occurs.
163     */
164    protected void _saxPage(SitemapElement sitemapElement, Zone zone, ZoneItem zoneItem) throws SAXException
165    {
166        AttributesImpl cAttsPage = new AttributesImpl();
167        cAttsPage.addCDATAAttribute("id", _escape(sitemapElement.getId()));
168        cAttsPage.addCDATAAttribute("name", _escape(sitemapElement.getName()));
169        cAttsPage.addCDATAAttribute("path", _escape(sitemapElement.getPathInSitemap()));
170        cAttsPage.addCDATAAttribute("title", _escape(sitemapElement.getTitle()));
171        if (sitemapElement instanceof Page page)
172        {
173            cAttsPage.addCDATAAttribute("long-title", _escape(page.getLongTitle()));
174        }
175        else
176        {
177            cAttsPage.addCDATAAttribute("long-title", _escape(sitemapElement.getName()));
178        }
179        cAttsPage.addCDATAAttribute("lang", _escape(sitemapElement.getSitemap().getName()));
180        cAttsPage.addCDATAAttribute("site", _escape(sitemapElement.getSite().getName()));
181        if (zone != null)
182        {
183            cAttsPage.addCDATAAttribute("zone", _escape(zone.getName()));
184        }
185        if (zoneItem != null)
186        {
187            cAttsPage.addCDATAAttribute("metadataSetName", _escape(StringUtils.defaultString(zoneItem.getViewName(), "main")));
188        }
189        
190        if (sitemapElement instanceof Page page)
191        {
192            _saxTags (page, cAttsPage);
193        }
194
195        XMLUtils.createElement(contentHandler, "page", cAttsPage);
196    }
197
198    /**
199     * SAX page's tags
200     * @param page the page  
201     * @param attrs the attributes to SAX into
202     * @throws AmetysRepositoryException if failed to get page's tags
203     */
204    protected void _saxTags(Page page, AttributesImpl attrs) throws AmetysRepositoryException
205    {
206        for (String tag : page.getTags())
207        {
208            if (_tagProviderEP.hasTag(tag, getContextualParameters(page)))
209            {
210                // FIXME use nested element not this dirty XML
211                attrs.addCDATAAttribute("PLUGIN_TAGS_" + tag, "empty");
212            }
213        }
214    }
215}