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