| /* |
| $Id$ created on 25.10.2005 |
| |
| Copyright 2003 (C) James Strachan and Bob Mcwhirter. All Rights Reserved. |
| |
| Redistribution and use of this software and associated documentation |
| ("Software"), with or without modification, are permitted provided |
| that the following conditions are met: |
| |
| 1. Redistributions of source code must retain copyright |
| statements and notices. Redistributions must also contain a |
| copy of this document. |
| |
| 2. Redistributions in binary form must reproduce the |
| above copyright notice, this list of conditions and the |
| following disclaimer in the documentation and/or other |
| materials provided with the distribution. |
| |
| 3. The name "groovy" must not be used to endorse or promote |
| products derived from this Software without prior written |
| permission of The Codehaus. For written permission, |
| please contact info@codehaus.org. |
| |
| 4. Products derived from this Software may not be called "groovy" |
| nor may "groovy" appear in their names without prior written |
| permission of The Codehaus. "groovy" is a registered |
| trademark of The Codehaus. |
| |
| 5. Due credit should be given to The Codehaus - |
| http://groovy.codehaus.org/ |
| |
| THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS |
| ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT |
| NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND |
| FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL |
| THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, |
| INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
| STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED |
| OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| package org.codehaus.groovy.ast; |
| |
| import groovy.lang.Closure; |
| import groovy.lang.GString; |
| import groovy.lang.MetaClass; |
| import groovy.lang.Range; |
| import groovy.lang.Reference; |
| import groovy.lang.Script; |
| |
| import java.math.BigDecimal; |
| import java.math.BigInteger; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.regex.Pattern; |
| |
| import org.objectweb.asm.Opcodes; |
| |
| /** |
| * This class is a Helper for ClassNode and classes handling ClassNodes. |
| * It does contain a set of predefined ClassNodes for the most used |
| * types and some code for cached ClassNode creation and basic |
| * ClassNode handling |
| * |
| * @author Jochen Theodorou |
| */ |
| public class ClassHelper { |
| |
| |
| private static String[] names = new String[] { |
| boolean.class.getName(), char.class.getName(), |
| byte.class.getName(), short.class.getName(), |
| int.class.getName(), long.class.getName(), |
| double.class.getName(), float.class.getName(), |
| Object.class.getName(), Void.TYPE.getName(), |
| Closure.class.getName(), GString.class.getName(), |
| List.class.getName(), Map.class.getName(), |
| Range.class.getName(), Pattern.class.getName(), |
| Script.class.getName(), String.class.getName(), |
| Boolean.class.getName(), Character.class.getName(), |
| Byte.class.getName(), Short.class.getName(), |
| Integer.class.getName(), Long.class.getName(), |
| Double.class.getName(), Float.class.getName(), |
| BigDecimal.class.getName(), BigInteger.class.getName(), |
| Void.class.getName(), Reference.class.getName(), |
| Class.class.getName(), MetaClass.class.getName() |
| }; |
| |
| private static Class[] classes = new Class[] { |
| Object.class, Boolean.TYPE, Character.TYPE, Byte.TYPE, Short.TYPE, |
| Integer.TYPE, Long.TYPE, Double.TYPE, Float.TYPE, Void.TYPE, |
| Closure.class, GString.class, List.class, Map.class, Range.class, |
| Pattern.class, Script.class, String.class, Boolean.class, |
| Character.class, Byte.class, Short.class, Integer.class, Long.class, |
| Double.class, Float.class, BigDecimal.class, BigInteger.class, Void.class, |
| Reference.class, Class.class, MetaClass.class |
| }; |
| |
| public static final ClassNode |
| DYNAMIC_TYPE = new ClassNode(Object.class), OBJECT_TYPE = DYNAMIC_TYPE, |
| VOID_TYPE = new ClassNode(Void.TYPE), CLOSURE_TYPE = new ClassNode(Closure.class), |
| GSTRING_TYPE = new ClassNode(GString.class), LIST_TYPE = new ClassNode(List.class), |
| MAP_TYPE = new ClassNode(Map.class), RANGE_TYPE = new ClassNode(Range.class), |
| PATTERN_TYPE = new ClassNode(Pattern.class), STRING_TYPE = new ClassNode(String.class), |
| SCRIPT_TYPE = new ClassNode(Script.class), REFERENCE_TYPE = new ClassNode(Reference.class), |
| |
| boolean_TYPE = new ClassNode(boolean.class), char_TYPE = new ClassNode(char.class), |
| byte_TYPE = new ClassNode(byte.class), int_TYPE = new ClassNode(int.class), |
| long_TYPE = new ClassNode(long.class), short_TYPE = new ClassNode(short.class), |
| double_TYPE = new ClassNode(double.class), float_TYPE = new ClassNode(float.class), |
| Byte_TYPE = new ClassNode(Byte.class), Short_TYPE = new ClassNode(Short.class), |
| Integer_TYPE = new ClassNode(Integer.class), Long_TYPE = new ClassNode(Long.class), |
| Character_TYPE = new ClassNode(Character.class), Float_TYPE = new ClassNode(Float.class), |
| Double_TYPE = new ClassNode(Double.class), Boolean_TYPE = new ClassNode(Boolean.class), |
| BigInteger_TYPE = new ClassNode(java.math.BigInteger.class), |
| BigDecimal_TYPE = new ClassNode(java.math.BigDecimal.class), |
| void_WRAPPER_TYPE = new ClassNode(Void.class), |
| |
| CLASS_Type = new ClassNode(Class.class), METACLASS_TYPE = new ClassNode(MetaClass.class); |
| |
| |
| private static ClassNode[] types = new ClassNode[] { |
| OBJECT_TYPE, |
| boolean_TYPE, char_TYPE, byte_TYPE, short_TYPE, |
| int_TYPE, long_TYPE, double_TYPE, float_TYPE, |
| VOID_TYPE, CLOSURE_TYPE, GSTRING_TYPE, |
| LIST_TYPE, MAP_TYPE, RANGE_TYPE, PATTERN_TYPE, |
| SCRIPT_TYPE, STRING_TYPE, Boolean_TYPE, Character_TYPE, |
| Byte_TYPE, Short_TYPE, Integer_TYPE, Long_TYPE, |
| Double_TYPE, Float_TYPE, BigDecimal_TYPE, BigInteger_TYPE, |
| void_WRAPPER_TYPE, REFERENCE_TYPE, CLASS_Type, METACLASS_TYPE |
| }; |
| |
| |
| private static ClassNode[] numbers = new ClassNode[] { |
| char_TYPE, byte_TYPE, short_TYPE, int_TYPE, long_TYPE, |
| double_TYPE, float_TYPE, Short_TYPE, Byte_TYPE, Character_TYPE, |
| Integer_TYPE, Float_TYPE, Long_TYPE, Double_TYPE, BigInteger_TYPE, |
| BigDecimal_TYPE |
| }; |
| |
| protected static final ClassNode[] EMPTY_TYPE_ARRAY = {}; |
| |
| public static final String OBJECT = "java.lang.Object"; |
| |
| |
| /** |
| * Creates an array of ClassNodes using an array of classes. |
| * For each of the given classes a new ClassNode will be |
| * created |
| * @see #make(Class) |
| * @param classes an array of classes used to create the ClassNodes |
| * @return an array of ClassNodes |
| */ |
| public static ClassNode[] make(Class[] classes) { |
| ClassNode[] cns = new ClassNode[classes.length]; |
| for (int i=0; i<cns.length; i++) { |
| cns[i] = make(classes[i]); |
| } |
| |
| return cns; |
| } |
| |
| /** |
| * Creates a ClassNode using a given class. |
| * A new ClassNode object is only created if the class |
| * is not one of the predefined ones |
| * |
| * @param c class used to created the ClassNode |
| * @return ClassNode instance created from the given class |
| */ |
| public static ClassNode make(Class c) { |
| for (int i=0; i<classes.length; i++) { |
| if (c==classes[i]) return types[i]; |
| } |
| if (c.isArray()) { |
| ClassNode cn = make(c.getComponentType()); |
| return cn.makeArray(); |
| } |
| ClassNode t = new ClassNode(c); |
| return t; |
| } |
| |
| /** |
| * Creates a ClassNode using a given class. |
| * Unlike make(String) this method will not use the cache |
| * to create the ClassNode. This means the ClassNode created |
| * from this method using the same name will have a different |
| * references |
| * |
| * @see #make(String) |
| * @param name of the class the ClassNode is representing |
| */ |
| public static ClassNode makeWithoutCaching(String name) { |
| ClassNode cn = new ClassNode(name,Opcodes.ACC_PUBLIC,OBJECT_TYPE); |
| cn.isPrimaryNode = false; |
| return cn; |
| } |
| |
| /** |
| * Creates a ClassNode using a given class. |
| * If the name is one of the predefined ClassNodes then the |
| * corresponding ClassNode instance will be returned. If the |
| * is null of of length 0 the dynamic type is returned |
| * |
| * @param name of the class the ClassNode is representing |
| */ |
| public static ClassNode make(String name) { |
| if (name == null || name.length() == 0) return DYNAMIC_TYPE; |
| |
| for (int i=0; i<classes.length; i++) { |
| String cname = classes[i].getName(); |
| if (name.equals(cname)) return types[i]; |
| } |
| return makeWithoutCaching(name); |
| } |
| |
| /** |
| * Creates a ClassNode containing the wrapper of a ClassNode |
| * of primitive type. Any ClassNode representing a primitive |
| * type should be created using the predefined types used in |
| * class. The method will check the parameter for known |
| * references of ClassNode representing a primitive type. If |
| * Reference is found, then a ClassNode will be contained that |
| * represents the wrapper class. For exmaple for boolean, the |
| * wrapper class is java.lang.Boolean. |
| * |
| * If the parameter is no primitve type, the redirected |
| * ClassNode will be returned |
| * |
| * @see #make(Class) |
| * @see #make(String) |
| * @param cn the ClassNode containing a possible primitive type |
| */ |
| public static ClassNode getWrapper(ClassNode cn) { |
| cn = cn.redirect(); |
| if (!isPrimitiveType(cn)) return cn; |
| if (cn==boolean_TYPE) { |
| return Boolean_TYPE; |
| } else if (cn==byte_TYPE) { |
| return Byte_TYPE; |
| } else if (cn==char_TYPE) { |
| return Character_TYPE; |
| } else if (cn==short_TYPE) { |
| return Short_TYPE; |
| } else if (cn==int_TYPE) { |
| return Integer_TYPE; |
| } else if (cn==long_TYPE) { |
| return Long_TYPE; |
| } else if (cn==float_TYPE) { |
| return Float_TYPE; |
| } else if (cn==double_TYPE) { |
| return Double_TYPE; |
| } else if (cn==VOID_TYPE) { |
| return void_WRAPPER_TYPE; |
| } |
| else { |
| return cn; |
| } |
| } |
| |
| /** |
| * Test to determine if a ClasNode is a primitve type. |
| * Note: this only works for ClassNodes created using a |
| * predefined ClassNode |
| * |
| * @see #make(Class) |
| * @see #make(String) |
| * @param cn the ClassNode containing a possible primitive type |
| * @return true if the ClassNode is a primitve type |
| */ |
| public static boolean isPrimitiveType(ClassNode cn) { |
| return cn == boolean_TYPE || |
| cn == char_TYPE || |
| cn == byte_TYPE || |
| cn == short_TYPE || |
| cn == int_TYPE || |
| cn == long_TYPE || |
| cn == float_TYPE || |
| cn == double_TYPE || |
| cn == VOID_TYPE; |
| } |
| |
| public static ClassNode makeReference() { |
| return make(Reference.class); |
| } |
| |
| } |