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.cms.source;
017
018import java.io.IOException;
019import java.util.ArrayList;
020import java.util.List;
021
022import org.apache.avalon.framework.logger.AbstractLogEnabled;
023import org.apache.avalon.framework.service.ServiceException;
024import org.apache.avalon.framework.service.ServiceManager;
025import org.apache.avalon.framework.service.Serviceable;
026import org.apache.excalibur.source.Source;
027import org.apache.excalibur.source.SourceResolver;
028
029import org.ametys.cms.contenttype.ContentTypesHelper;
030
031/**
032 * Default implementation of a {@link ContentView}
033 * Will first look in directory context://WEB-INF/stylesheets/content/article/article-[view].xsl
034 * And if the file does not exist will search in plugin:[currentPluginName]://stylesheets/content/article/article-[view].xsl
035 */
036public class DefaultContentView extends AbstractLogEnabled implements ContentView, Serviceable
037{
038    /** The source resolver */
039    protected SourceResolver _resolver;
040    /** Helper for content types */
041    protected ContentTypesHelper _contentTypesHelper;
042    
043    @Override
044    public void service(ServiceManager manager) throws ServiceException
045    {
046        _resolver = (SourceResolver) manager.lookup(SourceResolver.ROLE);
047        _contentTypesHelper = (ContentTypesHelper) manager.lookup(ContentTypesHelper.ROLE);
048    }
049    
050    @Override
051    public Source getSource(String location, String contentType, String view, String format, String pluginName) throws IOException
052    {
053        for (String s : _getSourceURIs(location, contentType, view, format, pluginName))
054        {
055            try
056            {
057                Source src = _resolver.resolveURI(s);
058                if (!src.exists())
059                {
060                    if (getLogger().isDebugEnabled())
061                    {
062                        getLogger().debug("Failed to find a stylesheet at '" + s + "'.");
063                    }
064                }
065                else
066                {
067                    return src;
068                }
069            }
070            catch (IOException e)
071            {
072                if (getLogger().isDebugEnabled())
073                {
074                    getLogger().debug("Resolving protocol failed for resolving '" + s + "'.");
075                }
076            }
077        }
078        
079        // should never occur because of the default stylesheet
080        throw new IOException("Can't find a stylesheet for: " + location);
081    }
082    
083    /**
084     * Returns the ordered list of URI to be tested to find a stylesheet to render the Content.
085     * @param location the requested location
086     * @param contentType the content type for rendering
087     * @param view the content view
088     * @param format the format of the output (html, pdf, ...)
089     * @param pluginName the plugin name
090     * @return a list of URIs
091     */
092    protected List<String> _getSourceURIs(String location, String contentType, String view, String format, String pluginName)
093    {
094        String f = "html".equals(format) ? "" : "2" + format;
095        
096        ArrayList<String> result = new ArrayList<>();
097        
098        // first look in the filesystem (case of automatic content types)
099        result.add("context://WEB-INF/param/content-types/_dynamic/" + pluginName + "/stylesheets/" + contentType + "/" + contentType + f + "-" + view + ".xsl");
100        result.add("context://WEB-INF/param/content-types/_dynamic/" + pluginName + "/stylesheets/" + contentType + "/" + contentType + f + ".xsl");
101        
102        result.add("context://WEB-INF/param/content-types/" + pluginName + "/stylesheets/" + contentType + "/" + contentType + f + "-" + view + ".xsl");
103        result.add("context://WEB-INF/param/content-types/" + pluginName + "/stylesheets/" + contentType + "/" + contentType + f + ".xsl");
104        
105        // then look in the plugin
106        result.add("plugin:" + pluginName + "://stylesheets/content/" + contentType + "/" + contentType + f + "-" + view + ".xsl");
107        result.add("plugin:" + pluginName + "://stylesheets/content/" + contentType + "/" + contentType + f + ".xsl");
108        
109        // then a default stylesheet
110        result.add("plugin:" + pluginName + "://stylesheets/default-content" + f + ".xsl");
111        result.add("plugin:cms://stylesheets/default-content" + f + ".xsl");
112        
113        return result;
114    }
115}