1 /*
   2  * Copyright (c) 1997, 2012, 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 package com.sun.codemodel.internal;
  27 
  28 
  29 /**
  30  * A representation of a type in codeModel.
  31  *
  32  * A type is always either primitive ({@link JPrimitiveType}) or
  33  * a reference type ({@link JClass}).
  34  */
  35 public abstract class JType implements JGenerable, Comparable<JType> {
  36 
  37     /**
  38      * Obtains a reference to the primitive type object from a type name.
  39      */
  40     public static JPrimitiveType parse(JCodeModel codeModel, String typeName) {
  41         if (typeName.equals("void"))
  42             return codeModel.VOID;
  43         else if (typeName.equals("boolean"))
  44             return codeModel.BOOLEAN;
  45         else if (typeName.equals("byte"))
  46             return codeModel.BYTE;
  47         else if (typeName.equals("short"))
  48             return codeModel.SHORT;
  49         else if (typeName.equals("char"))
  50             return codeModel.CHAR;
  51         else if (typeName.equals("int"))
  52             return codeModel.INT;
  53         else if (typeName.equals("float"))
  54             return codeModel.FLOAT;
  55         else if (typeName.equals("long"))
  56             return codeModel.LONG;
  57         else if (typeName.equals("double"))
  58             return codeModel.DOUBLE;
  59         else
  60             throw new IllegalArgumentException("Not a primitive type: " + typeName);
  61     }
  62 
  63     /** Gets the owner code model object. */
  64     public abstract JCodeModel owner();
  65 
  66     /**
  67      * Gets the full name of the type.
  68      *
  69      * See http://java.sun.com/docs/books/jls/second_edition/html/names.doc.html#25430 for the details.
  70      *
  71      * @return
  72      *      Strings like "int", "java.lang.String",
  73      *      "java.io.File[]". Never null.
  74      */
  75     public abstract String fullName();
  76 
  77     /**
  78      * Gets the binary name of the type.
  79      *
  80      * See http://java.sun.com/docs/books/jls/third_edition/html/binaryComp.html#44909
  81      *
  82      * @return
  83      *      Name like "Foo$Bar", "int", "java.lang.String", "java.io.File[]". Never null.
  84      */
  85     public String binaryName() {
  86         return fullName();
  87     }
  88 
  89     /**
  90      * Gets the name of this type.
  91      *
  92      * @return
  93      *     Names like "int", "void", "BigInteger".
  94      */
  95     public abstract String name();
  96 
  97     /**
  98      * Create an array type of this type.
  99      *
 100      * This method is undefined for primitive void type, which
 101      * doesn't have any corresponding array representation.
 102      *
 103      * @return A {@link JClass} representing the array type
 104      *         whose element type is this type
 105      */
 106     public abstract JClass array();
 107 
 108     /** Tell whether or not this is an array type. */
 109     public boolean isArray() {
 110         return false;
 111     }
 112 
 113     /** Tell whether or not this is a built-in primitive type, such as int or void. */
 114     public boolean isPrimitive() {
 115         return false;
 116     }
 117 
 118     /**
 119      * If this class is a primitive type, return the boxed class. Otherwise return <tt>this</tt>.
 120      *
 121      * <p>
 122      * For example, for "int", this method returns "java.lang.Integer".
 123      */
 124     public abstract JClass boxify();
 125 
 126     /**
 127      * If this class is a wrapper type for a primitive, return the primitive type.
 128      * Otherwise return <tt>this</tt>.
 129      *
 130      * <p>
 131      * For example, for "java.lang.Integer", this method returns "int".
 132      */
 133     public abstract JType unboxify();
 134 
 135     /**
 136      * Returns the erasure of this type.
 137      */
 138     public JType erasure() {
 139         return this;
 140     }
 141 
 142     /**
 143      * Returns true if this is a referenced type.
 144      */
 145     public final boolean isReference() {
 146         return !isPrimitive();
 147     }
 148 
 149     /**
 150      * If this is an array, returns the component type of the array.
 151      * (T of T[])
 152      */
 153     public JType elementType() {
 154         throw new IllegalArgumentException("Not an array type");
 155     }
 156 
 157     public String toString() {
 158         return this.getClass().getName()
 159                 + '(' + fullName() + ')';
 160     }
 161 
 162     /**
 163      * Compare two JTypes by FQCN, giving sorting precedence to types
 164      * that belong to packages java and javax over all others.
 165      *
 166      * This method is used to sort generated import statments in a
 167      * conventional way for readability.
 168      */
 169     public int compareTo(JType o) {
 170         final String rhs = o.fullName();
 171         boolean p = fullName().startsWith("java");
 172         boolean q = rhs.startsWith("java");
 173 
 174         if( p && !q ) {
 175             return -1;
 176         } else if( !p && q ) {
 177             return 1;
 178         } else {
 179             return fullName().compareTo(rhs);
 180         }
 181     }
 182 }