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 }