001/*
002 * (C) Copyright 2006-2007 Nuxeo SA (http://nuxeo.com/) and others.
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 *
016 * Contributors:
017 *     Jean-Marc Orliaguet, Chalmers
018 *
019 * $Id$
020 */
021
022package org.nuxeo.theme.html.ui;
023
024import java.util.Date;
025import java.util.Map;
026
027import org.apache.commons.logging.Log;
028import org.apache.commons.logging.LogFactory;
029import org.nuxeo.ecm.platform.web.common.vh.VirtualHostHelper;
030import org.nuxeo.theme.Manager;
031import org.nuxeo.theme.formats.styles.Style;
032import org.nuxeo.theme.html.CSSUtils;
033import org.nuxeo.theme.themes.ThemeDescriptor;
034import org.nuxeo.theme.themes.ThemeManager;
035
036public class ThemeStyles {
037    private static final Log log = LogFactory.getLog(ThemeStyles.class);
038
039    private static final boolean IGNORE_VIEW_NAME = false;
040
041    private static final boolean IGNORE_CLASSNAME = false;
042
043    private static final boolean INDENT = false;
044
045    public static String render(Map<String, String> params, boolean cache, boolean inline, boolean virtualHosting) {
046        String themeName = params.get("themeName");
047        String path = params.get("path");
048        String basePath = params.get("basepath");
049        String collectionName = params.get("collection");
050
051        String cssPath = VirtualHostHelper.getContextPathProperty() + "/nxthemes-css";
052
053        // Load theme if needed
054        ThemeDescriptor themeDescriptor = ThemeManager.getThemeDescriptorByThemeName(themeName);
055        if (themeDescriptor == null) {
056            log.warn(String.format("Could not resolve theme descriptor for name '%s'", themeName));
057        }
058        if (themeDescriptor != null && !themeDescriptor.isLoaded()) {
059            ThemeManager.loadTheme(themeDescriptor);
060        }
061
062        if (inline) {
063            boolean includeDate = true;
064            String includeDateParam = params.get("includeDate");
065            if (includeDateParam != null) {
066                includeDate = Boolean.TRUE.equals(includeDateParam);
067            }
068            return String.format("<style type=\"text/css\">\n%s\n</style>",
069                    generateThemeStyles(themeName, themeDescriptor, basePath, collectionName, includeDate));
070        }
071
072        long timestamp = 0;
073        if (cache) {
074            if (themeDescriptor != null) {
075                timestamp = themeDescriptor.getLastModified().getTime();
076            }
077            Long lastModifiedOnService = Manager.getThemeManager().getLastModified(themeName);
078            if (lastModifiedOnService != null) {
079                long lastModifiedOnServiceVal = lastModifiedOnService.longValue();
080                if (lastModifiedOnServiceVal > timestamp) {
081                    timestamp = lastModifiedOnServiceVal;
082                }
083            }
084        } else {
085            timestamp = new Date().getTime();
086        }
087        return String.format(
088                "<link rel=\"stylesheet\" type=\"text/css\" media=\"all\" href=\"%s/%s-styles.css?theme=%s&amp;path=%s&amp;basepath=%s&amp;collection=%s&amp;timestamp=%s\" />",
089                cssPath, themeName, themeName, path, basePath, collectionName, Long.valueOf(timestamp));
090    }
091
092    public static String generateThemeStyles(String themeName, ThemeDescriptor themeDescriptor, String basePath,
093            String collectionName, boolean includeDate) {
094
095        final StringBuilder sb = new StringBuilder();
096
097        final ThemeManager themeManager = Manager.getThemeManager();
098        // Named styles sorted to preserve dependencies in CSS
099        for (Style style : themeManager.getSortedNamedStyles(themeName)) {
100            sb.insert(
101                    0,
102                    CSSUtils.styleToCss(style, style.getSelectorViewNames(), IGNORE_VIEW_NAME, IGNORE_CLASSNAME, INDENT));
103            sb.insert(0, String.format("\n\n/* CSS styles named '%s' */\n", style.getName()));
104        }
105
106        // add generation comment on top of file
107        if (includeDate) {
108            sb.insert(0, String.format("/* CSS styles for theme '%s' (%s) */\n", themeName, new Date()));
109        } else {
110            sb.insert(0, String.format("/* CSS styles for theme '%s' */\n", themeName));
111        }
112
113        // Local theme styles
114        for (Style style : themeManager.getStyles(themeName)) {
115            sb.append(CSSUtils.styleToCss(style, style.getSelectorViewNames(), IGNORE_VIEW_NAME, IGNORE_CLASSNAME,
116                    INDENT));
117        }
118
119        final String collectionCssMarker = ThemeManager.getCollectionCssMarker();
120        String rendered = sb.toString();
121        if (collectionName != null) {
122            // Preprocessing: replace the collection name
123            rendered = rendered.replaceAll(collectionCssMarker, collectionName);
124        }
125        rendered = CSSUtils.expandVariables(rendered, basePath, collectionName, themeDescriptor);
126        return rendered;
127    }
128}