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.
 120      * Otherwise return {@code this}.
 121      *
 122      * <p>
 123      * For example, for "int", this method returns "java.lang.Integer".
 124      */
 125     public abstract JClass boxify();
 126 
 127     /**
 128      * If this class is a wrapper type for a primitive, return the primitive type.
 129      * Otherwise return {@code this}.
 130      *
 131      * <p>
 132      * For example, for "java.lang.Integer", this method returns "int".
 133      */
 134     public abstract JType unboxify();
 135 
 136     /**
 137      * Returns the erasure of this type.
 138      */
 139     public JType erasure() {
 140         return this;
 141     }
 142 
 143     /**
 144      * Returns true if this is a referenced type.
 145      */
 146     public final boolean isReference() {
 147         return !isPrimitive();
 148     }
 149 
 150     /**
 151      * If this is an array, returns the component type of the array.
 152      * (T of T[])
 153      */
 154     public JType elementType() {
 155         throw new IllegalArgumentException("Not an array type");
 156     }
 157 
 158     public String toString() {
 159         return this.getClass().getName()
 160                 + '(' + fullName() + ')';
 161     }
 162 
 163     /**
 164      * Compare two JTypes by FQCN, giving sorting precedence to types
 165      * that belong to packages java and javax over all others.
 166      *
 167      * This method is used to sort generated import statments in a
 168      * conventional way for readability.
 169      */
 170     public int compareTo(JType o) {
 171         final String rhs = o.fullName();
 172         boolean p = fullName().startsWith("java");
 173         boolean q = rhs.startsWith("java");
 174 
 175         if( p && !q ) {
 176             return -1;
 177         } else if( !p && q ) {
 178             return 1;
 179         } else {
 180             return fullName().compareTo(rhs);
 181         }
 182     }
 183 }