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&path=%s&basepath=%s&collection=%s&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}