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.plugins.linkdirectory.link;
017
018import java.io.IOException;
019import java.util.Arrays;
020import java.util.List;
021import java.util.stream.Collectors;
022
023import org.apache.avalon.framework.service.ServiceException;
024import org.apache.avalon.framework.service.ServiceManager;
025import org.apache.cocoon.ProcessingException;
026import org.apache.cocoon.environment.ObjectModelHelper;
027import org.apache.cocoon.environment.Request;
028import org.apache.cocoon.generation.ServiceableGenerator;
029import org.apache.cocoon.xml.AttributesImpl;
030import org.apache.cocoon.xml.XMLUtils;
031import org.xml.sax.SAXException;
032
033import org.ametys.core.user.CurrentUserProvider;
034import org.ametys.core.user.UserIdentity;
035import org.ametys.plugins.linkdirectory.DirectoryHelper;
036import org.ametys.plugins.linkdirectory.repository.DefaultLink;
037import org.ametys.plugins.repository.data.holder.ModelAwareDataHolder;
038import org.ametys.web.repository.page.Page;
039import org.ametys.web.repository.page.ZoneItem;
040
041/**
042 * Generate the links' list of a link directory as XML.
043 */
044public class LinksGenerator extends ServiceableGenerator 
045{
046    private static final String __DISPLAY_USER_LINKS_PARAMETER = "displayUserLinks";
047    
048    /** The current user provider */
049    private CurrentUserProvider _currentUserProvider;
050    private DirectoryHelper _directoryHelper;
051    
052    @Override
053    public void service(ServiceManager serviceManager) throws ServiceException
054    {
055        super.service(serviceManager);
056        _currentUserProvider = (CurrentUserProvider) serviceManager.lookup(CurrentUserProvider.ROLE);
057        _directoryHelper = (DirectoryHelper) serviceManager.lookup(DirectoryHelper.ROLE);
058    }
059    
060    @Override
061    public void generate() throws IOException, SAXException, ProcessingException
062    {
063        Request request = ObjectModelHelper.getRequest(objectModel);
064        
065        Page page = (Page) request.getAttribute(Page.class.getName());
066        ZoneItem zoneItem = (ZoneItem) request.getAttribute(ZoneItem.class.getName());
067
068        String siteName = (String) request.getAttribute("site");
069        String language = (String) request.getAttribute("renderingLanguage");
070        
071        ModelAwareDataHolder serviceParameters = zoneItem.getServiceParameters();
072        String[] themes = serviceParameters.getValue("themes", false, new String[0]);
073        
074        contentHandler.startDocument();
075        
076        AttributesImpl attrs = new AttributesImpl();
077        attrs.addCDATAAttribute("siteName", siteName);
078        attrs.addCDATAAttribute("language", language);
079        if (page != null)
080        {
081            attrs.addCDATAAttribute("page", page.getId());
082        }
083        
084        UserIdentity user = _currentUserProvider.getUser();
085       
086        // Get the themes as a list
087        List<DefaultLink> links = _directoryHelper.getLinks(Arrays.asList(themes), siteName, language);
088        
089        String storageContext = null;
090        
091        // Get the zone item if we sax for a service
092        attrs.addCDATAAttribute("zoneItemId", zoneItem.getId());
093        
094        if (user != null)
095        {
096            storageContext = _directoryHelper.getStorageContext(request, zoneItem.getId());
097        }
098        
099        String customThemeName = serviceParameters.hasValue("custom-theme") ? serviceParameters.getValue("custom-theme") : null;
100        
101        if (_directoryHelper.themeExists(customThemeName, siteName, language))
102        {
103            attrs.addCDATAAttribute("custom-theme", customThemeName);
104        }
105        
106        // SAX the links
107        XMLUtils.startElement(contentHandler, "links", attrs);
108        try
109        {
110            // Sax the amount of deleted themes 
111            _saxDeletedThemes(siteName, language, Arrays.asList(themes));
112            
113            // SAX user links
114            List<DefaultLink> userLinks = null;
115            if (user != null && serviceParameters.getValue(__DISPLAY_USER_LINKS_PARAMETER, false, false))
116            {
117                userLinks = _directoryHelper.getUserLinks(siteName, language, user, customThemeName).stream().collect(Collectors.toList());
118            }
119            
120            _directoryHelper.saxLinks(siteName, contentHandler, links, userLinks, _directoryHelper.getContextVars(request), storageContext, user);
121        }
122        catch (Exception e)
123        {
124            getLogger().error("An exception occurred while saxing the links", e);
125        }
126        
127        XMLUtils.endElement(contentHandler, "links");
128        contentHandler.endDocument();
129    }
130
131    /**
132     * Sax the amount of deleted themes
133     * @param siteName the site's name
134     * @param language the language
135     * @param themesNamesList the list of theme ids
136     * @throws SAXException if an exception occurs while saxing
137     */
138    protected void _saxDeletedThemes(String siteName, String language, List<String> themesNamesList) throws SAXException
139    {
140        int amount = 0;
141        for (String themeName : themesNamesList)
142        {
143            if (!_directoryHelper.themeExists(themeName, siteName, language))
144            {
145                // The theme was deleted but it is still referenced by the service
146                getLogger().warn("The id '" + themeName + "' does not reference an existing theme.");
147                amount++;
148            }
149        }
150        
151        AttributesImpl attr = new AttributesImpl();
152        attr.addCDATAAttribute("count", Integer.toString(amount));
153        XMLUtils.createElement(contentHandler, "unknown-themes", attr);
154    }
155}