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