1 /*
2  * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */

25
26
27 package javax.management.openmbean;
28
29
30 // java import
31 //
32 import java.io.InvalidObjectException;
33 import java.io.ObjectStreamException;
34 import java.math.BigDecimal;
35 import java.math.BigInteger;
36 import java.util.Date;
37 import java.util.Map;
38 import java.util.HashMap;
39
40 // jmx import
41 //
42 import javax.management.ObjectName;
43
44
45 /**
46  * The <code>SimpleType</code> class is the <i>open type</i> class whose instances describe
47  * all <i>open data</i> values which are neither arrays,
48  * nor {@link CompositeData CompositeData} values,
49  * nor {@link TabularData TabularData} values.
50  * It predefines all its possible instances as static fields, and has no public constructor.
51  * <p>
52  * Given a <code>SimpleType</code> instance describing values whose Java class name is <i>className</i>,
53  * the internal fields corresponding to the name and description of this <code>SimpleType</code> instance
54  * are also set to <i>className</i>.
55  * In other words, its methods <code>getClassName</code>, <code>getTypeName</code> and <code>getDescription</code>
56  * all return the same string value <i>className</i>.
57  *
58  * @since 1.5
59  */

60 public final class SimpleType<T> extends OpenType<T> {
61
62     /* Serial version */
63     static final long serialVersionUID = 2215577471957694503L;
64
65     // SimpleType instances.
66     // IF YOU ADD A SimpleType, YOU MUST UPDATE OpenType and typeArray
67
68     /**
69      * The <code>SimpleType</code> instance describing values whose
70      * Java class name is <code>java.lang.Void</code>.
71      */

72     public static final SimpleType<Void> VOID =
73         new SimpleType<Void>(Void.class);
74
75     /**
76      * The <code>SimpleType</code> instance describing values whose
77      * Java class name is <code>java.lang.Boolean</code>.
78      */

79     public static final SimpleType<Boolean> BOOLEAN =
80         new SimpleType<Boolean>(Boolean.class);
81
82     /**
83      * The <code>SimpleType</code> instance describing values whose
84      * Java class name is <code>java.lang.Character</code>.
85      */

86     public static final SimpleType<Character> CHARACTER =
87         new SimpleType<Character>(Character.class);
88
89     /**
90      * The <code>SimpleType</code> instance describing values whose
91      * Java class name is <code>java.lang.Byte</code>.
92      */

93     public static final SimpleType<Byte> BYTE =
94         new SimpleType<Byte>(Byte.class);
95
96     /**
97      * The <code>SimpleType</code> instance describing values whose
98      * Java class name is <code>java.lang.Short</code>.
99      */

100     public static final SimpleType<Short> SHORT =
101         new SimpleType<Short>(Short.class);
102
103     /**
104      * The <code>SimpleType</code> instance describing values whose
105      * Java class name is <code>java.lang.Integer</code>.
106      */

107     public static final SimpleType<Integer> INTEGER =
108         new SimpleType<Integer>(Integer.class);
109
110     /**
111      * The <code>SimpleType</code> instance describing values whose
112      * Java class name is <code>java.lang.Long</code>.
113      */

114     public static final SimpleType<Long> LONG =
115         new SimpleType<Long>(Long.class);
116
117     /**
118      * The <code>SimpleType</code> instance describing values whose
119      * Java class name is <code>java.lang.Float</code>.
120      */

121     public static final SimpleType<Float> FLOAT =
122         new SimpleType<Float>(Float.class);
123
124     /**
125      * The <code>SimpleType</code> instance describing values whose
126      * Java class name is <code>java.lang.Double</code>.
127      */

128     public static final SimpleType<Double> DOUBLE =
129         new SimpleType<Double>(Double.class);
130
131     /**
132      * The <code>SimpleType</code> instance describing values whose
133      * Java class name is <code>java.lang.String</code>.
134      */

135     public static final SimpleType<String> STRING =
136         new SimpleType<String>(String.class);
137
138     /**
139      * The <code>SimpleType</code> instance describing values whose
140      * Java class name is <code>java.math.BigDecimal</code>.
141      */

142     public static final SimpleType<BigDecimal> BIGDECIMAL =
143         new SimpleType<BigDecimal>(BigDecimal.class);
144
145     /**
146      * The <code>SimpleType</code> instance describing values whose
147      * Java class name is <code>java.math.BigInteger</code>.
148      */

149     public static final SimpleType<BigInteger> BIGINTEGER =
150         new SimpleType<BigInteger>(BigInteger.class);
151
152     /**
153      * The <code>SimpleType</code> instance describing values whose
154      * Java class name is <code>java.util.Date</code>.
155      */

156     public static final SimpleType<Date> DATE =
157         new SimpleType<Date>(Date.class);
158
159     /**
160      * The <code>SimpleType</code> instance describing values whose
161      * Java class name is <code>javax.management.ObjectName</code>.
162      */

163     public static final SimpleType<ObjectName> OBJECTNAME =
164         new SimpleType<ObjectName>(ObjectName.class);
165
166     private static final SimpleType<?>[] typeArray = {
167         VOID, BOOLEAN, CHARACTER, BYTE, SHORT, INTEGER, LONG, FLOAT,
168         DOUBLE, STRING, BIGDECIMAL, BIGINTEGER, DATE, OBJECTNAME,
169     };
170
171
172     private transient Integer myHashCode = null;        // As this instance is immutable, these two values
173     private transient String  myToString = null;        // need only be calculated once.
174
175
176     /* *** Constructor *** */
177
178     private SimpleType(Class<T> valueClass) {
179         super(valueClass.getName(), valueClass.getName(), valueClass.getName(),
180               false);
181     }
182
183
184     /* *** SimpleType specific information methods *** */
185
186     /**
187      * Tests whether <var>obj</var> is a value for this
188      * <code>SimpleType</code> instance.  <p> This method returns
189      * <code>true</code> if and only if <var>obj</var> is not null and
190      * <var>obj</var>'s class name is the same as the className field
191      * defined for this <code>SimpleType</code> instance (ie the class
192      * name returned by the {@link OpenType#getClassName()
193      * getClassName} method).
194      *
195      * @param obj the object to be tested.
196      *
197      * @return <code>true</code> if <var>obj</var> is a value for this
198      * <code>SimpleType</code> instance.
199      */

200     public boolean isValue(Object obj) {
201
202         // if obj is nullreturn false
203         //
204         if (obj == null) {
205             return false;
206         }
207
208         // Test if obj's class name is the same as for this instance
209         //
210         return this.getClassName().equals(obj.getClass().getName());
211     }
212
213
214     /* *** Methods overriden from class Object *** */
215
216     /**
217      * Compares the specified <code>obj</code> parameter with this <code>SimpleType</code> instance for equality.
218      * <p>
219      * Two <code>SimpleType</code> instances are equal if and only if their
220      * {@link OpenType#getClassName() getClassName} methods return the same value.
221      *
222      * @param  obj  the object to be compared for equality with this <code>SimpleType</code> instance;
223      *              if <var>obj</var> is <code>null</code> or is not an instance of the class <code>SimpleType</code>,
224      *              <code>equals</code> returns <code>false</code>.
225      *
226      * @return  <code>true</code> if the specified object is equal to this <code>SimpleType</code> instance.
227      */

228     public boolean equals(Object obj) {
229
230         /* If it weren't for readReplace(), we could replace this method
231            with just:
232            return (this == obj);
233         */

234
235         if (!(obj instanceof SimpleType<?>))
236             return false;
237
238         SimpleType<?> other = (SimpleType<?>) obj;
239
240         // Test if other's className field is the same as for this instance
241         //
242         return this.getClassName().equals(other.getClassName());
243     }
244
245     /**
246      * Returns the hash code value for this <code>SimpleType</code> instance.
247      * The hash code of a <code>SimpleType</code> instance is the hash code of
248      * the string value returned by the {@link OpenType#getClassName() getClassName} method.
249      * <p>
250      * As <code>SimpleType</code> instances are immutable, the hash code for this instance is calculated once,
251      * on the first call to <code>hashCode</code>, and then the same value is returned for subsequent calls.
252      *
253      * @return  the hash code value for this <code>SimpleType</code> instance
254      */

255     public int hashCode() {
256
257         // Calculate the hash code value if it has not yet been done (ie 1st call to hashCode())
258         //
259         if (myHashCode == null) {
260             myHashCode = Integer.valueOf(this.getClassName().hashCode());
261         }
262
263         // return always the same hash code for this instance (immutable)
264         //
265         return myHashCode.intValue();
266     }
267
268     /**
269      * Returns a string representation of this <code>SimpleType</code> instance.
270      * <p>
271      * The string representation consists of
272      * the name of this class (ie <code>javax.management.openmbean.SimpleType</code>) and the type name
273      * for this instance (which is the java class name of the values this <code>SimpleType</code> instance represents).
274      * <p>
275      * As <code>SimpleType</code> instances are immutable, the string representation for this instance is calculated once,
276      * on the first call to <code>toString</code>, and then the same value is returned for subsequent calls.
277      *
278      * @return  a string representation of this <code>SimpleType</code> instance
279      */

280     public String toString() {
281
282         // Calculate the string representation if it has not yet been done (ie 1st call to toString())
283         //
284         if (myToString == null) {
285             myToString = this.getClass().getName()+ "(name="+ getTypeName() +")";
286         }
287
288         // return always the same string representation for this instance (immutable)
289         //
290         return myToString;
291     }
292
293     private static final Map<SimpleType<?>,SimpleType<?>> canonicalTypes =
294         new HashMap<SimpleType<?>,SimpleType<?>>();
295     static {
296         for (int i = 0; i < typeArray.length; i++) {
297             final SimpleType<?> type = typeArray[i];
298             canonicalTypes.put(type, type);
299         }
300     }
301
302     /**
303      * Replace an object read from an {@link
304      * java.io.ObjectInputStream} with the unique instance for that
305      * value.
306      *
307      * @return the replacement object.
308      *
309      * @exception ObjectStreamException if the read object cannot be
310      * resolved.
311      */

312     public Object readResolve() throws ObjectStreamException {
313         final SimpleType<?> canonical = canonicalTypes.get(this);
314         if (canonical == null) {
315             // Should not happen
316             throw new InvalidObjectException("Invalid SimpleType: " + this);
317         }
318         return canonical;
319     }
320 }
321