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.odfweb.xslt;
017
018import org.apache.avalon.framework.service.ServiceException;
019import org.apache.avalon.framework.service.ServiceManager;
020import org.apache.commons.lang.StringUtils;
021
022import org.ametys.cms.repository.Content;
023import org.ametys.odf.ProgramItem;
024import org.ametys.odf.program.AbstractProgram;
025import org.ametys.odf.program.Program;
026import org.ametys.odf.program.SubProgram;
027import org.ametys.odf.skill.ODFSkillsHelper;
028import org.ametys.plugins.odfweb.repository.OdfPageHandler;
029import org.ametys.plugins.odfweb.repository.ProgramPage;
030import org.ametys.plugins.repository.AmetysObject;
031import org.ametys.web.repository.page.Page;
032import org.ametys.web.repository.sitemap.Sitemap;
033import org.ametys.web.transformation.xslt.AmetysXSLTHelper;
034
035/**
036 * Helper component to be used from XSL stylesheets.
037 */
038public class OdfXSLTHelper extends org.ametys.odf.OdfXSLTHelper
039{
040    /** The ODF page handler */
041    protected static OdfPageHandler _odfPageHandler;
042    
043    /** The ODF skills helper */
044    protected static ODFSkillsHelper _odfSkillsHelper;
045    
046    @Override
047    public void service(ServiceManager smanager) throws ServiceException
048    {
049        super.service(smanager);
050        _odfPageHandler = (OdfPageHandler) smanager.lookup(OdfPageHandler.ROLE);
051        _odfSkillsHelper = (ODFSkillsHelper) smanager.lookup(ODFSkillsHelper.ROLE);
052    }
053    
054    /**
055     * Get the ODF root page, for a specific site, language.
056     * If there is many ODF root pages, the first page of the list is returned.
057     * @param siteName the desired site name.
058     * @param language the sitemap language to search in.
059     * @return the first ODF root page, or null if not found
060     */
061    public static String odfRootPage(String siteName, String language)
062    {
063        Page odfRootPage = _odfPageHandler.getOdfRootPage(siteName, language);
064        if (odfRootPage != null)
065        {
066            return odfRootPage.getId();
067        }
068        return null;
069    }
070    
071    /**
072     * Get the ODF root page, for a specific site, language and catalog.
073     * @param siteName the desired site name.
074     * @param language the sitemap language to search in.
075     * @param catalog The ODF catalog
076     * @return the ODF root page, or null if not found
077     */
078    public static String odfRootPage(String siteName, String language, String catalog)
079    {
080        Page odfRootPage = _odfPageHandler.getOdfRootPage(siteName, language, catalog);
081        if (odfRootPage != null)
082        {
083            return odfRootPage.getId();
084        }
085        return null;
086    }
087    
088    /**
089     * Get the PDF url of a program or a subprogram
090     * @param contentId The content id
091     * @param siteName The site name
092     * @return the PDF url or empty string if the content is not a {@link Program} or {@link SubProgram}
093     */
094    public static String odfPDFUrl (String contentId, String siteName)
095    {
096        StringBuilder sb = new StringBuilder();
097        
098        Content content = _ametysObjectResolver.resolveById(contentId);
099        if (content instanceof AbstractProgram)
100        {
101            sb.append(AmetysXSLTHelper.uriPrefix())
102                .append("/plugins/odf-web/")
103                .append(siteName)
104                .append("/_content/")
105                .append(content.getName())
106                .append(".pdf");
107        }
108        
109        return sb.toString();
110    }
111
112    /**
113     * Get the id of parent program from the current page
114     * @return the id of parent program or null if not found
115     */
116    public static String parentProgramId()
117    {
118        String pageId = AmetysXSLTHelper.pageId();
119        
120        if (StringUtils.isNotEmpty(pageId))
121        {
122            Page page = _ametysObjectResolver.resolveById(pageId);
123            
124            AmetysObject parent = page.getParent();
125            while (!(parent instanceof Sitemap))
126            {
127                if (parent instanceof ProgramPage)
128                {
129                    return ((ProgramPage) parent).getProgram().getId();
130                }
131                
132                parent = parent.getParent();
133            }
134        }
135        
136        return null;
137    }
138    
139    /**
140     * <code>true</code> if the program item is part of an program item (program, subprogram or container) that is excluded from skills
141     * @param programItemId the program item id
142     * @param programPageItemId the program item page id. If null or empty, program item is display with no context, consider that skills are available
143     * @return <code>true</code> if the program item has an excluded parent in it path from the page context
144     */
145    public static boolean areSkillsUnavailable(String programItemId, String programPageItemId)
146    {
147        if (StringUtils.isBlank(programItemId) || StringUtils.isBlank(programPageItemId))
148        {
149            // program part is displayed outside a page context, assuming that skills should be displayed
150            return false;
151        }
152        
153        ProgramItem programItem = _ametysObjectResolver.resolveById(programItemId);
154        if (programItem instanceof Program)
155        {
156            return _odfSkillsHelper.isExcluded(programItem);
157        }
158        
159        Page programItemPage = _ametysObjectResolver.resolveById(programPageItemId);
160        
161        ProgramPage closestProgramPage = _getClosestProgramPage(programItemPage);
162        AbstractProgram closestProgramOrSubprogram = closestProgramPage.getProgram();
163        
164        ProgramItem parent = _odfHelper.getParentProgramItem(programItem, closestProgramOrSubprogram);
165        while (parent != null && !(parent instanceof Program))
166        {
167            if (_odfSkillsHelper.isExcluded(parent))
168            {
169                // If the parent is excluded, the skills are unavailable
170                return true;
171            }
172            
173            // If the closest program parent is a subprogram, continue to its program parent
174            if (closestProgramOrSubprogram instanceof SubProgram && closestProgramOrSubprogram.equals(parent))
175            {
176                closestProgramOrSubprogram = ((ProgramPage) closestProgramPage.getParent()).getProgram();
177            }
178            parent = _odfHelper.getParentProgramItem(parent, closestProgramOrSubprogram);
179        }
180        
181        return parent != null ? _odfSkillsHelper.isExcluded(parent) : false;
182    }
183    
184    private static ProgramPage _getClosestProgramPage(Page page)
185    {
186        Page parentPage = page.getParent();
187        while (!(parentPage instanceof ProgramPage))
188        {
189            parentPage = parentPage.getParent();
190        }
191        
192        return (ProgramPage) parentPage;
193    }
194}