View Javadoc

1   /*
2    * Copyright (C) 2006  Tom Gibara
3    *
4    * This library is free software; you can redistribute it and/or
5    * modify it under the terms of the GNU Lesser General Public
6    * License as published by the Free Software Foundation; either
7    * version 2.1 of the License, or (at your option) any later version.
8    *
9    * This library is distributed in the hope that it will be useful,
10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12   * Lesser General Public License for more details.
13   *
14   * You should have received a copy of the GNU Lesser General Public
15   * License along with this library; if not, write to the Free Software
16   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17   */
18  package com.tomgibara.pronto.util;
19  
20  import java.lang.reflect.InvocationTargetException;
21  import java.lang.reflect.Method;
22  import java.util.Arrays;
23  
24  /**
25   * A collection of static utility methods which help with the methods declared
26   * by the Object class.
27   * 
28   * @author Tom Gibara
29   */
30  
31  public final class Objects {
32  
33      /**
34       * Tests whether two objects, both of which may be null, are equal. If both
35       * arguments are null, the result is true. If one argument is null the
36       * result is false. If neither argument is null then the equals method on
37       * the first argument is used to determine equality.
38       * 
39       * @param a
40       *            the first object to be tested for equality
41       * @param b
42       *            the second object to be tested for equality
43       * @return true if the objects are equal, false otherwise
44       */
45  
46      public static boolean equal(final Object a, final Object b) {
47          if (a == b) return true;
48          if (a == null) return false;
49          if (b == null) return false;
50          return a.equals(b);
51      }
52  
53      /**
54       * Tests whether two objects, both of which may be null, are equal. If both
55       * arguments are null, the result is false. If one argument is null the
56       * result is true. If neither argument is null then the equals method on the
57       * first argument is used to determine inequality.
58       * 
59       * @param a
60       *            the first object to be tested for inequality
61       * @param b
62       *            the second object to be tested for inequality
63       * @return true if the objects are unequal, false otherwise
64       */
65  
66      public static boolean notEqual(final Object a, final Object b) {
67          if (a == b) return false;
68          if (a == null) return true;
69          if (b == null) return true;
70          return !a.equals(b);
71      }
72  
73      /**
74       * The hash code of the object or zero for null.
75       * 
76       * @param object
77       *            any object, or null
78       * @return the hashcode of the object or zero for null
79       */
80  
81      public static int hashCode(final Object object) {
82          return object == null ? 0 : object.hashCode();
83      }
84  
85      /**
86       * The object as a string (using toString) or null if the supplied object is
87       * null.
88       * 
89       * @param object
90       *            any object, or null
91       * @return the String representation of the object or null
92       */
93  
94      public static String toString(final Object object) {
95          return object == null ? null : object.toString();
96      }
97  
98      /**
99       * <p>
100      * Attempts to provide a meaningful string representation of any object by
101      * reflecting on the available getter methods. The string representation
102      * includes the class of the value and the names and values of properties.
103      * </p>
104      * 
105      * <p>
106      * This method is not efficient and should not be used in instances where
107      * speed of execution is important. It is intended to provide a convenient
108      * way of adding a toString() method to simple POJOs.
109      * </p>
110      * 
111      * <p>
112      * The string "null" is returned if null is supplied to the method.
113      * </p>
114      * 
115      * @param object
116      *            any object or null
117      * @return a string representation of the object.
118      */
119 
120     // TODO protect against circularity
121     public static String autoToString(final Object object) {
122         if (object == null) return "null";
123         Class clss = object.getClass();
124         Method[] getters = Reflect.getters(clss.getMethods());
125         StringBuilder sb = new StringBuilder();
126         sb.append('[').append(clss.getName()).append(' ');
127         Object[] noArgs = new Object[0];
128         for (int i = 0; i < getters.length; i++) {
129             if (i != 0) sb.append(", ");
130             Method method = getters[i];
131             sb.append(Reflect.propertyName(method.getName())).append('=');
132             Object value;
133             try {
134                 value = method.invoke(object, noArgs);
135                 if (value != null && value.getClass().isArray()) {
136                     Class type = value.getClass().getComponentType();
137                     if (type.isPrimitive()) {
138                         if (type == boolean.class) value = Arrays.toString((boolean[]) value);
139                         else if (type == byte.class) value = Arrays.toString((byte[]) value);
140                         else if (type == char.class) value = Arrays.toString((char[]) value);
141                         else if (type == double.class) value = Arrays.toString((double[]) value);
142                         else if (type == float.class) value = Arrays.toString((float[]) value);
143                         else if (type == int.class) value = Arrays.toString((int[]) value);
144                         else if (type == long.class) value = Arrays.toString((long[]) value);
145                         else if (type == short.class) value = Arrays.toString((short[]) value);
146                         else { throw new IllegalStateException("Unknown primitive array"); }
147                     } else {
148                         // do this wrapping so that we get a meaningful string
149                         // representation
150                         value = Arrays.toString((Object[]) value);
151                     }
152                 }
153             } catch (IllegalArgumentException e) {
154                 e.printStackTrace();
155                 value = e.getMessage();
156             } catch (IllegalAccessException e) {
157                 e.printStackTrace();
158                 value = e.getMessage();
159             } catch (InvocationTargetException e) {
160                 e.printStackTrace();
161                 value = e.getMessage();
162             }
163             sb.append(value);
164         }
165         sb.append(']');
166         return sb.toString();
167     }
168 
169     private Objects() { }
170 
171 }