/** * Helios, OpenSource Monitoring * Brought to you by the Helios Development Group * * Copyright 2007, Helios Development Group and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. * */ package org.helios.gmx.util; import java.util.HashMap; import java.util.Map; /** * <p>Title: Primitive</p> * <p>Description: A helper enum to work with primitives and their upconverts.</p> * <p>Company: Helios Development Group LLC</p> * @author Whitehead (nwhitehead AT heliosdev DOT org) * <p><code>org.helios.gmx.util.Primitive</code></p> */ public enum Primitive { /** Primitive descriptor for Byte */ BYTE(Byte.class, byte.class, "B"), /** Primitive descriptor for Boolean */ BOOLEAN(Boolean.class, boolean.class, "Z"), /** Primitive descriptor for Short */ SHORT(Short.class, short.class, "S"), /** Primitive descriptor for Integer */ INT(Integer.class, int.class, "I"), /** Primitive descriptor for Character */ CHAR(Character.class, char.class, "C"), /** Primitive descriptor for Long */ LONG(Long.class, long.class, "J"), /** Primitive descriptor for Float */ FLOAT(Float.class, float.class, "F"), /** Primitive descriptor for Double */ DOUBLE(Double.class, double.class, "D"), /** Primitive descriptor for Void */ VOID(Void.class, void.class, "V"); /** The number of entries in the enum */ public static final int count = Primitive.values().length; /** A map of Primitives keyed by the primitive class name */ private static final Map<String, Primitive> PNAME_TO_P = new HashMap<String, Primitive>(count); /** A map of Primitives keyed by the primitive class */ private static final Map<Class<?>, Primitive> PCLASS_TO_P = new HashMap<Class<?>, Primitive>(count); /** A map of Primitives keyed by the upconvert class name */ private static final Map<String, Primitive> UNAME_TO_P = new HashMap<String, Primitive>(count); /** A map of Primitives keyed by the upconvert class */ private static final Map<Class<?>, Primitive> UCLASS_TO_P = new HashMap<Class<?>, Primitive>(count); /** A map of Primitives keyed by the opcode symbol */ private static final Map<String, Primitive> SYMBOL_TO_P = new HashMap<String, Primitive>(count); static { for(Primitive p: Primitive.values()) { PNAME_TO_P.put(p.pclazz.getName(), p); PCLASS_TO_P.put(p.pclazz, p); UNAME_TO_P.put(p.uclazz.getName(), p); UCLASS_TO_P.put(p.uclazz, p); SYMBOL_TO_P.put(p.symbol, p); } } /** * Determines assignment compatibility for the passed types * @param to The assignment to class * @param from The assignment from class * @return true if {@code from} and be assigned to {@code to}, false otherwise. */ public static boolean isValidAssignment(Class<?> to, Class<?> from) { if(to==null || from==null) return false; Primitive toP = PCLASS_TO_P.get(to); Primitive fromP = PCLASS_TO_P.get(from); if(toP==null && fromP==null) { return to.isAssignableFrom(from); } if(toP==null || fromP==null) { return false; } return toP.equals(fromP); } /** * Creates a new Primitive * @param uclazz the upconvert class for the primitive * @param pclazz the primitive class for the primitive * @param symbol The primitive JVM symbol */ private Primitive(Class<?> uclazz, Class<?> pclazz, String symbol) { this.uclazz = uclazz; this.pclazz = pclazz; this.symbol = symbol; } /** The primitive's upconvert class */ private final Class<?> uclazz; /** The primitive's primitive class */ private final Class<?> pclazz; /** The primitive symbol used in arrays */ private final String symbol; /** * Determines if the passed object is an upconvert for a primitive type * @param obj The object to test * @return true if the passed object type is an upconvert, false if not. */ public static boolean isPrimitive(Object obj) { if(obj==null) return false; return PNAME_TO_P.containsKey(obj.getClass()); } /** * Indicates if the passed symbol represents a primitive opcode as listed in table 4.2 of the JVM spec. * @param symbol The symbol to test which will be trimmed. * @return true if the passed symbol represents a primitive opcode, false otherwise */ public static boolean isPrimitive(String symbol) { if(symbol==null) return false; return SYMBOL_TO_P.containsKey(symbol.trim()); } /** * Returns the primitive for the passed primitive opcode as listed in table 4.2 of the JVM spec. * @param symbol The symbol to test which will be trimmed. * @return a Primitive enum member */ public static Primitive getForSymbol(String symbol) { if(symbol==null) throw new IllegalArgumentException("The passed symbol was null", new Throwable()); Primitive p = SYMBOL_TO_P.get(symbol.trim()); if(p==null) throw new IllegalArgumentException("The passed symbol [" + symbol.trim() + "] was not a primitive op code", new Throwable()); return p; } /** * Determines if the passed class is an upconvert for a primitive type * @param clazz The class to test * @return true if the passed type is an upconvert, false if not. */ public static boolean isPrimitive(Class<?> clazz) { if(clazz==null) return false; return PCLASS_TO_P.containsKey(clazz); } /** * Determines if the passed class can be represented as a primitive or a class * @param type the type to test * @return true if the passed class can be represented as a primitive or a class, * false if the passed class has no primitive counterpart or was null */ public static boolean isDual(Class<?> type) { if(type==null) return false; return isPrimitive(type) || UCLASS_TO_P.containsKey(type); } /** * Determines if the passed object's class can be represented as a primitive or a class * @param obj The object whose type will be tested * @return true if the passed object's class can be represented as a primitive or a class, * false if the passed class has no primitive counterpart or was null */ public static boolean isDual(Object obj) { if(obj==null) return false; Class<?> type = obj.getClass(); return isPrimitive(type) || UCLASS_TO_P.containsKey(type); } /** * If the passed type is a primitive or autoboxable, returns the pair array:<ol> * <li>The primitive</li> * <li>The autoboxable</li> * </ol> * @param type The primitive or autoboxable * @return A class array pair or null if the passed type is null or not a primitive or autoboxable */ public static Class<?>[] getAutoBoxPair(Class<?> type) { if(type==null || !isDual(type)) { return null; } Class<?>[] types = new Class[2]; if(isPrimitive(type)) { types[0] = type; types[1] = up(type); } else { types[0] = primitive(type); types[1] = type; } return types; } /** * Returns the upper class for the passed primitive class. * If not a primitive, returns the passed class * @param clazz The class to return the upper for * @return The upper of the passed primitive class or the upper class that was passed. */ public static Class<?> up(Class<?> clazz) { if(clazz==null) throw new IllegalArgumentException("Passed class was null", new Throwable()); if(isPrimitive(clazz)) { return get(clazz).uclazz; } else { return clazz; } } /** * Returns the primitive class for the passed upper class. * If not an upper class, returns the passed primitive * @param clazz The class to return the primitive for * @return The primitive of the passed upper class or the primitive class that was passed. */ public static Class<?> primitive(Class<?> clazz) { if(clazz==null) throw new IllegalArgumentException("Passed class was null", new Throwable()); if(isPrimitive(clazz)) { return clazz; } else { return get(clazz).pclazz; } } /** * Determines if the passed class name is a primitive type * @param name The class name to test * @return true if the passed type is a primitive, false if not. */ public static boolean isPrimitiveName(String name) { if(name==null) return false; return PNAME_TO_P.containsKey(name); } /** * Returns the Primitive enum for the passed name * @param name The primitive class name * @return A primitive or null */ public static Primitive getPrimitive(String name) { return PNAME_TO_P.get(name); } /** * Returns the Primitive enum for the passed object. * Throws a runtime exception if the passed object is not a primitive upconvert. * @param obj The object to get the Primitive enum for * @return the Primitive or null if the passed object was null. */ public static Primitive get(Object obj) { if(obj==null) return null; if(!isPrimitive(obj)) throw new RuntimeException("The type [" + obj.getClass().getName() + "] is not primitive or an upconvert"); return UCLASS_TO_P.get(obj.getClass()); } /** * Returns the Primitive enum for the passed class. * Throws a runtime exception if the passed object is not a primitive or upconvert. * @param clazz The class to get the Primitive enum for * @return the Primitive or null if the passed class was null. */ public static Primitive get(Class<?> clazz) { if(clazz==null) return null; //if(!isPrimitive(clazz)) throw new RuntimeException("The type [" + clazz.getName() + "] is not primitive or an upconvert"); Primitive p = UCLASS_TO_P.get(clazz); if(p==null) { p = PCLASS_TO_P.get(clazz); } if(p==null) { throw new RuntimeException("Failed to match the type [" + clazz.getName() + "] which we thought was a primitive or an upconvert"); } return p; } /** * Renders the primitive info as a string * @return a string describing the primitive */ public String toString() { StringBuilder b = new StringBuilder(this.name()); b.append("\n\tPrimitive Class:").append(pclazz.getName()); b.append("\n\tUpConvert Class:").append(uclazz.getName()); return b.toString(); } public static void log(Object message) { System.out.println(message); } /** * Returns the primitive's upconvert class * @return the primitive's upconvert class */ public Class<?> getUclazz() { return uclazz; } /** * Returns the primitive's downconvert class * @return the primitive's downconvert class */ public Class<?> getPclazz() { return pclazz; } }