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.content;
017
018import java.io.IOException;
019import java.util.ArrayList;
020import java.util.HashMap;
021import java.util.List;
022import java.util.Map;
023
024import org.apache.avalon.framework.parameters.Parameters;
025import org.apache.avalon.framework.service.ServiceException;
026import org.apache.avalon.framework.service.ServiceManager;
027import org.apache.avalon.framework.service.Serviceable;
028import org.apache.cocoon.acting.AbstractAction;
029import org.apache.cocoon.environment.ObjectModelHelper;
030import org.apache.cocoon.environment.Redirector;
031import org.apache.cocoon.environment.Request;
032import org.apache.excalibur.source.Source;
033import org.apache.excalibur.source.SourceResolver;
034
035import org.ametys.cms.contenttype.ContentTypesHelper;
036import org.ametys.cms.repository.Content;
037
038/**
039 * This action export the wrapping XSLT URI.<br>
040 * Content negociation will be performed with the given URI: if content.xsl is asked, content-[contentType].xsl will be looked up first.
041 * 
042 * This action needs the parameter <code>path</code> pointing the default path to the XSL. 
043 */
044public class GetWrapperContextAction extends AbstractAction implements Serviceable
045{
046    /** The source resolver */
047    protected SourceResolver _srcResolver;
048    /** The content types helper */
049    protected ContentTypesHelper _contentTypesHelper;
050    
051    @Override
052    public void service(ServiceManager manager) throws ServiceException
053    {
054        _srcResolver = (SourceResolver) manager.lookup(SourceResolver.ROLE);
055        _contentTypesHelper = (ContentTypesHelper) manager.lookup(ContentTypesHelper.ROLE);
056    }
057    
058    @Override
059    public Map<String, String> act(Redirector redirector, org.apache.cocoon.environment.SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception
060    {
061        Request request = ObjectModelHelper.getRequest(objectModel);
062        
063        HashMap<String, String> result = new HashMap<>();
064        String uri = parameters.getParameter("path");
065        String wrapperURI = getWrapperURI(request, uri);
066        
067        result.put("wrapper-uri", wrapperURI);
068        return result;
069    }
070    
071    /**
072     * Compute the wrapping URI for the current Content.
073     * @param request the current Request.
074     * @param uri the default uri.
075     * @return the wrapper XSLT URI.
076     * @throws IOException if an error occurs whuile resolving Sources.
077     */
078    protected String getWrapperURI(Request request, String uri) throws IOException
079    {
080        for (String wrapperURI : getSourceURIs(request, uri))
081        {
082            Source src = _srcResolver.resolveURI(wrapperURI);
083            if (!src.exists())
084            {
085                if (getLogger().isDebugEnabled())
086                {
087                    getLogger().debug("Failed to find a stylesheet at '" + wrapperURI + "'.");
088                }
089            }
090            else
091            {
092                return wrapperURI;
093            }
094        }
095        
096        return null;
097    }
098    
099    /**
100     * Get the source URI for wrapped content
101     * @param request The request
102     * @param requestedURI The requested URI
103     * @return the wrapped URI
104     */
105    protected List<String> getSourceURIs (Request request, String requestedURI)
106    {
107        Content content = (Content) request.getAttribute(Content.class.getName());
108        
109        List<String> sourceURIs = new ArrayList<>();
110        
111        // Ex: context://WEB-INF/stylesheets/content/_wrapper/content-[cType].xsl 
112        int index = requestedURI.indexOf(".xsl");
113        
114        String cTypeId = _contentTypesHelper.getContentTypeIdForRendering(content);
115        sourceURIs.add("context://WEB-INF/" + requestedURI.substring(0, index) + "-" + cTypeId + ".xsl");
116        
117        cTypeId = _contentTypesHelper.getFirstContentType(content).getId();
118        sourceURIs.add("context://WEB-INF/" + requestedURI.substring(0, index) + "-" + cTypeId + ".xsl");
119        
120        sourceURIs.add("context://WEB-INF/" + requestedURI);
121        
122        sourceURIs.add("workspace:" + request.getAttribute("workspaceName") + "://" + requestedURI);
123        
124        return sourceURIs;
125        
126    }
127}