View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.myfaces.trinidad.menu;
20  
21  import java.util.ArrayList;
22  import java.util.Collection;
23  import java.util.Enumeration;
24  import java.util.HashSet;
25  import java.util.List;
26  import java.util.Locale;
27  import java.util.Map;
28  import java.util.MissingResourceException;
29  import java.util.ResourceBundle;
30  import java.util.Set;
31  
32  import javax.faces.context.FacesContext;
33  
34  import org.apache.myfaces.trinidad.logging.TrinidadLogger;
35  import org.apache.myfaces.trinidad.util.ContainerUtils;
36  
37  /**
38   * Menu Utilities used by the Menu Model internal code.
39   * All classes are package private.
40   *
41   */
42  public class MenuUtils
43  {
44    MenuUtils() {}
45  
46    //=======================================================================
47    // String, Stringbuffer utilities
48    //=======================================================================
49    /**
50     * Returns a String with the first occurrence of str1 replaced with str2
51     * in fullstring
52     * 
53     * @param fullstring - The full string
54     * @param str1 - String to be found in fullstring
55     * @param str2 - String to replace the first occurrence of str1
56     * @return String
57     */
58    static String stringReplaceFirst(String fullstring, String str1, String str2)
59    {
60      if (fullstring == null)
61        return null;
62      
63      StringBuffer returnStr = 
64        stringBufferReplaceFirst(new StringBuffer(fullstring), str1, str2);
65      return returnStr.toString();
66    }
67  
68    /**
69     * Returns a StringBuffer with the first occurrence of str1 replaced with str2
70     * in fullBuf
71     * 
72     * @param fullBuf - The full stringbuffer
73     * @param str1 - String to be found in fullBuf
74     * @param str2 - String to replace the first occurrence of str1
75     * @return StringBuffer
76     */
77    static StringBuffer stringBufferReplaceFirst(StringBuffer fullBuf, String str1, 
78                                                 String str2)
79    {
80      if (fullBuf == null)
81        return null;
82      
83      String fullstr = fullBuf.toString();
84      
85      // All Cases that just return fullBuf
86      if (str1 == null || str2 == null)
87        return fullBuf;
88      if ("".equals(fullstr) && !"".equals(str1))
89        return fullBuf;
90  
91      // if the string being replaced is not found, return    
92      int startIdx = fullBuf.indexOf(str1);
93      if (startIdx == -1)
94        return fullBuf;
95      
96      // We are ok, now go ahead
97      int foundLen = str1.length();
98      int endIdx = startIdx + foundLen;
99      
100     StringBuffer returnBuf = fullBuf.replace(startIdx, endIdx, str2);
101     return returnBuf;
102   }
103 
104   //=======================================================================
105   // Bound Value/EL Expression utilities
106   //=======================================================================
107   
108   /**
109    * Gets the bound value of an EL expression
110    * 
111    * @param elExpression - String representing an EL expression
112    */
113   static public <T> T getBoundValue(String elExpression, Class<T> desiredClass)
114   {
115     try
116     {
117       if (desiredClass == null)
118         throw new NullPointerException();
119 
120       FacesContext ctx = FacesContext.getCurrentInstance();
121       return (T) ctx.getApplication().evaluateExpressionGet(ctx,
122                                                             elExpression,
123                                                             desiredClass);
124     }
125     catch (Exception ex)
126     {
127       _LOG.severe("EL Expression " + elExpression + 
128                   " is invalid or returned a bad value.\n", ex);
129       _LOG.severe(ex);
130       return null;
131     }
132   }
133   
134   /**
135    * Evaluate an attribute value string representing a boolean value 
136    * and return its boolean value.  There are 3 possible valid values for
137    * boolStr:
138    * o EL Expression (that returns a boolean)
139    * o the string "true"
140    * o the string "false"
141    * 
142    * In the case of another string being passed in, the default value
143    * of the attribute is returned.
144    * 
145    * @param boolStr - String to be evaluated into a boolean.
146    * @param defaultVal - The default boolean value to be returned in the case
147    *                     where and invalid boolstr is passed in.
148    * @return boolean value equivalent of boolStr
149    */
150   static boolean evalBoolean (String boolStr, boolean defaultVal)
151   {
152     if (   boolStr != null 
153         && ContainerUtils.isValueReference(boolStr)
154        )
155     {
156       Boolean bValue = getBoundValue(boolStr, Boolean.class);
157       return bValue.booleanValue();
158     }
159     else
160     {    
161       if ("true".equals(boolStr) || "false".equals(boolStr))
162         return (Boolean.valueOf(boolStr)).booleanValue();
163       else
164         return defaultVal;
165     }
166   }
167 
168   /**
169    * Evaluate a string representing an EL expression.
170    * 
171    * @param propVal - string to be evaluated.
172    * @return the string bound value of the EL Expression
173    */
174   static String evalString(String propVal)
175   {
176     if (   propVal != null 
177         && ContainerUtils.isValueReference(propVal)
178        )
179     {
180       String elVal = getBoundValue(propVal, String.class);
181       return elVal;
182     }
183     return propVal;
184   }
185 
186   /**
187    * Evaluate a string representing an EL expression.
188    * 
189    * @param propVal - string to be evaluated.
190    * @return the int bound value of the EL Expression
191    */
192   static int evalInt(String propVal)
193   {
194     if (   propVal != null 
195         && ContainerUtils.isValueReference(propVal)
196        )
197     {
198       Integer elVal = getBoundValue(propVal, Integer.class);
199       return elVal.intValue();
200     }
201     return Integer.parseInt(propVal);
202   }
203 
204   /**
205    * Create a ResourceBundle and put it in an EL-reachable scope.
206    *
207    * @param resBundleName - String containing name of class containing the 
208    *                        resource bundle.
209    * @param resBundleKey - String key for the resource bundle
210    */
211   @SuppressWarnings("unchecked")
212   static public void loadBundle(String resBundleName, String resBundleKey)
213   {
214     FacesContext facesContext = FacesContext.getCurrentInstance();
215     Map<String, Object> applicationMap =
216       facesContext.getExternalContext().getApplicationMap();
217 
218     // Get the view root locale
219     Locale requestLocale = facesContext.getViewRoot().getLocale();
220 
221     // Make sure it is not null
222     if (requestLocale == null)
223     {
224       requestLocale = facesContext.getApplication().getDefaultLocale();
225     }
226 
227     // Is there a bundle with this key already on the session map?
228     _BundleMap bundleMap = (_BundleMap) applicationMap.get(resBundleKey);
229 
230     // if so, get its locale.  If the locale has not
231     // changed, just return, i.e. use the existing bundle
232     if (bundleMap != null)
233     {
234       Locale bundleLocale = bundleMap.getLocale();
235 
236       if (bundleLocale == null)
237       {
238         ResourceBundle rb = bundleMap.getBundle();
239         bundleLocale = rb.getLocale();
240       }
241 
242       if (requestLocale == bundleLocale)
243       {
244         // the bundle on the applicationMap is ok so just return
245         return;
246       }
247     }
248 
249     String bundleName = null;
250 
251     if (resBundleName != null)
252     {
253       // if _bundleName is an EL, then get its value
254       if (ContainerUtils.isValueReference(resBundleName))
255       {
256         bundleName = MenuUtils.getBoundValue(resBundleName, String.class);
257       }
258       else
259       {
260         bundleName = resBundleName ;
261       }
262     }
263 
264     final ResourceBundle bundle;
265 
266     try
267     {
268       bundle = ResourceBundle.getBundle(bundleName, requestLocale);
269     }
270     catch (MissingResourceException e)
271     {
272       _LOG.severe("RESOURCE_BUNDLE_NOT_FOUND", bundleName);
273       _LOG.severe(e);
274       return;
275     }
276 
277     // Put the bundle in the map.  At this point the key is
278     // unique because of the handler Id we inserted when loadBundle
279     // was called.
280     applicationMap.put(resBundleKey, new _BundleMap(bundle, requestLocale));
281   }
282   
283   /**
284    * Map containing a resource bundle and its key that is placed 
285    * on the http request map.  This resource bundle is used by the menu
286    * model metadata to externalize strings, such as tab labels, for 
287    * translation.
288    */
289   @SuppressWarnings("unchecked")
290   static private class _BundleMap implements Map<String, String>
291   {
292     private ResourceBundle _bundle;
293     private Locale _locale;
294     private List<String> _values;
295 
296     public _BundleMap(ResourceBundle bundle)
297     {
298       _bundle = bundle;
299       _locale = bundle.getLocale();
300     }
301 
302     public _BundleMap(ResourceBundle bundle, Locale locale)
303     {
304       _bundle = bundle;
305       _locale = locale;
306     }
307 
308     //Optimized methods
309     public String get(Object key)
310     {
311       try 
312       {
313         return _bundle.getString(key.toString());
314       } 
315       catch (Exception e) 
316       {
317         return "!!!" + key + "!!!";
318       }
319     }
320 
321     public boolean isEmpty()
322     {
323       return !_bundle.getKeys().hasMoreElements();
324     }
325 
326     public boolean containsKey(Object key)
327     {
328       return _bundle.getObject(key.toString()) != null;
329     }
330 
331     //Unoptimized methods
332     public Collection<String> values()
333     {
334         if (_values == null)
335         {
336           _values = new ArrayList<String>();
337           for (Enumeration<String> enumer = _bundle.getKeys(); 
338                enumer.hasMoreElements(); )
339           {
340             String v = _bundle.getString(enumer.nextElement());
341             _values.add(v);
342           }
343         }
344         return _values;
345     }
346 
347     public int size()
348     {
349       return values().size();
350     }
351 
352     public boolean containsValue(Object value)
353     {
354       return values().contains(value);
355     }
356 
357     public Set<Map.Entry<String, String>> entrySet()
358     {
359       Set<Map.Entry<String, String>> set = new HashSet<Map.Entry<String, String>>();
360       
361       for (Enumeration<String> enumer = _bundle.getKeys(); enumer.hasMoreElements(); )
362       {
363         final String k = enumer.nextElement();
364         set.add(new Map.Entry<String, String>()
365         {
366           public String getKey()
367           {
368             return k;
369           }
370 
371           public String getValue()
372           {
373             return _bundle.getString(k);
374           }
375 
376           public String setValue(String value)
377           {
378             throw new UnsupportedOperationException();
379           }
380         });
381       }
382       return set;
383     }
384 
385     public Set<String> keySet()
386     {
387       Set<String> set = new HashSet<String>();
388       for (Enumeration<String> enumer = _bundle.getKeys(); enumer.hasMoreElements(); )
389       {
390         set.add(enumer.nextElement());
391       }
392       return set;
393     }
394 
395     //Unsupported methods
396     public String remove(Object key)
397     {
398       throw new UnsupportedOperationException();
399     }
400 
401     public void putAll(Map<? extends String, ? extends String> t)
402     {
403       throw new UnsupportedOperationException();
404     }
405 
406     public String put(String key, String value)
407     {
408       throw new UnsupportedOperationException();
409     }
410 
411     public void clear()
412     {
413       throw new UnsupportedOperationException();
414     }
415     
416     public ResourceBundle getBundle()
417     {
418       return _bundle;
419     }
420 
421     public Locale getLocale()
422     {
423       return _locale;
424     }
425   }  // endclass _BundleMap
426 
427   private final static TrinidadLogger _LOG = 
428                         TrinidadLogger.createTrinidadLogger(MenuUtils.class);
429 }