001/*
002 *  Copyright 2010 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.io.IOException;
019import java.util.Collection;
020import java.util.Map;
021
022import org.apache.avalon.framework.service.ServiceException;
023import org.apache.avalon.framework.service.ServiceManager;
024import org.apache.cocoon.ProcessingException;
025import org.apache.cocoon.environment.ObjectModelHelper;
026import org.apache.cocoon.environment.Request;
027import org.apache.cocoon.generation.ServiceableGenerator;
028import org.apache.cocoon.xml.AttributesImpl;
029import org.apache.cocoon.xml.XMLUtils;
030import org.apache.commons.lang.StringUtils;
031import org.xml.sax.SAXException;
032
033import org.ametys.cms.repository.Content;
034import org.ametys.cms.tag.TagProviderExtensionPoint;
035import org.ametys.plugins.repository.AmetysObjectResolver;
036import org.ametys.plugins.repository.AmetysRepositoryException;
037import org.ametys.plugins.repository.version.VersionableAmetysObject;
038import org.ametys.web.repository.content.SharedContent;
039import org.ametys.web.repository.content.WebContent;
040import org.ametys.web.repository.page.Page;
041import org.ametys.web.repository.page.SitemapElement;
042import org.ametys.web.repository.page.Zone;
043import org.ametys.web.repository.page.ZoneItem;
044
045/**
046 * SAX {@link Page}s referencing the content.
047 */
048public class ContentPagesGenerator extends ServiceableGenerator
049{
050    private AmetysObjectResolver _resolver;
051    private TagProviderExtensionPoint _tagProviderExtensionPoint;
052    
053    @Override
054    public void service(ServiceManager smanager) throws ServiceException
055    {
056        super.service(smanager);
057        _resolver = (AmetysObjectResolver) smanager.lookup(AmetysObjectResolver.ROLE);
058        _tagProviderExtensionPoint = (TagProviderExtensionPoint) smanager.lookup(TagProviderExtensionPoint.ROLE);
059    }
060    
061    @Override
062    public void generate() throws IOException, SAXException, ProcessingException
063    {
064        Request request = ObjectModelHelper.getRequest(objectModel);
065        Content content = (Content) request.getAttribute(Content.class.getName());
066
067        if (content == null)
068        {
069            String contentId = request.getParameter("contentId");
070            content = _resolver.resolveById(contentId);
071        }
072        
073        contentHandler.startDocument();
074        XMLUtils.startElement(contentHandler, "pages");
075        
076        // Take the HEAD revision
077        String revision = ((VersionableAmetysObject) content).getRevision();
078        ((VersionableAmetysObject) content).switchToRevision(null);
079        
080        if (content instanceof WebContent)
081        {
082            Collection<ZoneItem> zoneItems = ((WebContent) content).getReferencingZoneItems();
083            
084            // For a shared content, we are mainly interrested in refereces of the initial content!
085            if (content instanceof SharedContent && ((SharedContent) content).getInitialContent() instanceof WebContent)
086            {
087                zoneItems.addAll(((WebContent) ((SharedContent) content).getInitialContent()).getReferencingZoneItems());
088            }
089            
090            for (ZoneItem zoneItem : zoneItems)
091            {
092                Zone zone = zoneItem.getZone();
093                SitemapElement sitemapElement = zone.getSitemapElement();
094                
095                if (sitemapElement instanceof Page page)
096                {
097                    _saxPage(page, zone, zoneItem);
098                }
099            }
100        }
101        
102        ((VersionableAmetysObject) content).switchToRevision(revision);
103        
104        XMLUtils.endElement(contentHandler, "pages");
105        contentHandler.endDocument();
106    }
107
108    /**
109     * SAX a content's page.
110     * @param page the page to SAX.
111     * @param zone the zone the content is in.
112     * @param zoneItem the the zone item the content belongs to.
113     * @throws SAXException if an error occurs.
114     */
115    protected void _saxPage(Page page, Zone zone, ZoneItem zoneItem) throws SAXException
116    {
117        AttributesImpl cAttsPage = new AttributesImpl();
118        cAttsPage.addCDATAAttribute("id", _escape(page.getId()));
119        cAttsPage.addCDATAAttribute("name", _escape(page.getName()));
120        cAttsPage.addCDATAAttribute("path", _escape(page.getPathInSitemap()));
121        cAttsPage.addCDATAAttribute("title", _escape(page.getTitle()));
122        cAttsPage.addCDATAAttribute("long-title", _escape(page.getLongTitle()));
123        cAttsPage.addCDATAAttribute("lang", _escape(page.getSitemap().getName()));
124        cAttsPage.addCDATAAttribute("site", _escape(page.getSite().getName()));
125        cAttsPage.addCDATAAttribute("zone", _escape(zone.getName()));
126        cAttsPage.addCDATAAttribute("metadataSetName", _escape(StringUtils.defaultString(zoneItem.getViewName(), "main")));
127        
128        _saxTags (page, cAttsPage);
129        
130        XMLUtils.createElement(contentHandler, "page", cAttsPage);
131    }
132    
133    /**
134     * SAX page's tags
135     * @param page the page  
136     * @param attrs the attributes to SAX into
137     * @throws AmetysRepositoryException if failed to get page's tags
138     */
139    protected void _saxTags(Page page, AttributesImpl attrs) throws AmetysRepositoryException
140    {
141        for (String tag : page.getTags())
142        {
143            Map<String, Object> params = Map.of("siteName", page.getSiteName());
144            if (_tagProviderExtensionPoint.hasTag(tag, params))
145            {
146                // FIXME use nested element not this dirty XML
147                attrs.addCDATAAttribute("PLUGIN_TAGS_" + tag, "empty");
148            }
149        }
150    }
151    
152    private String _escape(String target)
153    {
154        if (target == null)
155        {
156            return "";
157        }
158        return target.replaceAll("&", "&amp;").replaceAll("\\\\", "\\\\\\\\").replaceAll("\"", "\\\\\"").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
159    }
160
161}