001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * // Copyright (c) 1998, 2007, Oracle. All rights reserved.
005: *
006: *
007: * The contents of this file are subject to the terms of either the GNU
008: * General Public License Version 2 only ("GPL") or the Common Development
009: * and Distribution License("CDDL") (collectively, the "License"). You
010: * may not use this file except in compliance with the License. You can obtain
011: * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
012: * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
013: * language governing permissions and limitations under the License.
014: *
015: * When distributing the software, include this License Header Notice in each
016: * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
017: * Sun designates this particular file as subject to the "Classpath" exception
018: * as provided by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the License
020: * Header, with the fields enclosed by brackets [] replaced by your own
021: * identifying information: "Portions Copyrighted [year]
022: * [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * If you wish your version of this file to be governed by only the CDDL or
027: * only the GPL Version 2, indicate your decision by adding "[Contributor]
028: * elects to include this software in this distribution under the [CDDL or GPL
029: * Version 2] license." If you don't indicate a single choice of license, a
030: * recipient has the option to distribute your version of this file under
031: * either the CDDL, the GPL Version 2 or to extend the choice of license to
032: * its licensees as provided above. However, if you add GPL Version 2 code
033: * and therefore, elected the GPL Version 2 license, then the option applies
034: * only if the new code is made subject to such option by the copyright
035: * holder.
036: */
037: package oracle.toplink.essentials.internal.helper;
038:
039: import java.math.BigDecimal;
040: import java.math.BigInteger;
041:
042: import java.util.Date;
043: import java.util.HashSet;
044: import java.util.HashMap;
045: import java.util.Map;
046: import java.util.Set;
047:
048: import oracle.toplink.essentials.descriptors.ClassDescriptor;
049:
050: /**
051: * INTERNAL
052: * This class is a helper class providing type information.
053: * Its implementation uses Java reflection to calculate the type information.
054: */
055: public class BasicTypeHelperImpl {
056:
057: /** Set of intergral types and its wrapper classes. */
058: private static Set integralTypes = new HashSet();
059: /** Set of floating point types and its wrapper classes. */
060: private static Set floatingPointTypes = new HashSet();
061: /** Set of date classes. */
062: private static Set dateClasses = new HashSet();
063: /** Maps primtives types to their wrapper classes. */
064: private static Map primitiveToWrapper = new HashMap();
065: /** Maps wrapper classes to their primitive types. */
066: private static Map wrapperToPrimitive = new HashMap();
067:
068: static {
069: // Inilialize set of integral types plus their wrapper classes
070: integralTypes.add(byte.class);
071: integralTypes.add(Byte.class);
072: integralTypes.add(short.class);
073: integralTypes.add(Short.class);
074: integralTypes.add(char.class);
075: integralTypes.add(Character.class);
076: integralTypes.add(int.class);
077: integralTypes.add(Integer.class);
078: integralTypes.add(long.class);
079: integralTypes.add(Long.class);
080:
081: // Inilialize set of floating point types plus their wrapper classes
082: floatingPointTypes.add(float.class);
083: floatingPointTypes.add(Float.class);
084: floatingPointTypes.add(double.class);
085: floatingPointTypes.add(Double.class);
086:
087: // Inilialize set of floating point types plus their wrapper classes
088: dateClasses.add(java.util.Date.class);
089: dateClasses.add(java.util.Calendar.class);
090: dateClasses.add(java.sql.Date.class);
091: dateClasses.add(java.sql.Time.class);
092: dateClasses.add(java.sql.Timestamp.class);
093:
094: // Inilialize mapping primitives to their wrapper classes
095: primitiveToWrapper.put(boolean.class, Boolean.class);
096: primitiveToWrapper.put(byte.class, Byte.class);
097: primitiveToWrapper.put(short.class, Short.class);
098: primitiveToWrapper.put(char.class, Character.class);
099: primitiveToWrapper.put(int.class, Integer.class);
100: primitiveToWrapper.put(long.class, Long.class);
101: primitiveToWrapper.put(float.class, Float.class);
102: primitiveToWrapper.put(double.class, Double.class);
103:
104: // Inilialize mapping wrapper classes to their primitives
105: wrapperToPrimitive.put(Boolean.class, boolean.class);
106: wrapperToPrimitive.put(Byte.class, byte.class);
107: wrapperToPrimitive.put(Short.class, short.class);
108: wrapperToPrimitive.put(Character.class, char.class);
109: wrapperToPrimitive.put(Integer.class, int.class);
110: wrapperToPrimitive.put(Long.class, long.class);
111: wrapperToPrimitive.put(Float.class, float.class);
112: wrapperToPrimitive.put(Double.class, double.class);
113: }
114:
115: /** A singleton for this class */
116: private static final BasicTypeHelperImpl singleton = new BasicTypeHelperImpl();
117:
118: /** Gets instance of this class */
119: public static BasicTypeHelperImpl getInstance() {
120: return singleton;
121: }
122:
123: /** Returns the name of the specified type. */
124: public String getTypeName(Object type) {
125: Class clazz = getJavaClass(type);
126: return (clazz == null) ? null : clazz.getName();
127: }
128:
129: /** Returns the class object of the specified type. */
130: public Class getJavaClass(Object type) {
131: Class clazz = null;
132: if (type instanceof Class) {
133: clazz = (Class) type;
134: } else if (type instanceof ClassDescriptor) {
135: clazz = ((ClassDescriptor) type).getJavaClass();
136: }
137: return clazz;
138: }
139:
140: /** Returns the Object type representation.*/
141: public Object getObjectType() {
142: return Object.class;
143: }
144:
145: /** Returns the boolean type representation.*/
146: public Object getBooleanType() {
147: return boolean.class;
148: }
149:
150: /** Returns the Boolean class representation.*/
151: public Object getBooleanClassType() {
152: return Boolean.class;
153: }
154:
155: /** Returns the char type representation.*/
156: public Object getCharType() {
157: return char.class;
158: }
159:
160: /** Returns the Character class representation.*/
161: public Object getCharacterClassType() {
162: return Character.class;
163: }
164:
165: /** Returns the byte type representation.*/
166: public Object getByteType() {
167: return byte.class;
168: }
169:
170: /** Returns the Byte class representation.*/
171: public Object getByteClassType() {
172: return Byte.class;
173: }
174:
175: /** Returns the short type representation.*/
176: public Object getShortType() {
177: return short.class;
178: }
179:
180: /** Returns the Short class representation.*/
181: public Object getShortClassType() {
182: return Short.class;
183: }
184:
185: /** Returns the int type representation.*/
186: public Object getIntType() {
187: return int.class;
188: }
189:
190: /** Returns the Inter class representation.*/
191: public Object getIntegerClassType() {
192: return Integer.class;
193: }
194:
195: /** Returns the long type representation.*/
196: public Object getLongType() {
197: return long.class;
198: }
199:
200: /** Returns the type representation of class Long.*/
201: public Object getLongClassType() {
202: return Long.class;
203: }
204:
205: /** Returns the float type representation.*/
206: public Object getFloatType() {
207: return float.class;
208: }
209:
210: /** Returns the type representation of class Float.*/
211: public Object getFloatClassType() {
212: return Float.class;
213: }
214:
215: /** Returns the double type representation.*/
216: public Object getDoubleType() {
217: return double.class;
218: }
219:
220: /** Returns the type representation of class Double.*/
221: public Object getDoubleClassType() {
222: return Double.class;
223: }
224:
225: /** Returns the String type representation.*/
226: public Object getStringType() {
227: return String.class;
228: }
229:
230: /** Returns the BigInteger type representation.*/
231: public Object getBigIntegerType() {
232: return BigInteger.class;
233: }
234:
235: /** Returns the BigDecimal type representation.*/
236: public Object getBigDecimalType() {
237: return BigDecimal.class;
238: }
239:
240: /** Returns the java.util.Date type representation.*/
241: public Object getDateType() {
242: return Date.class;
243: }
244:
245: /** */
246: public boolean isEnumType(Object type) {
247: Class clazz = getJavaClass(type);
248: return (clazz != null) && (clazz.isEnum());
249: }
250:
251: /** */
252: public boolean isNumericType(Object type) {
253: return isIntegralType(type) || isFloatingPointType(type)
254: || isBigIntegerType(type) || isBigDecimalType(type);
255: }
256:
257: /**
258: * Returns true if the specified type represents an
259: * integral type or a wrapper class of an integral type.
260: */
261: public boolean isIntegralType(Object type) {
262: return integralTypes.contains(type);
263: }
264:
265: /**
266: * Returns true if the specified type represents an
267: * floating point type or a wrapper class of an floating point type.
268: */
269: public boolean isFloatingPointType(Object type) {
270: return floatingPointTypes.contains(type);
271: }
272:
273: /** Returns true if the specified type is a wrapper class. */
274: public boolean isWrapperClass(Object type) {
275: return wrapperToPrimitive.containsKey(type);
276: }
277:
278: /**
279: * Returns true if type is the boolean primitive type or the Boolean wrapper class
280: */
281: public boolean isBooleanType(Object type) {
282: return (type == getBooleanType())
283: || (type == getBooleanClassType());
284: }
285:
286: /**
287: * Returns true if type is the char primitive type or the Character wrapper class
288: */
289: public boolean isCharacterType(Object type) {
290: return (type == getCharType())
291: || (type == getCharacterClassType());
292: }
293:
294: /**
295: * Returns true if type is the byte primitive type or the Byte wrapper class
296: */
297: public boolean isByteType(Object type) {
298: return (type == getByteType()) || (type == getByteClassType());
299: }
300:
301: /**
302: * Returns true if type is the short primitive type or the Short wrapper class
303: */
304: public boolean isShortType(Object type) {
305: return (type == getShortType())
306: || (type == getShortClassType());
307: }
308:
309: /**
310: * Returns true if type is the int primitive type or the Integer wrapper class
311: */
312: public boolean isIntType(Object type) {
313: return (type == getIntType())
314: || (type == getIntegerClassType());
315: }
316:
317: /**
318: * Returns true if type is the long primitive type or the Long wrapper class
319: */
320: public boolean isLongType(Object type) {
321: return (type == getLongType()) || (type == getLongClassType());
322: }
323:
324: /**
325: * Returns true if type is the float primitive type or the Float wrapper class
326: */
327: public boolean isFloatType(Object type) {
328: return (type == getFloatType())
329: || (type == getFloatClassType());
330: }
331:
332: /**
333: * Returns true if type is the double primitive type or the Double wrapper class
334: */
335: public boolean isDoubleType(Object type) {
336: return (type == getDoubleType())
337: || (type == getDoubleClassType());
338: }
339:
340: /** Returns true if the specified type represents java.lang.String. */
341: public boolean isStringType(Object type) {
342: return type == getStringType();
343: }
344:
345: /** */
346: public boolean isDateClass(Object type) {
347: return dateClasses.contains(type);
348: }
349:
350: /** */
351: public boolean isBigIntegerType(Object type) {
352: return type == getBigIntegerType();
353: }
354:
355: /** */
356: public boolean isBigDecimalType(Object type) {
357: return type == getBigDecimalType();
358: }
359:
360: /** Returns true if the specified type denotes an orable type */
361: public boolean isOrderableType(Object type) {
362: return isNumericType(type) || isStringType(type)
363: || isDateClass(type) || isEnumType(type);
364: }
365:
366: /** */
367: public boolean isAssignableFrom(Object left, Object right) {
368: if ((left == null) || (right == null)) {
369: return false;
370: }
371: // chec for identical types
372: if (left == right) {
373: return true;
374: }
375: // numeric types are compatible
376: Object promoted = extendedBinaryNumericPromotion(left, right);
377: if (promoted != null) {
378: return true;
379: }
380: // date types are compatible
381: if (isDateClass(left) && isDateClass(right)) {
382: return true;
383: }
384: // handle boolean and Boolean
385: if (isBooleanType(left) && isBooleanType(right)) {
386: return true;
387: }
388: // check for inheritance and implements
389: return getJavaClass(left).isAssignableFrom(getJavaClass(right));
390: }
391:
392: /** Implements binary numeric promotion as defined in JLS extended by
393: * wrapper classes, BigDecimal and BigInteger. */
394: public Object extendedBinaryNumericPromotion(Object left,
395: Object right) {
396: if ((left == null) || (right == null) || !isNumericType(left)
397: || !isNumericType(right)) {
398: return null;
399: }
400:
401: // handle BigDecimal
402: if (isBigDecimalType(left) || isBigDecimalType(right)) {
403: return getBigDecimalType();
404: }
405:
406: // handle BigInteger
407: if (isBigIntegerType(left)) {
408: return isFloatingPointType(right) ? right
409: : getBigIntegerType();
410: }
411: if (isBigIntegerType(right)) {
412: return isFloatingPointType(left) ? left
413: : getBigIntegerType();
414: }
415:
416: // check wrapper classes
417: boolean wrapper = false;
418: if (isWrapperClass(left)) {
419: wrapper = true;
420: left = getPrimitiveType(left);
421: }
422: if (isWrapperClass(right)) {
423: wrapper = true;
424: right = getPrimitiveType(right);
425: }
426:
427: Object promoted = binaryNumericPromotion(left, right);
428: if (wrapper && promoted != null) {
429: promoted = getWrapperClass(promoted);
430: }
431: return promoted;
432: }
433:
434: // Helper methods
435:
436: /** Returns the primitive for the specified wrapper class. */
437: protected Object getPrimitiveType(Object wrapper) {
438: return wrapperToPrimitive.get(wrapper);
439: }
440:
441: /** Returns the wrapper class for the specified primitive. */
442: protected Object getWrapperClass(Object primitive) {
443: return primitiveToWrapper.get(primitive);
444: }
445:
446: /** Implements binary numeric promotion as defined in JLS. */
447: protected Object binaryNumericPromotion(Object left, Object right) {
448: if ((left == null) || (right == null)) {
449: return null;
450: }
451: Object type = null;
452:
453: if (left == getDoubleType() || right == getDoubleType()) {
454: type = getDoubleType();
455: } else if (left == getFloatType() || right == getFloatType()) {
456: type = getFloatType();
457: } else if (left == getLongType() || right == getLongType()) {
458: type = getLongType();
459: } else if (isIntegralType(left) && isIntegralType(right)) {
460: type = getIntType();
461: }
462: return type;
463: }
464:
465: }
|