View Javadoc

1   /*
2   
3       dsh-identify  Lightweight components for identifiable beans.
4       Copyright (c) 2003-2012 held jointly by the individual authors.
5   
6       This library is free software; you can redistribute it and/or modify it
7       under the terms of the GNU Lesser General Public License as published
8       by the Free Software Foundation; either version 3 of the License, or (at
9       your option) any later version.
10  
11      This library is distributed in the hope that it will be useful, but WITHOUT
12      ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
13      FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14      License for more details.
15  
16      You should have received a copy of the GNU Lesser General Public License
17      along with this library;  if not, write to the Free Software Foundation,
18      Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA.
19  
20      > http://www.fsf.org/licensing/licenses/lgpl.html
21      > http://www.opensource.org/licenses/lgpl-license.php
22  
23  */
24  package org.dishevelled.identify;
25  
26  import java.beans.BeanInfo;
27  import java.beans.BeanDescriptor;
28  import java.beans.Introspector;
29  import java.beans.PropertyDescriptor;
30  import java.beans.IntrospectionException;
31  
32  import java.lang.reflect.Method;
33  import java.lang.reflect.InvocationTargetException;
34  
35  import java.net.URL;
36  
37  import javax.swing.LookAndFeel;
38  import javax.swing.UIManager;
39  
40  import org.dishevelled.iconbundle.IconBundle;
41  
42  import org.dishevelled.iconbundle.impl.PNGIconBundle;
43  
44  /**
45   * Provides static utility methods for determining
46   * the name property value and icon bundle for a bean.
47   *
48   * @author  Michael Heuer
49   * @version $Revision: 1059 $ $Date: 2012-01-03 14:03:02 -0600 (Tue, 03 Jan 2012) $
50   */
51  public final class IdentifyUtils
52  {
53      /** Name strategy. */
54      private NameStrategy nameStrategy;
55  
56      /** Icon bundle strategy. */
57      private IconBundleStrategy iconBundleStrategy;
58  
59      /** Default icon bundle. */
60      private IconBundle defaultIconBundle;
61  
62      /** Private static instance of IdentifyUtils. */
63      private static IdentifyUtils instance;
64  
65      /** GTK look and feel class name. */
66      private static final String GTK_LOOK_AND_FEEL_CLASS_NAME = "com.sun.java.swing.plaf.gtk.GTKLookAndFeel";
67  
68      /** JDK <= 1.5 MacOSX look and feel class name. */
69      private static final String JDK15_MAC_OSX_LOOK_AND_FEEL_CLASS_NAME = "apple.laf.AquaLookAndFeel";
70  
71      /** JDK >= 1.6 MacOSX look and feel class name. */
72      private static final String JDK16_MAC_OSX_LOOK_AND_FEEL_CLASS_NAME = "com.apple.laf.AquaLookAndFeel";
73  
74      /** Windows look and feel class name. */
75      private static final String WINDOWS_LOOK_AND_FEEL_CLASS_NAME = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel";
76  
77  
78      /**
79       * Private no-arg constructor.
80       */
81      private IdentifyUtils()
82      {
83          nameStrategy = new DefaultNameStrategy();
84          iconBundleStrategy = new DefaultIconBundleStrategy();
85  
86          URL url = getClass().getResource("default.png");
87          defaultIconBundle = new PNGIconBundle(url);
88      }
89  
90  
91      /**
92       * Return the static instance of IdentifyUtils.
93       *
94       * @return the static instance of IdentifyUtils
95       */
96      public static IdentifyUtils getInstance()
97      {
98          if (instance == null)
99          {
100             instance = new IdentifyUtils();
101         }
102         return instance;
103     }
104 
105     /**
106      * Return a name for the specified bean using the set name
107      * strategy.  Return the String <code>"null"</code> if
108      * <code>bean</code> is null.
109      *
110      * @see #getNameStrategy
111      *
112      * @param bean bean
113      * @return a name for the specified bean
114      */
115     public static String getNameFor(final Object bean)
116     {
117         return getInstance().getNameStrategy().getNameFor(bean);
118     }
119 
120     /**
121      * Return an icon bundle for the specified bean using the
122      * set icon bundle strategy.  Return <code>null</code> if
123      * <code>bean</code> is null, and the default icon bundle
124      * if an icon bundle cannot otherwise be found.
125      *
126      * @see #getIconBundleStrategy
127      * @see #getDefaultIconBundle
128      *
129      * @param bean bean
130      * @return an icon bundle for the specified bean
131      */
132     public static IconBundle getIconBundleFor(final Object bean)
133     {
134         return getInstance().getIconBundleStrategy().getIconBundleFor(bean);
135     }
136 
137     /**
138      * Return true if the current look and feel is the GTK look and feel.
139      *
140      * @see #GTK_LOOK_AND_FEEL_CLASS_NAME
141      * @return true if the current look and feel is the GTK look and feel
142      */
143     public static boolean isGTKLookAndFeel()
144     {
145         LookAndFeel lookAndFeel = UIManager.getLookAndFeel();
146         if (lookAndFeel == null)
147         {
148             return false;
149         }
150         return GTK_LOOK_AND_FEEL_CLASS_NAME.equals(lookAndFeel.getClass().getName());
151     }
152 
153     /**
154      * Return true if the current look and feel is the MacOSX look and feel.
155      *
156      * @see #JDK15_MAC_OSX_LOOK_AND_FEEL_CLASS_NAME
157      * @see #JDK16_MAC_OSX_LOOK_AND_FEEL_CLASS_NAME
158      * @return true if the current look and feel is the MacOSX look and feel
159      */
160     public static boolean isMacOSXLookAndFeel()
161     {
162         LookAndFeel lookAndFeel = UIManager.getLookAndFeel();
163         if (lookAndFeel == null)
164         {
165             return false;
166         }
167         return JDK15_MAC_OSX_LOOK_AND_FEEL_CLASS_NAME.equals(lookAndFeel.getClass().getName())
168             || JDK16_MAC_OSX_LOOK_AND_FEEL_CLASS_NAME.equals(lookAndFeel.getClass().getName());
169     }
170 
171     /**
172      * Return true if the current look and feel is the Windows look and feel.
173      *
174      * @see #WINDOWS_LOOK_AND_FEEL_CLASS_NAME
175      * @return true if the current look and feel is the Windows look and feel
176      */
177     public static boolean isWindowsLookAndFeel()
178     {
179         LookAndFeel lookAndFeel = UIManager.getLookAndFeel();
180         if (lookAndFeel == null)
181         {
182             return false;
183         }
184         return WINDOWS_LOOK_AND_FEEL_CLASS_NAME.equals(lookAndFeel.getClass().getName());
185     }
186 
187     /**
188      * Return the strategy used to determine the value for
189      * a name property on a bean.
190      *
191      * @return the name strategy
192      */
193     public NameStrategy getNameStrategy()
194     {
195         return nameStrategy;
196     }
197 
198     /**
199      * Set the strategy used to determine the value for
200      * a name property on a bean to <code>nameStrategy</code>.
201      *
202      * @param nameStrategy name strategy, must not be null
203      */
204     public void setNameStrategy(final NameStrategy nameStrategy)
205     {
206         if (nameStrategy == null)
207         {
208             throw new IllegalArgumentException("nameStrategy must not be null");
209         }
210 
211         this.nameStrategy = nameStrategy;
212     }
213 
214     /**
215      * Return the strategy used to find an icon bundle for
216      * a bean.
217      *
218      * @return the icon bundle strategy
219      */
220     public IconBundleStrategy getIconBundleStrategy()
221     {
222         return iconBundleStrategy;
223     }
224 
225     /**
226      * Set the strategy used to find an icon bundle for a bean
227      * to <code>iconBundleStrategy</code>.
228      *
229      * @param iconBundleStrategy icon bundle strategy, must not
230      *    be null
231      */
232     public void setIconBundleStrategy(final IconBundleStrategy iconBundleStrategy)
233     {
234         if (iconBundleStrategy == null)
235         {
236             throw new IllegalArgumentException("iconBundleStrategy must not be null");
237         }
238 
239         this.iconBundleStrategy = iconBundleStrategy;
240     }
241 
242     /**
243      * Return the icon bundle to use as a default icon bundle,
244      * in the case the icon bundle strategy is unable to find an
245      * icon bundle for a bean.
246      *
247      * @return the icon bundle to use as a default icon bundle
248      */
249     public IconBundle getDefaultIconBundle()
250     {
251         return defaultIconBundle;
252     }
253 
254     /**
255      * Set the default icon bundle to <code>defaultIconBundle</code>.
256      *
257      * @param defaultIconBundle the default icon bundle, must
258      *    not be null
259      */
260     public void setDefaultIconBundle(final IconBundle defaultIconBundle)
261     {
262         if (defaultIconBundle == null)
263         {
264             throw new IllegalArgumentException("defaultIconBundle must not be null");
265         }
266         this.defaultIconBundle = defaultIconBundle;
267     }
268 
269 
270     //
271     //  strategies
272 
273     /**
274      * Strategy used to determine the value for a name
275      * property on a bean.
276      */
277     interface NameStrategy
278     {
279 
280         /**
281          * Return a name for the specified bean.  Return
282          * the String <code>"null"</code> if
283          * <code>bean</code> is null.
284          *
285          * @param bean bean
286          * @return a name for the specified bean
287          */
288         String getNameFor(Object bean);
289     }
290 
291     /**
292      * Strategy used to find an icon bundle for a bean.
293      */
294     interface IconBundleStrategy
295     {
296 
297         /**
298          * Return an icon bundle for the specified bean.
299          * Return <code>null</code> if <code>bean</code>
300          * is null, and the default icon bundle if an icon bundle
301          * cannot otherwise be found.
302          *
303          * @see #getDefaultIconBundle
304          *
305          * @param bean bean
306          * @return an icon bundle for the specified bean
307          */
308         IconBundle getIconBundleFor(Object bean);
309     }
310 
311     /**
312      * Default name strategy.  Returns the string <code>"null"</code>
313      * if the specified bean is null.  Otherwise
314      * <ul>
315      * <li>checks if the bean is instanceof Identifiable</li>
316      * <li>checks if the bean's BeanInfo's BeanDescriptor is instanceof IdentifiableBeanDescriptor</li>
317      * <li>finally, returns <code>bean.toString()</code></li>
318      *</ul>
319      */
320     private class DefaultNameStrategy
321         implements NameStrategy
322     {
323 
324         /** {@inheritDoc} */
325         public String getNameFor(final Object bean)
326         {
327             if (bean == null)
328             {
329                 return "null";
330             }
331 
332             if (bean instanceof Identifiable)
333             {
334                 return ((Identifiable) bean).getName();
335             }
336 
337             try
338             {
339                 BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());
340                 BeanDescriptor beanDescriptor = beanInfo.getBeanDescriptor();
341 
342                 if (beanDescriptor instanceof IdentifiableBeanDescriptor)
343                 {
344                     int namePropertyIndex = ((IdentifiableBeanDescriptor) beanDescriptor).getNamePropertyIndex();
345                     if (namePropertyIndex != -1)
346                     {
347                         PropertyDescriptor namePropertyDescriptor = beanInfo.getPropertyDescriptors()[namePropertyIndex];
348                         Method readMethod = namePropertyDescriptor.getReadMethod();
349                         String name = (String) readMethod.invoke(bean, new Object[] {});
350                         return name;
351                     }
352                 }
353             }
354             catch (IntrospectionException ie)
355             {
356                 // empty
357             }
358             catch (IllegalAccessException iae)
359             {
360                 // empty
361             }
362             catch (InvocationTargetException ite)
363             {
364                 // empty
365             }
366 
367             return bean.toString();
368         }
369     }
370 
371     /**
372      * Default icon bundle strategy.  Returns <code>null</code> if
373      * the specified bean is null.  Otherwise
374      * <ul>
375      * <li>checks if the bean is instanceof Identifiable</li>
376      * <li>checks if the bean's BeanInfo's BeanDescriptor is instanceof IdentifiableBeanDescriptor</li>
377      * <li>finally, returns the default icon bundle</li>
378      * </ul>
379      *
380      * @see #getDefaultBeanInfo
381      */
382     private class DefaultIconBundleStrategy
383         implements IconBundleStrategy
384     {
385 
386         /** {@inheritDoc} */
387         public IconBundle getIconBundleFor(final Object bean)
388         {
389             if (bean == null)
390             {
391                 return null;
392             }
393 
394             if (bean instanceof Identifiable)
395             {
396                 return ((Identifiable) bean).getIconBundle();
397             }
398 
399             try
400             {
401                 BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());
402                 BeanDescriptor beanDescriptor = beanInfo.getBeanDescriptor();
403 
404                 if (beanDescriptor instanceof IdentifiableBeanDescriptor)
405                 {
406                     return ((IdentifiableBeanDescriptor) beanDescriptor).getIconBundle();
407                 }
408             }
409             catch (IntrospectionException ie)
410             {
411                 // empty
412             }
413 
414             return defaultIconBundle;
415         }
416     }
417 }