001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package com.sun.rave.web.ui.theme;
042:
043: import java.util.HashMap;
044: import java.util.Iterator;
045: import java.util.Locale;
046: import java.util.Map;
047: import java.util.ResourceBundle;
048:
049: /**
050: * <p>The ThemeManager manages the locale specific
051: * versions of each Theme. The ThemeManager is
052: * created by the ThemeConfigurationListener
053: * and placed in an application parameter
054: * of the same name as the theme itself.<p>
055: * <p>Components do not need to interact
056: * with the ThemeManager directly - use
057: * <code>com.sun.rave.web.ui.util.ThemeUtilities</code>
058: * instead.</p>
059: * <p>To specify a default theme, set it in a context
060: * init parameter in the deployment descriptor. Use
061: * the parameter name <code>com.sun.rave.web.ui.DefaultTheme</code>.
062: * @author avk
063: */
064: public class ThemeManager {
065:
066: /**
067: * The context attribute name used to
068: * place/retrieve the ThemeManager.
069: */
070: public final static String THEME_MANAGER = "com.sun.rave.web.ui.ThemeManager"; //NOI18N
071:
072: private static String defaultTheme = null;
073: private Locale defaultLocale = null;
074: private HashMap themes;
075: private boolean populated = false;
076: private ThemeManager themeManager = null;
077: private static final boolean DEBUG = false;
078: private String messageResource = null;
079:
080: /**
081: * Constructor for the ThemeManager
082: */
083: protected ThemeManager() {
084: themes = new HashMap();
085: }
086:
087: /**
088: * This method adds a named Theme to the ThemeManager.
089: * @param name The name for which this Theme was created
090: * @param themeMap The mapObject of themes
091: */
092: protected void addThemeMap(String name, Map themeMap) {
093: if (DEBUG)
094: log("\tNow adding theme map for " + name);
095: themes.put(name, themeMap);
096: }
097:
098: /**
099: * <p>Retrieve a Theme instance for a Theme and for a specified locale.</p>
100: * <p>If no Theme instances can be found for the specified name, the method
101: * uses the name of the default theme instead. If no default theme has been
102: * specified, any available theme name will be used. If none is found,
103: * a ThemeConfigurationException is thrown.</p>
104: * <p> If no Theme instance can be found for the locale, the default locale
105: * from the <code>faces-config.xml</code> file is used. If no default theme
106: * was specified, any theme instance will be used. If no theme instances
107: * are found, a ThemeConfigurationException is thrown.</p>
108: *
109: * @param name The for which this Theme was created
110: * @param locale The locale for which the Theme instance is needed
111: * @return The Theme for the locale
112: */
113: public Theme getTheme(String name, Locale locale) {
114:
115: // "themes" is a map which manages the individual theme maps.
116: // First see if there is a value for the name specified in the
117: // method parameter. (themes is not null, it is created on
118: // startup).
119:
120: Object mapObject = themes.get(name);
121:
122: // If there is no value, try to find another theme map.
123: if (mapObject == null) {
124:
125: // Check if there are no themes (we don't want to do perform this
126: // test at the start of this method for performance reasons - it is
127: // invoked a lot and this fallback mechanism is only used when there
128: // is a misconfiguration.
129: if (themes.isEmpty()) {
130: String message = "CONFIGURATION ERROR: no theme resources library available";
131: throw new ThemeConfigurationException(message);
132: }
133:
134: log("WARNING: theme " + name + " has not been initialized.");
135:
136: // If a default theme name was specified, try to get the theme map
137: // for the default theme.
138: if (defaultTheme != null) {
139: mapObject = themes.get(defaultTheme);
140: if (mapObject != null) {
141: log("Using the default theme " + defaultTheme);
142: }
143: } else {
144: log("WARNING: no default theme name available either, using any theme!");
145: }
146:
147: if (mapObject == null) {
148: mapObject = themes.values().iterator().next();
149: }
150: }
151:
152: Map themeMap = (Map) mapObject;
153: Theme theme = null;
154: Object object = themeMap.get(locale);
155:
156: if (object == null) {
157: log("No theme instance found for locale "
158: + locale.getDisplayName());
159:
160: if (defaultLocale != null) {
161: log("Trying to use the default locale "
162: + defaultLocale.getDisplayName());
163: object = themeMap.get(defaultLocale);
164: }
165: if (object == null && !themeMap.isEmpty()) {
166: log("Trying to use any theme instance");
167: object = themeMap.values().iterator().next();
168: }
169: if (object == null) {
170: String message = "CONFIGURATION ERROR: no theme resources library available";
171: throw new ThemeConfigurationException(message);
172: }
173: }
174: return (Theme) object;
175: }
176:
177: /**
178: * Use this method to specify the default theme for
179: * the web application
180: * @param name The name of the default Theme
181: */
182: protected void setDefaultThemeName(String name) {
183: if (name != null && name.length() > 0) {
184: defaultTheme = name;
185: }
186: checkDefaultThemeName();
187: }
188:
189: /**
190: * Use this method to specify the default locale for
191: * the web application
192: * @param defaultLocale The defaultLocale
193: */
194: protected void setDefaultLocale(Locale defaultLocale) {
195: this .defaultLocale = defaultLocale;
196: }
197:
198: /**
199: * Use this method to retrieve the name of the default
200: * Theme for the locale.
201: * @return The default Theme's name
202: */
203: public String getDefaultThemeName() {
204: return defaultTheme;
205: }
206:
207: /**
208: * String representation of this class
209: * @return The string representation of this class
210: */
211: public String toString() {
212: StringBuffer buffer = new StringBuffer(
213: "ThemeManager for Sun Web Componenents.");
214: buffer.append("\nDefault theme is ");
215: buffer.append(defaultTheme);
216: buffer.append(".\nAvailable themes: ");
217: Iterator iterator = themes.keySet().iterator();
218: while (iterator.hasNext()) {
219: buffer.append(iterator.next());
220: buffer.append(" ");
221: }
222: buffer.append(".\nAvailable locales: ");
223: iterator = ((Map) (themes.get(defaultTheme))).keySet()
224: .iterator();
225: while (iterator.hasNext()) {
226: buffer.append(iterator.next());
227: buffer.append(" ");
228: }
229: return buffer.toString();
230: }
231:
232: /**
233: * Use this method to check if name is a valid themename
234: * @param name A name
235: * @return true if the manager has a theme of the name, false otherwise
236: */
237: private void checkDefaultThemeName() {
238: boolean warn = false;
239: if (defaultTheme != null) {
240: if (themes.containsKey(defaultTheme)) {
241: return;
242: } else {
243: warn = true;
244: log("WARNING: default theme name " + defaultTheme
245: + " is invalid");
246: }
247: }
248:
249: Iterator keys = themes.keySet().iterator();
250: if (keys.hasNext()) {
251: defaultTheme = keys.next().toString();
252: }
253:
254: if (warn) {
255: log("Using defaultTheme " + defaultTheme + "instead");
256:
257: }
258: }
259:
260: private void log(String s) {
261: System.out.println(this .getClass().getName() + "::" + s);
262: }
263: }
|