001/*
002 * (C) Copyright 2006-2007 Nuxeo SAS <http://nuxeo.com> and others
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the Eclipse Public License v1.0
006 * which accompanies this distribution, and is available at
007 * http://www.eclipse.org/legal/epl-v10.html
008 *
009 * Contributors:
010 *     Jean-Marc Orliaguet, Chalmers
011 *
012 * $Id$
013 */
014
015package org.nuxeo.theme.formats;
016
017import java.net.URL;
018
019import org.apache.commons.logging.Log;
020import org.apache.commons.logging.LogFactory;
021import org.nuxeo.theme.Manager;
022import org.nuxeo.theme.elements.Element;
023import org.nuxeo.theme.elements.ElementType;
024import org.nuxeo.theme.engines.EngineType;
025import org.nuxeo.theme.fragments.Fragment;
026import org.nuxeo.theme.models.Model;
027import org.nuxeo.theme.models.ModelType;
028import org.nuxeo.theme.rendering.AbstractFilter;
029import org.nuxeo.theme.rendering.FilterTypeFamily;
030import org.nuxeo.theme.rendering.RenderingInfo;
031import org.nuxeo.theme.resources.ResourceManager;
032import org.nuxeo.theme.templates.TemplateEngineType;
033import org.nuxeo.theme.types.TypeFamily;
034import org.nuxeo.theme.types.TypeRegistry;
035import org.nuxeo.theme.views.View;
036import org.nuxeo.theme.views.ViewType;
037
038public class FormatFilter extends AbstractFilter {
039
040    private static final Log log = LogFactory.getLog(FormatFilter.class);
041
042    private FormatType formatType;
043
044    public FormatFilter() {
045    }
046
047    public FilterTypeFamily getFilterTypeFamily() {
048        return FilterTypeFamily.FORMAT;
049    }
050
051    public FormatType getFormatType() {
052        return formatType;
053    }
054
055    public void setFormatType(final FormatType formatType) {
056        this.formatType = formatType;
057    }
058
059    @Override
060    public RenderingInfo process(final RenderingInfo info, final boolean cache) {
061        final EngineType engine = info.getEngine();
062        final TemplateEngineType templateEngineType = info.getTemplateEngine();
063        final String viewMode = info.getViewMode();
064        final Element element = info.getElement();
065        final ElementType elementType = element.getElementType();
066
067        final Model model = info.getModel();
068        final ModelType modelType = model == null ? null : model.getModelType();
069
070        final Format format = info.getFormat();
071
072        // look for a view by model type and by view name
073        final View view = getView(format.getName(), engine, viewMode, elementType, modelType, formatType,
074                templateEngineType);
075
076        if (view == null) {
077            // Sanity check
078            if (model == null) {
079                if (element instanceof Fragment) {
080                    Fragment fragment = (Fragment) element;
081                    ModelType expectedModelType = fragment.getFragmentType().getModelType();
082                    if (expectedModelType != null) {
083                        log.warn(String.format("Fragment %s should have returned a model of type: %s",
084                                fragment.computeXPath(), expectedModelType.getTypeName()));
085                    }
086                }
087            } else {
088                log.warn(String.format("No %s view named '%s' found for element %s (theme URL is: %s)",
089                        formatType.getTypeName(), format.getName(), element.computeXPath(),
090                        info.getThemeUrl().toString()));
091            }
092        } else {
093
094            final String markup = view.render(info);
095            info.setMarkup(markup);
096
097            // Add resources used by the view (.css, .js, ...)
098            final URL themeUrl = info.getThemeUrl();
099            final ResourceManager resourceManager = Manager.getResourceManager();
100            for (String resource : view.getViewType().getResources()) {
101                resourceManager.addResource(resource, themeUrl);
102            }
103        }
104        return info;
105    }
106
107    private View getView(final String viewName, final EngineType engine, final String viewMode,
108            final ElementType elementType, final ModelType modelType, final FormatType formatType,
109            final TemplateEngineType templateEngineType) {
110
111        // allow to fall back on no specific view name
112        final String effectiveViewName = (viewName == null || viewName.equals("")) ? "*" : viewName;
113        final String effectiveViewMode = viewMode == null ? "*" : viewMode;
114        final String engineName = engine == null ? "default" : engine.getName();
115        final String templateEngineName = templateEngineType == null ? null : templateEngineType.getName();
116
117        final String elementTypeName = elementType == null ? "*" : elementType.getTypeName();
118        final String modelTypeName = modelType == null ? "*" : modelType.getTypeName();
119        final String formatTypeName = formatType == null ? "*" : formatType.getTypeName();
120
121        View view = getViewFor(formatTypeName, elementTypeName, effectiveViewName, modelTypeName, engineName,
122                effectiveViewMode, templateEngineName);
123
124        // fall back to unspecified element type
125        if (view == null && !"*".equals(elementTypeName)) {
126            view = getViewFor(formatTypeName, "*", effectiveViewName, modelTypeName, engineName, effectiveViewMode,
127                    templateEngineName);
128        }
129
130        // fall back to unspecified model type
131        if (view == null && !"*".equals(modelTypeName)) {
132            view = getViewFor(formatTypeName, elementTypeName, effectiveViewName, "*", engineName, effectiveViewMode,
133                    templateEngineName);
134        }
135
136        // fall back to unspecified element and model type
137        if (view == null && !"*".equals(elementTypeName) && !"*".equals(modelTypeName)) {
138            view = getViewFor(formatTypeName, "*", effectiveViewName, "*", engineName, effectiveViewMode,
139                    templateEngineName);
140        }
141
142        // fall back to unspecified view name and unspecified model type
143        if (view == null && !"*".equals(effectiveViewName)) {
144            view = getViewFor(formatTypeName, elementTypeName, "*", "*", engineName, effectiveViewMode,
145                    templateEngineName);
146        }
147        return view;
148    }
149
150    private View getViewFor(final String formatTypeName, final String elementTypeName, final String viewName,
151            final String modelTypeName, final String engineName, final String viewMode, final String templateEngineName) {
152
153        TypeRegistry typeRegistry = Manager.getTypeRegistry();
154
155        ViewType viewType = (ViewType) typeRegistry.lookup(TypeFamily.VIEW, ViewType.computeName(formatTypeName,
156                elementTypeName, viewName, modelTypeName, engineName, viewMode, templateEngineName));
157
158        // Any view mode
159        if (viewType == null && !"*".equals(viewMode)) {
160            viewType = (ViewType) typeRegistry.lookup(TypeFamily.VIEW, ViewType.computeName(formatTypeName,
161                    elementTypeName, viewName, modelTypeName, engineName, "*", templateEngineName));
162        }
163
164        // Any view mode, default engine
165        if (viewType == null && !"default".equals(engineName)) {
166            viewType = (ViewType) typeRegistry.lookup(TypeFamily.VIEW, ViewType.computeName(formatTypeName,
167                    elementTypeName, viewName, modelTypeName, "default", "*", templateEngineName));
168        }
169
170        return viewType == null ? null : viewType.getView();
171    }
172}