You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by jw...@apache.org on 2007/07/30 23:14:32 UTC
svn commit: r561122 - in /myfaces/trinidad/trunk/trinidad:
trinidad-api/src/main/java/org/apache/myfaces/trinidad/skin/
trinidad-examples/trinidad-demo/src/main/java/org/apache/myfaces/trinidaddemo/resource/
trinidad-impl/src/main/java/org/apache/myfac...
Author: jwaldman
Date: Mon Jul 30 14:14:30 2007
New Revision: 561122
URL: http://svn.apache.org/viewvc?view=rev&rev=561122
Log:
TRINIDAD-105 enable registerResourceBundle to any skin
(on trunk)
1. added the bundle-name api for skin-additions in trinidad-skins.xml
2. added SkinAddition class and addSkinAddition and getSkinAdditions for Skin
3. Check in resource bundles from the skin-additions as well as the Skin's resource bundle for translatedValue's key.
Added:
myfaces/trinidad/trunk/trinidad/trinidad-api/src/main/java/org/apache/myfaces/trinidad/skin/SkinAddition.java
myfaces/trinidad/trunk/trinidad/trinidad-examples/trinidad-demo/src/main/java/org/apache/myfaces/trinidaddemo/resource/SkinBundle_fr.java
Modified:
myfaces/trinidad/trunk/trinidad/trinidad-api/src/main/java/org/apache/myfaces/trinidad/skin/Skin.java
myfaces/trinidad/trunk/trinidad/trinidad-examples/trinidad-demo/src/main/java/org/apache/myfaces/trinidaddemo/resource/SkinBundle.java
myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinExtension.java
myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinImpl.java
myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinUtils.java
myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/ui/laf/xml/parse/SkinAdditionNode.java
myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/ui/laf/xml/parse/SkinAdditionNodeParser.java
Modified: myfaces/trinidad/trunk/trinidad/trinidad-api/src/main/java/org/apache/myfaces/trinidad/skin/Skin.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad/trinidad-api/src/main/java/org/apache/myfaces/trinidad/skin/Skin.java?view=diff&rev=561122&r1=561121&r2=561122
==============================================================================
--- myfaces/trinidad/trunk/trinidad/trinidad-api/src/main/java/org/apache/myfaces/trinidad/skin/Skin.java (original)
+++ myfaces/trinidad/trunk/trinidad/trinidad-api/src/main/java/org/apache/myfaces/trinidad/skin/Skin.java Mon Jul 30 14:14:30 2007
@@ -18,6 +18,7 @@
*/
package org.apache.myfaces.trinidad.skin;
+import java.util.List;
import java.util.Map;
import java.util.MissingResourceException;
@@ -72,7 +73,7 @@
abstract public Map<String, String> getStyleClassMap(RenderingContext arc);
/**
- * Returns the name of the XSS style sheet for this Skin.
+ * Returns the name of the style sheet for this Skin.
*/
abstract public String getStyleSheetName();
@@ -141,7 +142,7 @@
abstract public void registerIcon(
String iconName,
Icon icon);
-
+
/**
* Registers a style sheet which defines extension-specific
* styles. The styles specified by this style sheet will be
@@ -149,8 +150,40 @@
* @param styleSheetName The name of the style sheet which
* defines the extension's styles.
* @throws NullPointerException if styleSheetName is null.
+ * @deprecated Use addSkinAddition(SkinAddition) instead.
+ * @see #addSkinAddition(SkinAddition)
*/
abstract public void registerStyleSheet(
String styleSheetName
);
+
+ /**
+ * Adds a SkinAddition on this Skin. You can call this method as many times
+ * as you like for the Skin, and it will add the SkinAddition to the list of
+ * SkinAdditions.
+ * However, it does not make sense to call this method more than once
+ * with the same SkinAddition object.
+ * This is meant for the skin-addition use-cases, where a custom component
+ * developer has a style sheet and/or resource bundle for their custom
+ * components, and they want the style sheet and/or resource bundle
+ * to work for this Skin and the children Skins.
+ * The stylesheets specified in the SkinAdditions will be merged with the
+ * Skin's own styles.
+ * The resource bundles specified in the SkinAdditions will be looked into
+ * if the translated key is not found in the Skin's own resource bundle
+ * during the call to getTranslatedString or getTranslatedValue.
+ *
+ * @param skinAddition The SkinAddition object to add to the Skin.
+ * @throws NullPointerException if SkinAddition is null.
+ */
+ abstract public void addSkinAddition (
+ SkinAddition skinAddition
+ );
+
+ /**
+ * Gets a List of SkinAdditions that have been added on this Skin.
+ * @return List a List of SkinAdditions.
+ */
+ abstract public List<SkinAddition> getSkinAdditions ();
+
}
Added: myfaces/trinidad/trunk/trinidad/trinidad-api/src/main/java/org/apache/myfaces/trinidad/skin/SkinAddition.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad/trinidad-api/src/main/java/org/apache/myfaces/trinidad/skin/SkinAddition.java?view=auto&rev=561122
==============================================================================
--- myfaces/trinidad/trunk/trinidad/trinidad-api/src/main/java/org/apache/myfaces/trinidad/skin/SkinAddition.java (added)
+++ myfaces/trinidad/trunk/trinidad/trinidad-api/src/main/java/org/apache/myfaces/trinidad/skin/SkinAddition.java Mon Jul 30 14:14:30 2007
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.trinidad.skin;
+
+import java.util.Collections;
+
+import org.apache.myfaces.trinidad.context.LocaleContext;
+
+/**
+ * SkinAdditions are defined in trinidad-skins.xml file <skin-addition>
+ * They are used by custom component developers who have created custom
+ * components, and they need a way to 'push' in their own stylesheet and
+ * resource bundle for these components into some skin of their choosing,
+ * most likely the simple skin.
+ * Skin objects contain zero or more SkinAdditions. The SkinAdditions' stylesheets
+ * are merged into the Skin's own stylesheet. The SkinAdditions' resource
+ * bundle is looked at along with the Skin's own resource bundle when Skin's
+ * getTranslatedValue is called.
+ *
+ */
+public class SkinAddition
+{
+
+
+ /**
+ * Constructor takes a styleSheet name and a resourceBundle name.
+ */
+ public SkinAddition (
+ String styleSheetName,
+ String resourceBundleName
+ )
+ {
+ _styleSheetName = styleSheetName;
+ _resourceBundleName = resourceBundleName;
+ }
+
+ /**
+ * Gets the SkinAddition's style sheet name.
+ */
+ public String getStyleSheetName()
+ {
+ return _styleSheetName;
+ }
+
+ /**
+ * Gets the SkinAddition's resource bundle .
+ */
+ public String getResourceBundleName()
+ {
+ return _resourceBundleName;
+ }
+
+ private final String _styleSheetName;
+ private final String _resourceBundleName;
+
+}
Modified: myfaces/trinidad/trunk/trinidad/trinidad-examples/trinidad-demo/src/main/java/org/apache/myfaces/trinidaddemo/resource/SkinBundle.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad/trinidad-examples/trinidad-demo/src/main/java/org/apache/myfaces/trinidaddemo/resource/SkinBundle.java?view=diff&rev=561122&r1=561121&r2=561122
==============================================================================
--- myfaces/trinidad/trunk/trinidad/trinidad-examples/trinidad-demo/src/main/java/org/apache/myfaces/trinidaddemo/resource/SkinBundle.java (original)
+++ myfaces/trinidad/trunk/trinidad/trinidad-examples/trinidad-demo/src/main/java/org/apache/myfaces/trinidaddemo/resource/SkinBundle.java Mon Jul 30 14:14:30 2007
@@ -32,6 +32,11 @@
{
{"af_tableSelectMany.SELECT_COLUMN_HEADER", "Select A Lot"},
{"af_tableSelectOne.SELECT_COLUMN_HEADER", "Select Just One"},
+ {"af_inputDate.LAUNCH_PICKER_TIP", "Purple Launch Picker"},
+ {"Birds.SELECT_MANY", "Purple Default Select Many"},
};
}
+
+
+
Added: myfaces/trinidad/trunk/trinidad/trinidad-examples/trinidad-demo/src/main/java/org/apache/myfaces/trinidaddemo/resource/SkinBundle_fr.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad/trinidad-examples/trinidad-demo/src/main/java/org/apache/myfaces/trinidaddemo/resource/SkinBundle_fr.java?view=auto&rev=561122
==============================================================================
--- myfaces/trinidad/trunk/trinidad/trinidad-examples/trinidad-demo/src/main/java/org/apache/myfaces/trinidaddemo/resource/SkinBundle_fr.java (added)
+++ myfaces/trinidad/trunk/trinidad/trinidad-examples/trinidad-demo/src/main/java/org/apache/myfaces/trinidaddemo/resource/SkinBundle_fr.java Mon Jul 30 14:14:30 2007
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.trinidaddemo.resource;
+
+import java.util.ListResourceBundle;
+
+public class SkinBundle_fr extends ListResourceBundle
+{
+ @Override
+ public Object[][] getContents()
+ {
+ return _CONTENTS;
+ }
+
+ static private final Object[][] _CONTENTS =
+ {
+ {"af_tableSelectMany.SELECT_COLUMN_HEADER", "Select A Lot"},
+ {"af_tableSelectOne.SELECT_COLUMN_HEADER", "Select Just One"},
+ {"af_inputDate.LAUNCH_PICKER_TIP", "French Purple Launch Picker"},
+ {"Birds.SELECT_MANY", "Purple French Select Many"},
+ };
+}
+
Modified: myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinExtension.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinExtension.java?view=diff&rev=561122&r1=561121&r2=561122
==============================================================================
--- myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinExtension.java (original)
+++ myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinExtension.java Mon Jul 30 14:14:30 2007
@@ -19,15 +19,9 @@
package org.apache.myfaces.trinidadinternal.skin;
import java.io.IOException;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
-import java.util.ResourceBundle;
import java.util.Stack;
-import java.util.concurrent.ConcurrentHashMap;
import javax.faces.context.FacesContext;
import org.apache.myfaces.trinidad.logging.TrinidadLogger;
@@ -72,14 +66,19 @@
* and render-kit-id match will be chosen.
* Must be non-null.
* @param renderKitId The render-kit-id that this Skin is designed for.
+ * @param styleSheetName The name of the stylesheet for this Skin.
+ * @param resourceBundleName The name of the resource bundle for this Skin.
+
* @throws NullPointerException if baseSkin, id, or family is null.
- *
+ *
*/
public SkinExtension(
Skin baseSkin,
String id,
String family,
- String renderKitId
+ String renderKitId,
+ String styleSheetName,
+ String resourceBundleName
)
{
if (baseSkin == null)
@@ -96,6 +95,45 @@
_id = id;
_family = family;
_renderKitId = renderKitId;
+ _styleSheetName = styleSheetName;
+ _bundleName = resourceBundleName;
+ }
+
+ /**
+ * Creates a Skin which extends the specified base
+ * Skin.
+ *
+ * @param baseSkin The base Skin that this custom
+ * Skin "extends". If it is a Skin designed for "org.apache.myfaces.trinidad.desktop"
+ * render-kit-id, then its base skin should be SimpleDesktopSkin.
+ * If it is a Skin designed for "org.apache.myfaces.trinidad.pda" render-kit-id,
+ * then its base skin should be SimplePdaSkin.
+ * Must be non-null.
+ * @param id A string which can be used to uniquely identify the
+ * Skin .
+ * Must be non-null.
+ * @param family The Skin family name that this
+ * SkinExtension belongs to. For example, you might have
+ * a Skin that makes your pages look purple for the
+ * desktop renderkit and a Skin that makes your pages
+ * look purple for the pda renderkit.
+ * You can set the skin-family to "purple" in
+ * trinidad-config.xml, and the Skin with skin-family
+ * and render-kit-id match will be chosen.
+ * Must be non-null.
+ * @param renderKitId The render-kit-id that this Skin is designed for.
+ * @throws NullPointerException if baseSkin, id, or family is null.
+ * @deprecated Use the constructor that also contains styleSheetName and resourceBundleName
+ *
+ */
+ public SkinExtension(
+ Skin baseSkin,
+ String id,
+ String family,
+ String renderKitId
+ )
+ {
+ this(baseSkin, id, family, renderKitId, null, null);
}
@@ -129,9 +167,9 @@
}
/**
- * Returns the name of the XSS style sheet for this Skin if
- * on has been set
- * @see setStyleSheetName
+ * Returns the name of the style sheet for this Skin if
+ * one has been set
+ * @see #setStyleSheetName(String)
*/
@Override
public String getStyleSheetName()
@@ -150,21 +188,22 @@
/**
- * Returns the name of the bundle for the extension.
+ * Returns the name of the bundle for the SkinExtension.
*/
@Override
public String getBundleName()
{
- if (_bundleName != null)
- return _bundleName;
- return _baseSkin.getBundleName();
+ return _bundleName;
}
/**
- * Returns the name of the bundle for the extension.
+ * Returns the name of the bundle for this SkinExtension.
+ * @deprecated Use the constructor that takes a resourceBundleName instead.
*/
public void setBundleName(String bundleName)
{
+ // TODO take out method once sufficient time has past since deprecation
+ // in July, 2007
_bundleName = bundleName;
}
@@ -197,72 +236,30 @@
return _baseSkin.getStyleClassMap(arc);
}
+
+
/**
- * Override of Skin.getTranslatedValue() which
- * supports pulling translations from component providers
- * as well as the base Skin.
- */
+ * Override of Skin.getTranslatedValue() which
+ * supports pulling translations from Skin and if not found from the base Skin.
+ */
@Override
public Object getTranslatedValue(
LocaleContext lContext,
String key
) throws MissingResourceException
{
- // Short-circuit when there is no customized translation
- if (_bundleName == null)
- {
+ // Look for the skin's translated value (first bundle name, then registered bundles)
+ // if that's not found, then look in the base skin's translated value.
+ // getCachedTranslatedValue will protect against MissingResourceExceptions
+ Object translatedValue = super.getCachedTranslatedValue(lContext, key);
+ // TODO Cache base skin's non-null translatedValue with this skin to
+ // make it faster.
+ if (translatedValue == null)
return getBaseSkin().getTranslatedValue(lContext, key);
- }
-
- // First, check the local translations cache
- Object value = _getCachedTranslatedValue(lContext, key);
- if (value != null)
- {
- // testTranslationKey(key);//jmw test for testing translation keys
- if (value == _NULL_TRANSLATION)
- return null;
-
- return value;
- }
-
- // Next, check to see if we can get a translation from
- // a bundle that has been explicitly registered on this
- // SkinExtension instance. (We can just use
- // Skin.getTranslatedValue() for this.)
- // Note: In order to avoid MissingResourceExceptions, we
- // first check to see if the translation key is available
- // before looking up the message in the ResourceBundle.
- if (_isTranslationKeyAvailable(lContext, key))
- {
- try
- {
- value = super.getTranslatedValue(lContext, key);
- }
- catch (MissingResourceException e)
- {
- // It is possible that the call to getBundle() might
- // fail with a MissingResourceException if the customer
- // has only provided a custom bundle for certain languages.
- // This is okay, so we just eat these exceptions.
- ;
- }
- }
-
- // If we didn't find a value in the local bundle, try getting
- // the translation from the base Skin.
- if (value == null)
- {
- Skin baseSkin = getBaseSkin();
- value = baseSkin.getTranslatedValue(lContext, key);
- }
-
- // If we found an translation, store it in the cache so that
- // we don't have to search for it again next time.
- _putCachedTranslatedValue(lContext, key, value);
-
- return value;
+ else
+ return translatedValue;
}
-
+
/**
* Try to pull a locally set property, if null
* pull a property from the base skin.
@@ -357,6 +354,7 @@
/**
* Sets the name of the style sheet for this Skin.
+ * @deprecated Use the SkinExtension constructor that takes a styleSheetName instead.
*/
public void setStyleSheetName(String styleSheetName)
{
@@ -407,133 +405,6 @@
}
}
-
- // Gets the translated value from the local translations cache.
- private Object _getCachedTranslatedValue(
- LocaleContext lContext,
- String key
- )
- {
- // Get the translation Locale
- Locale locale = lContext.getTranslationLocale();
-
- // Get all of the translations for the current translation Locale
- Map<String, Object> localeTranslations = _translations.get(locale);
-
- if (localeTranslations != null)
- return localeTranslations.get(key);
-
- return null;
- }
-
- // Stores the translated value in the local translations cache
- // Note the synchronization! This is necessary because we may be
- // putting translations into the cache from multiple request threads.
- synchronized private void _putCachedTranslatedValue(
- LocaleContext lContext,
- String key,
- Object value
- )
- {
- // Use a placeholder to mark null translations
- if (value == null)
- value = _NULL_TRANSLATION;
-
- // Get the translation Locale
- Locale locale = lContext.getTranslationLocale();
-
- // Get all of the translations for the current translation locale
- Map<String, Object> localeTranslations = _translations.get(locale);
-
- if (localeTranslations == null)
- {
- // If we didn't previously have any translations for this
- // Locale, create storage for translations now...
- localeTranslations = new ConcurrentHashMap<String, Object>();
- _translations.put(locale, localeTranslations);
- }
-
- // Store the new component translations array
- localeTranslations.put(key, value);
- }
-
- // Checks whether there is a translation with the specified
- // key in the custom ResourceBundle. We call this method
- // before calling ResourceBundle.getObject() because custom
- // bundles are not required to provide translations for all
- // messages. If we didn't first check _isTranslationKeyAvailable(),
- // we might see a lot of MissingResourceExceptions.
- private boolean _isTranslationKeyAvailable(
- LocaleContext lContext,
- String key
- )
- {
- String bundleName = getBundleName();
- if (bundleName == null)
- return false;
-
- Map<String, Boolean> keys = _getTranslationKeys(lContext);
-
- return keys.containsKey(key);
- }
-
- // Returns the a Map which contains the translation keys for
- // the specified locale.
- @SuppressWarnings("unchecked")
- private Map<String, Boolean> _getTranslationKeys(
- LocaleContext lContext
- )
- {
- // We store the translation keys map in the translation cache
- Map<String, Boolean> keys =
- (Map<String, Boolean>)_getCachedTranslatedValue(lContext,
- _TRANSLATION_KEYS_KEY);
-
- if (keys == null)
- {
- String bundleName = getBundleName();
- assert bundleName != null;
-
- keys = new HashMap<String, Boolean>();
-
- ResourceBundle bundle = null;
-
- try
- {
- bundle = lContext.getBundle(bundleName);
- }
- catch (MissingResourceException e)
- {
- // It is possible that the call to getBundle() might
- // fail with a MissingResourceException if the customer
- // has only provided a custom bundle for certain languages.
- // This is okay, so we just eat these exceptions.
- ;
- }
-
- if (bundle != null)
- {
- Enumeration<String> en = bundle.getKeys();
-
- if (en != null)
- {
- while (en.hasMoreElements())
- keys.put(en.nextElement(), Boolean.TRUE);
- }
- }
-
- if (keys.isEmpty())
- keys = Collections.emptyMap();
- else
- keys = Collections.unmodifiableMap(keys);
-
- _putCachedTranslatedValue(lContext,
- _TRANSLATION_KEYS_KEY,
- keys);
- }
-
- return keys;
- }
/**
* Find the actual icon
* @param refIcon a ReferenceIcon instance
@@ -636,21 +507,7 @@
private String _styleSheetName;
private String _bundleName;
- // Now that we look into possibly multiple ResourceBundles
- // to find a translation (eg. the local bundle, a component
- // provider's bundle, the super-LAFs bundle), translation lookups
- // can become expensive. So, we keep a local cache all translated
- // resources which is populated as we go along. Translations are
- // hashed by Locale/component name/key. This is more
- // hashing than usual to get a translation, but at least this is
- // a finite/fixed expense. At least this way translation lookup
- // performance won't degrade if a custom bundle is provided - or
- // if we need to pull the translation from some other Skin.
- //
- // This HashMap hashes Locales -> HashMaps.
- // The HashMaps map translation key to message.
- private ConcurrentHashMap<Locale, Map<String, Object>> _translations =
- new ConcurrentHashMap<Locale, Map<String, Object>>(13);
+
// The StyleSheetDocument for the base LookAndFeel's style sheet
private StyleSheetDocument _baseStyleSheetDocument;
@@ -663,15 +520,8 @@
// the SkinExtension.
private StyleSheetDocument _fullStyleSheetDocument;
- // Special key that we use for storing the translation keys
- // in the translation cache.
- private static final String _TRANSLATION_KEYS_KEY = "_uixLafTransKeys";
-
// Placeholder for null icons
private static final Icon _NULL_ICON = new NullIcon();
-
- // Placeholder for null translations
- private static final Object _NULL_TRANSLATION = new Object();
// Error messages
private static final String _CIRCULAR_INCLUDE_ERROR =
Modified: myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinImpl.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinImpl.java?view=diff&rev=561122&r1=561121&r2=561122
==============================================================================
--- myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinImpl.java (original)
+++ myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinImpl.java Mon Jul 30 14:14:30 2007
@@ -19,14 +19,20 @@
package org.apache.myfaces.trinidadinternal.skin;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
+import java.util.ResourceBundle;
import java.util.Stack;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
@@ -37,6 +43,7 @@
import org.apache.myfaces.trinidad.skin.Icon;
import org.apache.myfaces.trinidad.skin.Skin;
+import org.apache.myfaces.trinidad.skin.SkinAddition;
import org.apache.myfaces.trinidadinternal.renderkit.core.CoreRenderingContext;
import org.apache.myfaces.trinidadinternal.renderkit.core.xhtml.SkinProperties;
import org.apache.myfaces.trinidadinternal.share.config.Configuration;
@@ -52,7 +59,6 @@
/**
* Defines the components (icons, styles, etc)
* which are used to implement a particular skin.
- * @todo. look through UIExtension comments.
*
* This implementation class adds the details that should
* not be exposed outside of this API.
@@ -64,6 +70,7 @@
*/
abstract public class SkinImpl extends Skin
{
+
/**
* Returns an string identifier which uniquely identies
* this Skin implementation. Skin implementations
@@ -112,7 +119,7 @@
}
/**
- * Returns the name of the XSS style sheet for this Skin.
+ * Returns the name of the style sheet for this Skin.
*/
@Override
abstract public String getStyleSheetName();
@@ -141,6 +148,8 @@
* Cannot be null.
* @param key The key of the translation to retrieve. Cannot be null.
* @throws NullPointerException if lContext or key is null.
+ * @throws MissingResourceException if the resource key cannot be found in the skin's bundle
+ * or the skin additions' bundles.
*/
@Override
public Object getTranslatedValue(
@@ -148,74 +157,33 @@
String key
) throws MissingResourceException
{
- //testTranslationKey(key); //jmw test
-
if (lContext == null)
throw new NullPointerException(_LOG.getMessage(
"NULL_LOCALE_CONTEXT"));
if (key == null)
throw new NullPointerException("Null key");
- String bundleName = getBundleName();
- if (bundleName == null)
+ List<String> resourceBundleNames = _getResourceBundleNames();
+
+ // if there is nothing to check, return null
+ if (resourceBundleNames.size() == 0)
return null;
-
- return lContext.getBundle(bundleName).getObject(key);
- }
-
-
-
- /**
- * This is a test function.
- * This looks at the stack that I have on the request map for the
- * current component being rendered -- I store the prefix in
- * UIComponentUINode.
- * @param key
- */
- /********* jmw for testing translation keys
- public static void testTranslationKey(
- String key)
- {
-
- javax.faces.context.FacesContext fcontext =
- javax.faces.context.FacesContext.getCurrentInstance();
- Stack translationKeyStack = (Stack)fcontext.getExternalContext().
- getRequestMap().get("TRANSLATION_KEY");
-
-
- String translationKeyPrefix = null;
-
- if ((translationKeyStack != null) && !translationKeyStack.empty())
- translationKeyPrefix = (String)translationKeyStack.peek();
-
-
- // System.out.println(translationKeyPrefix + " / " + key); //jmw test
-
- String keyPrefix = null;
- int index = key.indexOf('.');
- if (index != -1)
- keyPrefix = key.substring(0, index);
-
- if (translationKeyPrefix != null)
- {
- if (!(translationKeyPrefix.equalsIgnoreCase(keyPrefix)))
- {
- System.out.println("***NO MATCH " + translationKeyPrefix + " / " + key + "");
- }
- }
- if ((translationKeyPrefix == null) && (key != null) &&
- !(key.equals("WINDOW_CREATION_ERROR") || key.equals("NO_SCRIPT_MESSAGE")))
+
+ Object translatedValue = getCachedTranslatedValue(lContext, key);
+ if (translatedValue == null)
{
- System.out.println("***nothing was rendered, but I have a key of " + key);
+ throw new MissingResourceException("Can't find resource for bundle "
+ +resourceBundleNames
+ +", key "+key,
+ getBundleName(),
+ key);
}
+
+ return translatedValue;
+
}
- ****/
- /**
- * Returns the name of the ResourceBundle for the Skin.
- */
- abstract protected String getBundleName();
/**
* Our renderers call this to get the icon. This returns a renderable
@@ -260,56 +228,6 @@
}
/**
- * Find the actual icon
- * @param refIcon a ReferenceIcon instance
- * @param referencedIconStack The stack of reference icon names which have
- * already been visited. Used to detect circular dependencies.
- * @return icon which is resolved. i.e., it is not a ReferenceIcon.
- */
- private Icon _resolveReferenceIcon(
- ReferenceIcon refIcon,
- Stack<String> referencedIconStack)
- {
- String refName = refIcon.getName();
-
- // make sure we don't have a circular dependency
- if ( _stackContains(referencedIconStack, refName))
- {
- if (_LOG.isWarning())
- _LOG.warning(_CIRCULAR_INCLUDE_ERROR + refName);
- return null;
- }
-
- if (referencedIconStack == null)
- {
- referencedIconStack = new Stack<String>();
- }
-
- referencedIconStack.push(refName);
-
- Icon icon = getIcon(refName, false);
-
- if ((icon instanceof ReferenceIcon) && (icon != null))
- {
-
- return _resolveReferenceIcon((ReferenceIcon)icon,
- referencedIconStack);
-
- }
-
- return icon;
- }
-
- // Tests whether the value is present in the (possibly null) stack.
- private static boolean _stackContains(Stack<String> stack, Object value)
- {
- if (stack == null)
- return false;
-
- return stack.contains(value);
- }
-
- /**
* Registers an Icon for the specified icon name.
* @param iconName The name of the icon. Cannot be null.
* @param icon The Icon to register.
@@ -327,45 +245,58 @@
_icons.put(iconName, icon);
}
-
+
/**
- * Registers a style sheet which defines extension-specific
- * styles. The styles specified by this style sheet will be
- * merged with the Skin's own styles. The full set
- * of styles can be obtained by calling getStyleSheetDocument().
- * @todo Is this even supported???
- * @param styleSheetName The name of the style sheet which
- * defines the extension's styles. This style sheet
- * should be installed under the directory specified by
- * Configuration.STYLES_DIRECTORY path.
- * @see #getStyleSheetDocument
- * @throws NullPointerException if styleSheetName is null.
+ * Adds a SkinAddition on this Skin. You can call this method as many times
+ * as you like for the Skin, and it will add the SkinAddition to the list of
+ * SkinAdditions.
+ * However, it does not make sense to call this method more than once
+ * with the same SkinAddition object.
+ * This is meant for the skin-addition use-cases, where a custom component
+ * developer has a style sheet and/or resource bundle for their custom
+ * components, and they want the style sheet and/or resource bundle
+ * to work for this Skin and the children Skins.
+ * The stylesheets specified in the SkinAdditions will be merged with the
+ * Skin's own styles.
+ * The resource bundles specified in the SkinAdditions will be looked into
+ * if the translated key is not found in the Skin's own resource bundle
+ * during the call to getTranslatedString or getTranslatedValue.
+ *
+ * @param skinAddition The SkinAddition object to add to the Skin.
+ * @throws NullPointerException if SkinAddition is null.
*/
- @Override
- public void registerStyleSheet(
- String styleSheetName
+ public void addSkinAddition (
+ SkinAddition skinAddition
)
{
- if (styleSheetName == null)
- throw new NullPointerException(_LOG.getMessage(
- "NULL_STYLESHEETNAME"));
-
- if (_extensionStyleSheetNames == null)
- {
- _extensionStyleSheetNames = new ArrayList<String>();
- }
+ // TODO change error message to use the error message resource bundle.
+ if (skinAddition == null)
+ throw new NullPointerException(
+ "A null SkinAddition object was passed to addSkinAddition.");
- _extensionStyleSheetNames.add(styleSheetName);
+ if (_skinAdditions == null)
+ {
+ _skinAdditions = new ArrayList<SkinAddition>();
+ }
+ _skinAdditions.add(skinAddition);
}
-
+
/**
- * Returns the style class map, or null if there is no map.
- * @param arc RenderingContext
- * @return Map<String, String> It should be a map that contains the full style class name as
- * the key, and the value could be a shortened style class name,
- * or a portlet style class name, etc.
+ * Gets an unmodifiable List of SkinAdditions that have been added
+ * on this Skin. To add to the SkinAdditions List,
+ * call addSkinAddition(SkinAddition)
+ * @return List an unmodifiable List of SkinAdditions.
+ * @see #addSkinAddition(SkinAddition)
*/
-
+ public List<SkinAddition> getSkinAdditions()
+ {
+ if (_skinAdditions == null)
+ {
+ return Collections.emptyList();
+ }
+ else
+ return Collections.unmodifiableList(_skinAdditions);
+ }
/**
* Returns the style class map, or null if there is no map.
@@ -374,8 +305,9 @@
* short style classes can be used instead of the full style class
* names to reduce the overall size of generated content.
* @param arc RenderingContext
- * @return Map<String, String> The default implemention returns a map of full
- * style class names to shortened style classes.
+ * @return Map<String, String> It should be a map that contains the full style class name
+ * as the key, and the value could be a shortened style class name,
+ * or a portlet style class name, etc.
*/
@Override
public Map<String, String> getStyleClassMap(
@@ -397,7 +329,7 @@
/**
* Returns the StyleSheetDocument object which defines all of the
* styles for this Skin, including any styles that are
- * contributed by UIExtensions.
+ * contributed by skin-additions.
*/
public StyleSheetDocument getStyleSheetDocument(StyleContext context)
{
@@ -443,6 +375,130 @@
{
_properties.put(key, value);
}
+
+ /**
+ * Returns a translated value in the LocaleContext's translation Locale, or null
+ * if the key could not be found.
+ * This value may or may not be a String, and developers should avoid
+ * calling toString() unless absolutely necessary.
+ * This method protects against MissingResourceExceptions by checking that the key exists
+ * before calling the bundle's getObject method. It eats any MissingResourceExceptions as
+ * a result of not finding the bundle, since there can be multiple bundles per skin, and
+ * we could get a lot of MissingResourceExceptions otherwise.
+ * Then the method caches the value once it is found in a particular
+ * resource bundle.
+ * This method is useful for SkinExtensions which will also check their ancestor skins
+ * for the resource if it is not found in the SkinExtension. MissingResourceExceptions would
+ * be numerous if we didn't protect against them.
+ * If you want to throw a MissingResourceException once all the ancestor skins and their
+ * bundles and registered bundles are checked, then you should call getTranslatedValue for the
+ * most base skin, and it will throw a MissingResourceException if the
+ * key was not found in any of the bundles.
+ * @see #getTranslatedValue(LocaleContext, String)
+ * @param lContext The LocaleContext which provides the translation Locale.
+ * Cannot be null.
+ * @param key The key of the translation to retrieve. Cannot be null.
+ * @throws NullPointerException if lContext or key is null.
+ * @return Object translated value of the key;
+ * null if bundleName and skin-addition bundleNames are null for this Skin;
+ * null if the key cannot be found in the bundle or registered bundles -or-
+ *
+
+ */
+ protected Object getCachedTranslatedValue(
+ LocaleContext lContext,
+ String key
+ )
+ {
+ if (lContext == null)
+ throw new NullPointerException(_LOG.getMessage(
+ "NULL_LOCALE_CONTEXT"));
+ if (key == null)
+ throw new NullPointerException("Null key");
+
+ List<String> resourceBundleNames = _getResourceBundleNames();
+
+ // if there is nothing to check, return null
+ if (resourceBundleNames.size() == 0)
+ return null;
+
+
+ return _getCachedTranslationValueFromLocale(lContext,
+ resourceBundleNames, key);
+
+ }
+
+ /**
+ * @param styleSheetName
+ * @see #addSkinAddition(SkinAddition)
+ * @deprecated Use addSkinAddition instead
+ */
+ public void registerStyleSheet(String styleSheetName)
+ {
+ //TODO Take out deprecated after sufficient amount of time has passed
+ // deprecated July, 2007
+ SkinAddition addition = new SkinAddition(styleSheetName, null);
+ addSkinAddition(addition);
+ }
+
+ /**
+ * Returns the name of the ResourceBundle for this Skin instance.
+ * This does not include the SkinAddition resource bundles.
+ * We differentiate between the two types of resource bundles so that
+ * the Skin's own resource bundle can take precedence.
+ */
+ abstract protected String getBundleName();
+
+
+ /**
+ * Find the actual icon
+ * @param refIcon a ReferenceIcon instance
+ * @param referencedIconStack The stack of reference icon names which have
+ * already been visited. Used to detect circular dependencies.
+ * @return icon which is resolved. i.e., it is not a ReferenceIcon.
+ */
+ private Icon _resolveReferenceIcon(
+ ReferenceIcon refIcon,
+ Stack<String> referencedIconStack)
+ {
+ String refName = refIcon.getName();
+
+ // make sure we don't have a circular dependency
+ if ( _stackContains(referencedIconStack, refName))
+ {
+ if (_LOG.isWarning())
+ _LOG.warning(_CIRCULAR_INCLUDE_ERROR + refName);
+ return null;
+ }
+
+ if (referencedIconStack == null)
+ {
+ referencedIconStack = new Stack<String>();
+ }
+
+ referencedIconStack.push(refName);
+
+ Icon icon = getIcon(refName, false);
+
+ if ((icon instanceof ReferenceIcon) && (icon != null))
+ {
+
+ return _resolveReferenceIcon((ReferenceIcon)icon,
+ referencedIconStack);
+
+ }
+
+ return icon;
+ }
+
+ // Tests whether the value is present in the (possibly null) stack.
+ private static boolean _stackContains(Stack<String> stack, Object value)
+ {
+ if (stack == null)
+ return false;
+
+ return stack.contains(value);
+ }
// Checks to see whether any of our style sheets have been updated
private boolean _checkStylesModified(
@@ -454,16 +510,16 @@
if (_skinStyleSheet != null)
modified = _skinStyleSheet.checkModified(context);
- // We also check all of the UIExtension style sheets even
+ // We also check all of the skin-addition style sheets even
// if we already know that the skin's style sheet has been
// modified. We need to do this because we want to call
// StyleSheetEntry.checkModified() for each entry - otherwise
// out of date StyleSheetEntries may not get updated.
- if (_extensionStyleSheets != null)
+ if (_skinAdditionStyleSheets != null)
{
- for (int i = 0; i < _extensionStyleSheets.length; i++)
+ for (int i = 0; i < _skinAdditionStyleSheets.length; i++)
{
- StyleSheetEntry entry = _extensionStyleSheets[i];
+ StyleSheetEntry entry = _skinAdditionStyleSheets[i];
if (entry.checkModified(context))
modified = true;
}
@@ -547,8 +603,8 @@
_registerIconsAndPropertiesFromStyleSheetEntry(_skinStyleSheet);
}
- // Now create entries for UIExtension-specific style sheets.
- _extensionStyleSheets = _getExtensionStyleSheets(context);
+ // Now create entries for skin-addition-specific style sheets.
+ _skinAdditionStyleSheets = _getSkinAdditionsStyleSheets(context);
}
// Now merge all of the documents provided by all of our
@@ -558,25 +614,25 @@
if (_skinStyleSheet != null)
document = _skinStyleSheet.getDocument();
- // Merge in any UIExtension style sheets on top of
+ // Merge in any skin-addition style sheets on top of
// the skin's style sheet
- if (_extensionStyleSheets != null)
+ if (_skinAdditionStyleSheets != null)
{
- for (int i = 0; i < _extensionStyleSheets.length; i++)
+ for (int i = 0; i < _skinAdditionStyleSheets.length; i++)
{
- StyleSheetEntry entry = _extensionStyleSheets[i];
+ StyleSheetEntry entry = _skinAdditionStyleSheets[i];
if (entry != null)
{
// add the icons and properties that are in the
- // extensionDocument's StyleSheetEntry
+ // skin-addition's StyleSheetEntry
_registerIconsAndPropertiesFromStyleSheetEntry(entry);
// now merge the css properties
- StyleSheetDocument extensionDocument = entry.getDocument();
+ StyleSheetDocument additionDocument = entry.getDocument();
- if (extensionDocument != null)
+ if (additionDocument != null)
{
- // Merge the UIExtension's StyleSheetDocument on top of
+ // Merge the skin-addition's StyleSheetDocument on top of
// the current StyleSheetDocument. Note: This is not
// exactly efficient - we would be better off creating
// an array of StyleSheetDocuments and merging them all
@@ -584,7 +640,7 @@
// executed, this shouldn't be a bottleneck...
document = StyleSheetDocumentUtils.mergeStyleSheetDocuments(
document,
- extensionDocument);
+ additionDocument);
}
}
@@ -604,19 +660,20 @@
StyleSheetDocument.UNKNOWN_TIMESTAMP);
}
- // Gets the StyleSheetEntries for UIExtensions
- private StyleSheetEntry[] _getExtensionStyleSheets(StyleContext context)
+ // Gets the StyleSheetEntries for skin-additions
+ private StyleSheetEntry[] _getSkinAdditionsStyleSheets(StyleContext context)
{
- if (_extensionStyleSheetNames == null)
+ List<String> skinAdditionStyleSheetNames = _getSkinAdditionsStyleSheetNames();
+ if (skinAdditionStyleSheetNames.size() == 0)
return null;
// Create a list to hold our StyleSheetEntries
- int count = _extensionStyleSheetNames.size();
+ int count = skinAdditionStyleSheetNames.size();
List<StyleSheetEntry> entries = new ArrayList<StyleSheetEntry>(count);
// Loop through all registered style sheet names and
// try to create a StyleSheetEntry for each name.
- for(String name : _extensionStyleSheetNames)
+ for(String name : skinAdditionStyleSheetNames)
{
StyleSheetEntry entry = StyleSheetEntry.createEntry(context, name);
if (entry != null)
@@ -627,30 +684,328 @@
if (!entries.isEmpty())
{
- _extensionStyleSheets = new StyleSheetEntry[entries.size()];
- return entries.toArray(_extensionStyleSheets);
+ _skinAdditionStyleSheets = new StyleSheetEntry[entries.size()];
+ return entries.toArray(_skinAdditionStyleSheets);
}
return null;
}
+
+ /*
+ * Returns an List of skin-addition style sheets for the Skin.
+ * These stylesheets are added with addSkinAddition.
+ * This List does not include the skin's own stylesheet.
+ * @return List<String> of skin addition stylesheet names. It will
+ * return a List of size 0 if no skin addition stylesheets exist.
+ * @see #addSkinAddition(String, String)
+ * @see #getStyleSheetName()
+ */
+ private List<String> _getSkinAdditionsStyleSheetNames()
+ {
+ // Get all the SkinAdditions's style sheet names.
+ // Get the style sheet names and create a List
+ // Cache this list in an instance variable
+
+ if (_skinAdditionStyleSheetNames != null)
+ return _skinAdditionStyleSheetNames;
+
+ // loop through all the SkinAdditions and get the resource bundles
+ List<SkinAddition> additions = getSkinAdditions();
+
+ List<String> styleSheetNames = new ArrayList<String>(additions.size());
+
+ for (SkinAddition addition : additions)
+ {
+ String name = addition.getStyleSheetName();
+ if (name != null)
+ {
+ styleSheetNames.add(name);
+ }
+ }
+
+ // cache in instance variable
+ _skinAdditionStyleSheetNames = styleSheetNames;
+
+ return _skinAdditionStyleSheetNames;
+ }
+
+ /*
+ * Returns the List of all the ResourceBundles for the Skin --
+ * including Skin's bundle and the skin addition bundles
+ * These resourceBundles are added with addSkinAddition.
+ * @see #addSkinAddition(String, String)
+ * @see #getBundleName()
+ */
+ private List<String> _getResourceBundleNames()
+ {
+ // Get all the SkinAdditions's resource bundles.
+ // Get the resource bundle names and create a List
+ // Cache this list in instance variable
+
+ // return if already cached
+ if (_resourceBundleNames != null)
+ return _resourceBundleNames;
+
+ // We haven't retrieved the bundle names yet, so do so now.
+ String bundleName = getBundleName();
+
+ List<SkinAddition> additions = getSkinAdditions();
+
+ int resourceBundleCount = additions.size();
+ if (bundleName != null)
+ resourceBundleCount++;
+
+ List<String> bundleNameList = new ArrayList<String>(resourceBundleCount);
+
+ if (bundleName != null)
+ bundleNameList.add(bundleName);
+
+ for (SkinAddition addition : additions)
+ {
+ String name = addition.getResourceBundleName();
+ if (name != null)
+ {
+ bundleNameList.add(name);
+ }
+ }
+
+ // cache in instance variable
+ _resourceBundleNames = bundleNameList;
+
+ return _resourceBundleNames;
+ }
+
+ // get the cached value for the locale and key from the _translations map.
+ // If the value does not exist, then find it in the resource bundles,
+ // searching the Skin's bundle first, then each skin addition resource
+ // bundle until it is found. This method fills in the cached key/value map
+ // as we look for the key/value. It keeps track of which bundles we looked
+ // in so that we don't have to look in them any more for this session.
+ private Object _getCachedTranslationValueFromLocale(
+ LocaleContext lContext,
+ List<String> resourceBundleNames,
+ String key
+ )
+ {
+ Locale locale = lContext.getTranslationLocale();
+
+ KeyValueMapStatus keyValueMapStatus = _translations.get(locale);
+ Map keyValueMap = null;
+
+ if (keyValueMapStatus != null)
+ {
+ keyValueMap = keyValueMapStatus.getKeyValueMap();
+ if (keyValueMap != null)
+ {
+ Object value = keyValueMap.get(key);
+ if (value != null)
+ {
+ return value;
+ }
+ }
+ }
+ else
+ {
+ // create the keyValueMapStatus object and put it on the locale
+ synchronized (_translations)
+ {
+ if (!_translations.contains(locale))
+ {
+ keyValueMapStatus = new KeyValueMapStatus();
+ keyValueMap = keyValueMapStatus.getKeyValueMap();
+ _translations.put(locale, keyValueMapStatus);
+ }
+ }
+ }
+
+ // at this point the keyValueMapStatus is set on the locale,
+ // and we know we have to fill it in.
+ // getProcessedBundlesIndex will tell us which resource bundles
+ // we have already processed (locale bundle + skin-addition bundles)
+ // we increment this number after we look in each bundle and update
+ // the keyValueMap.
+
+ int numberOfBundleNames = resourceBundleNames.size();
+
+ // in theory, multiple threads could get the same processedBundleIndex
+ // here, so we could get all these threads updating the same map, but
+ // it will eventually update the index, so I won't worry about this now.
+ int startIndex = keyValueMapStatus.getProcessedBundlesIndex();
+ for (int i=startIndex; i < numberOfBundleNames;)
+ {
+ String bundleName = resourceBundleNames.get(i);
+ // 'true' means to check if the key already exists in the keyValueMap and
+ // if so do not override.
+ _fillInKeyValueMap(lContext, bundleName, keyValueMap, (i==0));
+ i = keyValueMapStatus.incrementAndGetProcessedBundlesIndex();
+ Object value = keyValueMap.get(key);
+ if (value != null)
+ {
+ return value;
+ }
+ }
+
+ // nothing was found
+ return null;
+
+ }
+
+ /**
+ * Fill in the keyValueMap with all the keys and values for the ResourceBundle.
+ * The ResourceBundle is found by calling lContext.getBundle(bundleName).
+ * MissingResourceExceptions are not thrown, since it is possible that
+ * SkinExtensions have only provided custom bundles for certain languages.
+ * @param lContext LocaleContext, LocaleContext maintains a cache of found ResourceBundles
+ * @param bundleName the resource bundle's name.
+ * @param keyValueMap A Map of bundle keys to their values
+ * @param checkForKey If true, we will check if the key is already in the map
+ * and not re-add it. If false, we don't bother checking,
+ * we just add it. When this method is called for the
+ * first bundle, then we know we do not need to check.
+ */
+ private void _fillInKeyValueMap(
+ LocaleContext lContext,
+ String bundleName,
+ Map keyValueMap,
+ boolean checkForKey)
+ {
+
+ ResourceBundle bundle = null;
+
+ try
+ {
+ bundle = lContext.getBundle(bundleName);
+ }
+ catch (MissingResourceException e)
+ {
+ // It is possible that the call to getBundle() might
+ // fail with a MissingResourceException if the customer
+ // has only provided a custom bundle for certain languages.
+ // This is okay, so we just eat these exceptions.
+ ;
+ }
+
+ if (bundle != null)
+ {
+ Enumeration<String> en = bundle.getKeys();
+
+ if (en != null)
+ {
+ while (en.hasMoreElements())
+ {
+ String bundleKey = en.nextElement();
+ // if checkForKey is true, don't override an existing key/value
+ if (checkForKey)
+ {
+ if (!keyValueMap.containsKey(bundleKey))
+ {
+ Object value = bundle.getObject(bundleKey);
+ if (value != null)
+ keyValueMap.put(bundleKey, value);
+ }
+ }
+ else
+ {
+ Object value = bundle.getObject(bundleKey);
+ if (value != null)
+ keyValueMap.put(bundleKey, value);
+ }
+ }
+ }
+ }
+ }
+
+ // This is the 'value' of the _translations map.
+ // This contains a translation key/value map which contains
+ // all the translation keys and values in the resource bundles
+ // we have processed thus far for a particular locale.
+ // It also contains an index which keeps track of how
+ // many of the bundles we have checked so far, so that
+ // we don't recheck a bundle.
+ // This is to help with performance, since getting
+ // values from a resource bundle is expensive.
+ private static class KeyValueMapStatus
+ {
+
+ KeyValueMapStatus()
+ {
+ _keyValueMap = new ConcurrentHashMap<String, Object>();
+ _processedBundlesIndex = new AtomicInteger(0);
+ }
+
+ // get the current key/value Map
+ public Map<String, Object> getKeyValueMap()
+ {
+ return _keyValueMap;
+ }
+
+ // Get the current value of processedBundlesIndex.
+ public int getProcessedBundlesIndex()
+ {
+ return _processedBundlesIndex.get();
+ }
+
+ // Atomically increment by one the current value of processBundlesIndex.
+ // @return the updated value
+ public int incrementAndGetProcessedBundlesIndex()
+ {
+ return _processedBundlesIndex.incrementAndGet();
+ }
+
+ Map<String, Object> _keyValueMap;
+ // This keeps track of the number of bundles that have been processed.
+ // A Skin can have multiple bundles registered on it -- a local resource
+ // bundle + any number of skin-addition bundles.
+ // When we get a key (getTranslatedValue), we check each bundle
+ // and fill in the keyValueMap until we find the key.
+ // We update this index after we process each
+ // bundle, so that we don't recheck a bundle. We only have to check a bundle
+ // once per locale per session, because we cache the keys/values for each
+ // bundle we check in the _keyValueMap.
+ AtomicInteger _processedBundlesIndex;
+ }
+
+ // Now that we look into possibly multiple ResourceBundles
+ // to find a translation (eg. the local bundle + a skin-addition's
+ // bundle), translation lookups can become expensive.
+ // To get a value, we call: lContext.getBundle(name).getObject(key).
+ // We speed things up by caching the translations
+ // in this _translations map.
+ // As we get a call to getTranslatedValue with a key, we
+ // look through our keyValueMap. If it isn't there, we loop
+ // through each resource bundle we haven't yet checked,
+ // and we get all the keys and values
+ // and when we have all the keys/values for the
+ // bundle, we return if the key/value is there. Otherwise,
+ // we check the next bundle and so on.
+ // If we never get a request for a key in bundle X, that bundle X's
+ // keys/values will never be put in the keyvalue map. This is a good thing.
+ private ConcurrentHashMap<Locale, KeyValueMapStatus> _translations =
+ new ConcurrentHashMap<Locale, KeyValueMapStatus>(13);
// HashMap that maps icon name to Icons
private ConcurrentHashMap<String, Icon> _icons = new ConcurrentHashMap<String, Icon>();
// The StyleSheetDocument which contains all of the styles
- // for this Skin - including styles contributed by UIExtensions.
+ // for this Skin - including styles contributed by skin-additions.
private StyleSheetDocument _styleSheetDocument;
// A StyleSheetEntry which defines the styles that are
// provided by this Skin's style sheet only (does
- // not include UIExtension styles).
+ // not include skin-additions styles).
private StyleSheetEntry _skinStyleSheet;
- // List of extension style sheet names
- private List<String> _extensionStyleSheetNames;
+ // List of skin-additions style sheet names for this Skin
+ private List<String> _skinAdditionStyleSheetNames;
- // Array of UIExtension StyleSheetEntries
- private StyleSheetEntry[] _extensionStyleSheets;
+ // Array of skin-additions StyleSheetEntries
+ private StyleSheetEntry[] _skinAdditionStyleSheets;
+
+ // List of all the resource bundle names (bundleName + skin-additions)
+ private List<String> _resourceBundleNames;
+
+ // List of skin-additions for this Skin
+ private List<SkinAddition> _skinAdditions;
// HashMap of Skin properties
private ConcurrentHashMap<Object, Object> _properties= new ConcurrentHashMap<Object, Object>();
Modified: myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinUtils.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinUtils.java?view=diff&rev=561122&r1=561121&r2=561122
==============================================================================
--- myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinUtils.java (original)
+++ myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinUtils.java Mon Jul 30 14:14:30 2007
@@ -41,6 +41,7 @@
import org.apache.myfaces.trinidad.skin.Skin;
+import org.apache.myfaces.trinidad.skin.SkinAddition;
import org.apache.myfaces.trinidadinternal.renderkit.core.skin.MinimalDesktopSkinExtension;
import org.apache.myfaces.trinidadinternal.renderkit.core.skin.MinimalPdaSkinExtension;
import org.apache.myfaces.trinidadinternal.renderkit.core.skin.MinimalPortletSkinExtension;
@@ -96,7 +97,7 @@
}
/**
- * Register any custom skin extensions found in the
+ * Register any custom skin extensions (and skin-additions) found in the
* trinidad-skins.xml file with the SkinFactory.
*
* Make sure the SkinFactory.getFactory() does not return null before
@@ -118,7 +119,7 @@
skinFactory = SkinFactory.getFactory();
}
- _registerSkinExtensions(context, skinFactory);
+ _registerSkinExtensionsAndAdditions(context, skinFactory);
}
@@ -286,7 +287,7 @@
}
/**
- * Parse the trinidad-skins.xml file for SkinExtensions and add each
+ * Parse the trinidad-skins.xml file for SkinExtensions and SkinAdditionNodes and add each
* SkinExtension to the skinFactory.
* First find all the trinidad-skins.xml files that are in META-INF directory, and
* add those skins to the skin factory.
@@ -296,7 +297,7 @@
* @param context
* @param skinFactory
*/
- private static void _registerSkinExtensions(
+ private static void _registerSkinExtensionsAndAdditions(
ExternalContext context,
SkinFactory skinFactory)
{
@@ -340,6 +341,9 @@
// register all the skin additions from META-INF trinidad-skins.xml and WEB-INF
// trinidad-skins.xml that we have stored in the metaInfSkinsNodeList object and the
// webInfSkinsNode object
+ // skin-additions are additions to a skin, not extensions. They are used by
+ // custom component developers that want to add a stylesheet for their components
+ // to a particular skin, like the simple skin.
FacesContext fContext = FacesContext.getCurrentInstance();
// register skin-additions from META-INF/trinidad-skins.xml files
_registerMetaInfSkinAdditions(fContext, skinFactory, metaInfSkinsNodeList);
@@ -654,16 +658,21 @@
{
String skinId = skinAdditionNode.getSkinId();
String styleSheetName = skinAdditionNode.getStyleSheetName();
-
+ String resourceBundleName = skinAdditionNode.getResourceBundleName();
+
Skin skin = skinFactory.getSkin(fContext, skinId);
- if (skin != null && styleSheetName != null)
- {
+ if (skin != null && (styleSheetName != null) || (resourceBundleName != null))
+ {
// If the styleSheetName is in the META-INF/trinidad-skins.xml file, then
// we prepend META-INF to the styleSheetName if it doesn't begin with '/'.
// This way we can find the file when we go to parse it later.
- if (isMetaInfFile)
- styleSheetName = _prependMetaInf(styleSheetName);
- skin.registerStyleSheet(styleSheetName);
+ if (isMetaInfFile && (styleSheetName != null))
+ styleSheetName = _prependMetaInf(styleSheetName);
+
+
+ // we need to create a SkinAddition and add it to the skin
+ SkinAddition addition = new SkinAddition(styleSheetName, resourceBundleName);
+ skin.addSkinAddition(addition);
}
}
}
Modified: myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/ui/laf/xml/parse/SkinAdditionNode.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/ui/laf/xml/parse/SkinAdditionNode.java?view=diff&rev=561122&r1=561121&r2=561122
==============================================================================
--- myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/ui/laf/xml/parse/SkinAdditionNode.java (original)
+++ myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/ui/laf/xml/parse/SkinAdditionNode.java Mon Jul 30 14:14:30 2007
@@ -33,11 +33,13 @@
*/
public SkinAdditionNode (
String skinId,
- String styleSheetName
+ String styleSheetName,
+ String resourceBundleName
)
{
_styleSheetName = styleSheetName;
_skinId = skinId;
+ _resourceBundleName = resourceBundleName;
}
public String getSkinId()
@@ -60,6 +62,16 @@
_styleSheetName = ssName;
}
+ public String getResourceBundleName()
+ {
+ return _resourceBundleName;
+ }
+
+ public void setResourceBundleName(String rbName)
+ {
+ _resourceBundleName = rbName;
+ }
+
// Sort by the name of the stylesheet
public int compareTo(SkinAdditionNode node)
{
@@ -68,5 +80,6 @@
private String _skinId;
private String _styleSheetName;
+ private String _resourceBundleName;
}
Modified: myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/ui/laf/xml/parse/SkinAdditionNodeParser.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/ui/laf/xml/parse/SkinAdditionNodeParser.java?view=diff&rev=561122&r1=561121&r2=561122
==============================================================================
--- myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/ui/laf/xml/parse/SkinAdditionNodeParser.java (original)
+++ myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/ui/laf/xml/parse/SkinAdditionNodeParser.java Mon Jul 30 14:14:30 2007
@@ -60,11 +60,13 @@
// id and family are required. log a severe error if they are null.
if ((_skinId == null) && (_LOG.isWarning()))
_LOG.severe("REQUIRED_ELEMENT_SKINID_NOT_FOUND");
+ /*
if ((_styleSheetName == null) && (_LOG.isWarning()))
_LOG.severe("REQUIRED_ELEMENT_STYLE_SHEET_NAME_NOT_FOUND");
+ */
- return new SkinAdditionNode(_skinId, _styleSheetName);
+ return new SkinAdditionNode(_skinId, _styleSheetName, _resourceBundleName);
}
@Override
@@ -77,7 +79,8 @@
{
if ("skin-id".equals(localName) ||
- "style-sheet-name".equals(localName))
+ "style-sheet-name".equals(localName) ||
+ "bundle-name".equals(localName))
{
return new StringParser();
@@ -99,11 +102,14 @@
_skinId = (String) child;
else if ("style-sheet-name".equals(localName))
_styleSheetName = (String) child;
+ else if ("bundle-name".equals(localName))
+ _resourceBundleName = (String) child;
}
private String _skinId;
private String _styleSheetName;
+ private String _resourceBundleName;
private static final TrinidadLogger _LOG =