jaxws/src/share/classes/com/sun/codemodel/internal/JCodeModel.java
author tbell
Mon, 20 Apr 2009 15:14:39 -0700
changeset 2678 57cf2a1c1a05
parent 8 474761f14bca
permissions -rw-r--r--
6831313: update jaxws in OpenJDK7 to 2.1 plus bug fixes from OpenJDK 6 6672868: Package javax.xml.ws.wsaddressing not included in make/docs/CORE_PKGS.gmk Reviewed-by: darcy
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
8
474761f14bca Initial load
duke
parents:
diff changeset
     1
/*
2678
57cf2a1c1a05 6831313: update jaxws in OpenJDK7 to 2.1 plus bug fixes from OpenJDK 6
tbell
parents: 8
diff changeset
     2
 * Copyright 2005-2006 Sun Microsystems, Inc.  All Rights Reserved.
8
474761f14bca Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
474761f14bca Initial load
duke
parents:
diff changeset
     4
 *
474761f14bca Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
474761f14bca Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
474761f14bca Initial load
duke
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Sun designates this
474761f14bca Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
474761f14bca Initial load
duke
parents:
diff changeset
     9
 * by Sun in the LICENSE file that accompanied this code.
474761f14bca Initial load
duke
parents:
diff changeset
    10
 *
474761f14bca Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
474761f14bca Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
474761f14bca Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
474761f14bca Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
474761f14bca Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
474761f14bca Initial load
duke
parents:
diff changeset
    16
 *
474761f14bca Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
474761f14bca Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
474761f14bca Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
474761f14bca Initial load
duke
parents:
diff changeset
    20
 *
474761f14bca Initial load
duke
parents:
diff changeset
    21
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
474761f14bca Initial load
duke
parents:
diff changeset
    22
 * CA 95054 USA or visit www.sun.com if you need additional information or
474761f14bca Initial load
duke
parents:
diff changeset
    23
 * have any questions.
474761f14bca Initial load
duke
parents:
diff changeset
    24
 */
474761f14bca Initial load
duke
parents:
diff changeset
    25
474761f14bca Initial load
duke
parents:
diff changeset
    26
package com.sun.codemodel.internal;
474761f14bca Initial load
duke
parents:
diff changeset
    27
474761f14bca Initial load
duke
parents:
diff changeset
    28
import java.io.File;
474761f14bca Initial load
duke
parents:
diff changeset
    29
import java.io.IOException;
474761f14bca Initial load
duke
parents:
diff changeset
    30
import java.io.PrintStream;
474761f14bca Initial load
duke
parents:
diff changeset
    31
import java.lang.reflect.Modifier;
474761f14bca Initial load
duke
parents:
diff changeset
    32
import java.util.ArrayList;
474761f14bca Initial load
duke
parents:
diff changeset
    33
import java.util.Collections;
474761f14bca Initial load
duke
parents:
diff changeset
    34
import java.util.HashMap;
474761f14bca Initial load
duke
parents:
diff changeset
    35
import java.util.Iterator;
474761f14bca Initial load
duke
parents:
diff changeset
    36
import java.util.List;
474761f14bca Initial load
duke
parents:
diff changeset
    37
import java.util.Map;
474761f14bca Initial load
duke
parents:
diff changeset
    38
474761f14bca Initial load
duke
parents:
diff changeset
    39
import com.sun.codemodel.internal.writer.FileCodeWriter;
474761f14bca Initial load
duke
parents:
diff changeset
    40
import com.sun.codemodel.internal.writer.ProgressCodeWriter;
474761f14bca Initial load
duke
parents:
diff changeset
    41
474761f14bca Initial load
duke
parents:
diff changeset
    42
474761f14bca Initial load
duke
parents:
diff changeset
    43
/**
474761f14bca Initial load
duke
parents:
diff changeset
    44
 * Root of the code DOM.
474761f14bca Initial load
duke
parents:
diff changeset
    45
 *
474761f14bca Initial load
duke
parents:
diff changeset
    46
 * <p>
474761f14bca Initial load
duke
parents:
diff changeset
    47
 * Here's your typical CodeModel application.
474761f14bca Initial load
duke
parents:
diff changeset
    48
 *
474761f14bca Initial load
duke
parents:
diff changeset
    49
 * <pre>
474761f14bca Initial load
duke
parents:
diff changeset
    50
 * JCodeModel cm = new JCodeModel();
474761f14bca Initial load
duke
parents:
diff changeset
    51
 *
474761f14bca Initial load
duke
parents:
diff changeset
    52
 * // generate source code by populating the 'cm' tree.
474761f14bca Initial load
duke
parents:
diff changeset
    53
 * cm._class(...);
474761f14bca Initial load
duke
parents:
diff changeset
    54
 * ...
474761f14bca Initial load
duke
parents:
diff changeset
    55
 *
474761f14bca Initial load
duke
parents:
diff changeset
    56
 * // write them out
474761f14bca Initial load
duke
parents:
diff changeset
    57
 * cm.build(new File("."));
474761f14bca Initial load
duke
parents:
diff changeset
    58
 * </pre>
474761f14bca Initial load
duke
parents:
diff changeset
    59
 *
474761f14bca Initial load
duke
parents:
diff changeset
    60
 * <p>
474761f14bca Initial load
duke
parents:
diff changeset
    61
 * Every CodeModel node is always owned by one {@link JCodeModel} object
474761f14bca Initial load
duke
parents:
diff changeset
    62
 * at any given time (which can be often accesesd by the <tt>owner()</tt> method.)
474761f14bca Initial load
duke
parents:
diff changeset
    63
 *
474761f14bca Initial load
duke
parents:
diff changeset
    64
 * As such, when you generate Java code, most of the operation works
474761f14bca Initial load
duke
parents:
diff changeset
    65
 * in a top-down fashion. For example, you create a class from {@link JCodeModel},
474761f14bca Initial load
duke
parents:
diff changeset
    66
 * which gives you a {@link JDefinedClass}. Then you invoke a method on it
474761f14bca Initial load
duke
parents:
diff changeset
    67
 * to generate a new method, which gives you {@link JMethod}, and so on.
474761f14bca Initial load
duke
parents:
diff changeset
    68
 *
474761f14bca Initial load
duke
parents:
diff changeset
    69
 * There are a few exceptions to this, most notably building {@link JExpression}s,
474761f14bca Initial load
duke
parents:
diff changeset
    70
 * but generally you work with CodeModel in a top-down fashion.
474761f14bca Initial load
duke
parents:
diff changeset
    71
 *
474761f14bca Initial load
duke
parents:
diff changeset
    72
 * Because of this design, most of the CodeModel classes aren't directly instanciable.
474761f14bca Initial load
duke
parents:
diff changeset
    73
 *
474761f14bca Initial load
duke
parents:
diff changeset
    74
 *
474761f14bca Initial load
duke
parents:
diff changeset
    75
 * <h2>Where to go from here?</h2>
474761f14bca Initial load
duke
parents:
diff changeset
    76
 * <p>
474761f14bca Initial load
duke
parents:
diff changeset
    77
 * Most of the time you'd want to populate new type definitions in a {@link JCodeModel}.
474761f14bca Initial load
duke
parents:
diff changeset
    78
 * See {@link #_class(String, ClassType)}.
474761f14bca Initial load
duke
parents:
diff changeset
    79
 */
474761f14bca Initial load
duke
parents:
diff changeset
    80
public final class JCodeModel {
474761f14bca Initial load
duke
parents:
diff changeset
    81
474761f14bca Initial load
duke
parents:
diff changeset
    82
    /** The packages that this JCodeWriter contains. */
474761f14bca Initial load
duke
parents:
diff changeset
    83
    private HashMap<String,JPackage> packages = new HashMap<String,JPackage>();
474761f14bca Initial load
duke
parents:
diff changeset
    84
474761f14bca Initial load
duke
parents:
diff changeset
    85
    /** All JReferencedClasses are pooled here. */
474761f14bca Initial load
duke
parents:
diff changeset
    86
    private final HashMap<Class,JReferencedClass> refClasses = new HashMap<Class,JReferencedClass>();
474761f14bca Initial load
duke
parents:
diff changeset
    87
474761f14bca Initial load
duke
parents:
diff changeset
    88
474761f14bca Initial load
duke
parents:
diff changeset
    89
    /** Obtains a reference to the special "null" type. */
474761f14bca Initial load
duke
parents:
diff changeset
    90
    public final JNullType NULL = new JNullType(this);
474761f14bca Initial load
duke
parents:
diff changeset
    91
    // primitive types
474761f14bca Initial load
duke
parents:
diff changeset
    92
    public final JPrimitiveType VOID    = new JPrimitiveType(this,"void",   Void.class);
474761f14bca Initial load
duke
parents:
diff changeset
    93
    public final JPrimitiveType BOOLEAN = new JPrimitiveType(this,"boolean",Boolean.class);
474761f14bca Initial load
duke
parents:
diff changeset
    94
    public final JPrimitiveType BYTE    = new JPrimitiveType(this,"byte",   Byte.class);
474761f14bca Initial load
duke
parents:
diff changeset
    95
    public final JPrimitiveType SHORT   = new JPrimitiveType(this,"short",  Short.class);
474761f14bca Initial load
duke
parents:
diff changeset
    96
    public final JPrimitiveType CHAR    = new JPrimitiveType(this,"char",   Character.class);
474761f14bca Initial load
duke
parents:
diff changeset
    97
    public final JPrimitiveType INT     = new JPrimitiveType(this,"int",    Integer.class);
474761f14bca Initial load
duke
parents:
diff changeset
    98
    public final JPrimitiveType FLOAT   = new JPrimitiveType(this,"float",  Float.class);
474761f14bca Initial load
duke
parents:
diff changeset
    99
    public final JPrimitiveType LONG    = new JPrimitiveType(this,"long",   Long.class);
474761f14bca Initial load
duke
parents:
diff changeset
   100
    public final JPrimitiveType DOUBLE  = new JPrimitiveType(this,"double", Double.class);
474761f14bca Initial load
duke
parents:
diff changeset
   101
474761f14bca Initial load
duke
parents:
diff changeset
   102
    /**
474761f14bca Initial load
duke
parents:
diff changeset
   103
     * If the flag is true, we will consider two classes "Foo" and "foo"
474761f14bca Initial load
duke
parents:
diff changeset
   104
     * as a collision.
474761f14bca Initial load
duke
parents:
diff changeset
   105
     */
474761f14bca Initial load
duke
parents:
diff changeset
   106
    protected static final boolean isCaseSensitiveFileSystem = getFileSystemCaseSensitivity();
474761f14bca Initial load
duke
parents:
diff changeset
   107
474761f14bca Initial load
duke
parents:
diff changeset
   108
    private static boolean getFileSystemCaseSensitivity() {
474761f14bca Initial load
duke
parents:
diff changeset
   109
        try {
474761f14bca Initial load
duke
parents:
diff changeset
   110
            // let the system property override, in case the user really
474761f14bca Initial load
duke
parents:
diff changeset
   111
            // wants to override.
474761f14bca Initial load
duke
parents:
diff changeset
   112
            if( System.getProperty("com.sun.codemodel.internal.FileSystemCaseSensitive")!=null )
474761f14bca Initial load
duke
parents:
diff changeset
   113
                return true;
474761f14bca Initial load
duke
parents:
diff changeset
   114
        } catch( Exception e ) {}
474761f14bca Initial load
duke
parents:
diff changeset
   115
474761f14bca Initial load
duke
parents:
diff changeset
   116
        // on Unix, it's case sensitive.
474761f14bca Initial load
duke
parents:
diff changeset
   117
        return (File.separatorChar == '/');
474761f14bca Initial load
duke
parents:
diff changeset
   118
    }
474761f14bca Initial load
duke
parents:
diff changeset
   119
474761f14bca Initial load
duke
parents:
diff changeset
   120
474761f14bca Initial load
duke
parents:
diff changeset
   121
    public JCodeModel() {}
474761f14bca Initial load
duke
parents:
diff changeset
   122
474761f14bca Initial load
duke
parents:
diff changeset
   123
    /**
474761f14bca Initial load
duke
parents:
diff changeset
   124
     * Add a package to the list of packages to be generated
474761f14bca Initial load
duke
parents:
diff changeset
   125
     *
474761f14bca Initial load
duke
parents:
diff changeset
   126
     * @param name
474761f14bca Initial load
duke
parents:
diff changeset
   127
     *        Name of the package. Use "" to indicate the root package.
474761f14bca Initial load
duke
parents:
diff changeset
   128
     *
474761f14bca Initial load
duke
parents:
diff changeset
   129
     * @return Newly generated package
474761f14bca Initial load
duke
parents:
diff changeset
   130
     */
474761f14bca Initial load
duke
parents:
diff changeset
   131
    public JPackage _package(String name) {
474761f14bca Initial load
duke
parents:
diff changeset
   132
        JPackage p = packages.get(name);
474761f14bca Initial load
duke
parents:
diff changeset
   133
        if (p == null) {
474761f14bca Initial load
duke
parents:
diff changeset
   134
            p = new JPackage(name, this);
474761f14bca Initial load
duke
parents:
diff changeset
   135
            packages.put(name, p);
474761f14bca Initial load
duke
parents:
diff changeset
   136
        }
474761f14bca Initial load
duke
parents:
diff changeset
   137
        return p;
474761f14bca Initial load
duke
parents:
diff changeset
   138
    }
474761f14bca Initial load
duke
parents:
diff changeset
   139
474761f14bca Initial load
duke
parents:
diff changeset
   140
    public final JPackage rootPackage() {
474761f14bca Initial load
duke
parents:
diff changeset
   141
        return _package("");
474761f14bca Initial load
duke
parents:
diff changeset
   142
    }
474761f14bca Initial load
duke
parents:
diff changeset
   143
474761f14bca Initial load
duke
parents:
diff changeset
   144
    /**
474761f14bca Initial load
duke
parents:
diff changeset
   145
     * Returns an iterator that walks the packages defined using this code
474761f14bca Initial load
duke
parents:
diff changeset
   146
     * writer.
474761f14bca Initial load
duke
parents:
diff changeset
   147
     */
474761f14bca Initial load
duke
parents:
diff changeset
   148
    public Iterator<JPackage> packages() {
474761f14bca Initial load
duke
parents:
diff changeset
   149
        return packages.values().iterator();
474761f14bca Initial load
duke
parents:
diff changeset
   150
    }
474761f14bca Initial load
duke
parents:
diff changeset
   151
474761f14bca Initial load
duke
parents:
diff changeset
   152
    /**
474761f14bca Initial load
duke
parents:
diff changeset
   153
     * Creates a new generated class.
474761f14bca Initial load
duke
parents:
diff changeset
   154
     *
474761f14bca Initial load
duke
parents:
diff changeset
   155
     * @exception JClassAlreadyExistsException
474761f14bca Initial load
duke
parents:
diff changeset
   156
     *      When the specified class/interface was already created.
474761f14bca Initial load
duke
parents:
diff changeset
   157
     */
474761f14bca Initial load
duke
parents:
diff changeset
   158
    public JDefinedClass _class(String fullyqualifiedName) throws JClassAlreadyExistsException {
474761f14bca Initial load
duke
parents:
diff changeset
   159
        return _class(fullyqualifiedName,ClassType.CLASS);
474761f14bca Initial load
duke
parents:
diff changeset
   160
    }
474761f14bca Initial load
duke
parents:
diff changeset
   161
474761f14bca Initial load
duke
parents:
diff changeset
   162
    /**
474761f14bca Initial load
duke
parents:
diff changeset
   163
     * Creates a dummy, unknown {@link JClass} that represents a given name.
474761f14bca Initial load
duke
parents:
diff changeset
   164
     *
474761f14bca Initial load
duke
parents:
diff changeset
   165
     * <p>
474761f14bca Initial load
duke
parents:
diff changeset
   166
     * This method is useful when the code generation needs to include the user-specified
474761f14bca Initial load
duke
parents:
diff changeset
   167
     * class that may or may not exist, and only thing known about it is a class name.
474761f14bca Initial load
duke
parents:
diff changeset
   168
     */
474761f14bca Initial load
duke
parents:
diff changeset
   169
    public JClass directClass(String name) {
474761f14bca Initial load
duke
parents:
diff changeset
   170
        return new JDirectClass(this,name);
474761f14bca Initial load
duke
parents:
diff changeset
   171
    }
474761f14bca Initial load
duke
parents:
diff changeset
   172
474761f14bca Initial load
duke
parents:
diff changeset
   173
    /**
474761f14bca Initial load
duke
parents:
diff changeset
   174
     * Creates a new generated class.
474761f14bca Initial load
duke
parents:
diff changeset
   175
     *
474761f14bca Initial load
duke
parents:
diff changeset
   176
     * @exception JClassAlreadyExistsException
474761f14bca Initial load
duke
parents:
diff changeset
   177
     *      When the specified class/interface was already created.
474761f14bca Initial load
duke
parents:
diff changeset
   178
     */
474761f14bca Initial load
duke
parents:
diff changeset
   179
    public JDefinedClass _class(String fullyqualifiedName,ClassType t) throws JClassAlreadyExistsException {
474761f14bca Initial load
duke
parents:
diff changeset
   180
        int idx = fullyqualifiedName.lastIndexOf('.');
474761f14bca Initial load
duke
parents:
diff changeset
   181
        if( idx<0 )     return rootPackage()._class(fullyqualifiedName);
474761f14bca Initial load
duke
parents:
diff changeset
   182
        else
474761f14bca Initial load
duke
parents:
diff changeset
   183
            return _package(fullyqualifiedName.substring(0,idx))
474761f14bca Initial load
duke
parents:
diff changeset
   184
                ._class( JMod.PUBLIC, fullyqualifiedName.substring(idx+1), t );
474761f14bca Initial load
duke
parents:
diff changeset
   185
    }
474761f14bca Initial load
duke
parents:
diff changeset
   186
474761f14bca Initial load
duke
parents:
diff changeset
   187
    /**
474761f14bca Initial load
duke
parents:
diff changeset
   188
     * Gets a reference to the already created generated class.
474761f14bca Initial load
duke
parents:
diff changeset
   189
     *
474761f14bca Initial load
duke
parents:
diff changeset
   190
     * @return null
474761f14bca Initial load
duke
parents:
diff changeset
   191
     *      If the class is not yet created.
474761f14bca Initial load
duke
parents:
diff changeset
   192
     * @see JPackage#_getClass(String)
474761f14bca Initial load
duke
parents:
diff changeset
   193
     */
474761f14bca Initial load
duke
parents:
diff changeset
   194
    public JDefinedClass _getClass(String fullyQualifiedName) {
474761f14bca Initial load
duke
parents:
diff changeset
   195
        int idx = fullyQualifiedName.lastIndexOf('.');
474761f14bca Initial load
duke
parents:
diff changeset
   196
        if( idx<0 )     return rootPackage()._getClass(fullyQualifiedName);
474761f14bca Initial load
duke
parents:
diff changeset
   197
        else
474761f14bca Initial load
duke
parents:
diff changeset
   198
            return _package(fullyQualifiedName.substring(0,idx))
474761f14bca Initial load
duke
parents:
diff changeset
   199
                ._getClass( fullyQualifiedName.substring(idx+1) );
474761f14bca Initial load
duke
parents:
diff changeset
   200
    }
474761f14bca Initial load
duke
parents:
diff changeset
   201
474761f14bca Initial load
duke
parents:
diff changeset
   202
    /**
474761f14bca Initial load
duke
parents:
diff changeset
   203
     * Creates a new anonymous class.
474761f14bca Initial load
duke
parents:
diff changeset
   204
     *
474761f14bca Initial load
duke
parents:
diff changeset
   205
     * @deprecated
474761f14bca Initial load
duke
parents:
diff changeset
   206
     *      The naming convention doesn't match the rest of the CodeModel.
474761f14bca Initial load
duke
parents:
diff changeset
   207
     *      Use {@link #anonymousClass(JClass)} instead.
474761f14bca Initial load
duke
parents:
diff changeset
   208
     */
474761f14bca Initial load
duke
parents:
diff changeset
   209
    public JDefinedClass newAnonymousClass(JClass baseType) {
474761f14bca Initial load
duke
parents:
diff changeset
   210
        return new JAnonymousClass(baseType);
474761f14bca Initial load
duke
parents:
diff changeset
   211
    }
474761f14bca Initial load
duke
parents:
diff changeset
   212
474761f14bca Initial load
duke
parents:
diff changeset
   213
    /**
474761f14bca Initial load
duke
parents:
diff changeset
   214
     * Creates a new anonymous class.
474761f14bca Initial load
duke
parents:
diff changeset
   215
     */
474761f14bca Initial load
duke
parents:
diff changeset
   216
    public JDefinedClass anonymousClass(JClass baseType) {
474761f14bca Initial load
duke
parents:
diff changeset
   217
        return new JAnonymousClass(baseType);
474761f14bca Initial load
duke
parents:
diff changeset
   218
    }
474761f14bca Initial load
duke
parents:
diff changeset
   219
474761f14bca Initial load
duke
parents:
diff changeset
   220
    public JDefinedClass anonymousClass(Class baseType) {
474761f14bca Initial load
duke
parents:
diff changeset
   221
        return anonymousClass(ref(baseType));
474761f14bca Initial load
duke
parents:
diff changeset
   222
    }
474761f14bca Initial load
duke
parents:
diff changeset
   223
474761f14bca Initial load
duke
parents:
diff changeset
   224
    /**
474761f14bca Initial load
duke
parents:
diff changeset
   225
     * Generates Java source code.
474761f14bca Initial load
duke
parents:
diff changeset
   226
     * A convenience method for <code>build(destDir,destDir,System.out)</code>.
474761f14bca Initial load
duke
parents:
diff changeset
   227
     *
474761f14bca Initial load
duke
parents:
diff changeset
   228
     * @param   destDir
474761f14bca Initial load
duke
parents:
diff changeset
   229
     *          source files are generated into this directory.
474761f14bca Initial load
duke
parents:
diff changeset
   230
     * @param   status
474761f14bca Initial load
duke
parents:
diff changeset
   231
     *      if non-null, progress indication will be sent to this stream.
474761f14bca Initial load
duke
parents:
diff changeset
   232
     */
474761f14bca Initial load
duke
parents:
diff changeset
   233
    public void build( File destDir, PrintStream status ) throws IOException {
474761f14bca Initial load
duke
parents:
diff changeset
   234
        build(destDir,destDir,status);
474761f14bca Initial load
duke
parents:
diff changeset
   235
    }
474761f14bca Initial load
duke
parents:
diff changeset
   236
474761f14bca Initial load
duke
parents:
diff changeset
   237
    /**
474761f14bca Initial load
duke
parents:
diff changeset
   238
     * Generates Java source code.
474761f14bca Initial load
duke
parents:
diff changeset
   239
     * A convenience method that calls {@link #build(CodeWriter,CodeWriter)}.
474761f14bca Initial load
duke
parents:
diff changeset
   240
     *
474761f14bca Initial load
duke
parents:
diff changeset
   241
     * @param   srcDir
474761f14bca Initial load
duke
parents:
diff changeset
   242
     *          Java source files are generated into this directory.
474761f14bca Initial load
duke
parents:
diff changeset
   243
     * @param   resourceDir
474761f14bca Initial load
duke
parents:
diff changeset
   244
     *          Other resource files are generated into this directory.
474761f14bca Initial load
duke
parents:
diff changeset
   245
     * @param   status
474761f14bca Initial load
duke
parents:
diff changeset
   246
     *      if non-null, progress indication will be sent to this stream.
474761f14bca Initial load
duke
parents:
diff changeset
   247
     */
474761f14bca Initial load
duke
parents:
diff changeset
   248
    public void build( File srcDir, File resourceDir, PrintStream status ) throws IOException {
474761f14bca Initial load
duke
parents:
diff changeset
   249
        CodeWriter src = new FileCodeWriter(srcDir);
474761f14bca Initial load
duke
parents:
diff changeset
   250
        CodeWriter res = new FileCodeWriter(resourceDir);
474761f14bca Initial load
duke
parents:
diff changeset
   251
        if(status!=null) {
474761f14bca Initial load
duke
parents:
diff changeset
   252
            src = new ProgressCodeWriter(src, status );
474761f14bca Initial load
duke
parents:
diff changeset
   253
            res = new ProgressCodeWriter(res, status );
474761f14bca Initial load
duke
parents:
diff changeset
   254
        }
474761f14bca Initial load
duke
parents:
diff changeset
   255
        build(src,res);
474761f14bca Initial load
duke
parents:
diff changeset
   256
    }
474761f14bca Initial load
duke
parents:
diff changeset
   257
474761f14bca Initial load
duke
parents:
diff changeset
   258
    /**
474761f14bca Initial load
duke
parents:
diff changeset
   259
     * A convenience method for <code>build(destDir,System.out)</code>.
474761f14bca Initial load
duke
parents:
diff changeset
   260
     */
474761f14bca Initial load
duke
parents:
diff changeset
   261
    public void build( File destDir ) throws IOException {
474761f14bca Initial load
duke
parents:
diff changeset
   262
        build(destDir,System.out);
474761f14bca Initial load
duke
parents:
diff changeset
   263
    }
474761f14bca Initial load
duke
parents:
diff changeset
   264
474761f14bca Initial load
duke
parents:
diff changeset
   265
    /**
474761f14bca Initial load
duke
parents:
diff changeset
   266
     * A convenience method for <code>build(srcDir,resourceDir,System.out)</code>.
474761f14bca Initial load
duke
parents:
diff changeset
   267
     */
474761f14bca Initial load
duke
parents:
diff changeset
   268
    public void build( File srcDir, File resourceDir ) throws IOException {
474761f14bca Initial load
duke
parents:
diff changeset
   269
        build(srcDir,resourceDir,System.out);
474761f14bca Initial load
duke
parents:
diff changeset
   270
    }
474761f14bca Initial load
duke
parents:
diff changeset
   271
474761f14bca Initial load
duke
parents:
diff changeset
   272
    /**
474761f14bca Initial load
duke
parents:
diff changeset
   273
     * A convenience method for <code>build(out,out)</code>.
474761f14bca Initial load
duke
parents:
diff changeset
   274
     */
474761f14bca Initial load
duke
parents:
diff changeset
   275
    public void build( CodeWriter out ) throws IOException {
474761f14bca Initial load
duke
parents:
diff changeset
   276
        build(out,out);
474761f14bca Initial load
duke
parents:
diff changeset
   277
    }
474761f14bca Initial load
duke
parents:
diff changeset
   278
474761f14bca Initial load
duke
parents:
diff changeset
   279
    /**
474761f14bca Initial load
duke
parents:
diff changeset
   280
     * Generates Java source code.
474761f14bca Initial load
duke
parents:
diff changeset
   281
     */
474761f14bca Initial load
duke
parents:
diff changeset
   282
    public void build( CodeWriter source, CodeWriter resource ) throws IOException {
474761f14bca Initial load
duke
parents:
diff changeset
   283
        JPackage[] pkgs = packages.values().toArray(new JPackage[packages.size()]);
474761f14bca Initial load
duke
parents:
diff changeset
   284
        // avoid concurrent modification exception
474761f14bca Initial load
duke
parents:
diff changeset
   285
        for( JPackage pkg : pkgs )
474761f14bca Initial load
duke
parents:
diff changeset
   286
            pkg.build(source,resource);
474761f14bca Initial load
duke
parents:
diff changeset
   287
        source.close();
474761f14bca Initial load
duke
parents:
diff changeset
   288
        resource.close();
474761f14bca Initial load
duke
parents:
diff changeset
   289
    }
474761f14bca Initial load
duke
parents:
diff changeset
   290
474761f14bca Initial load
duke
parents:
diff changeset
   291
    /**
474761f14bca Initial load
duke
parents:
diff changeset
   292
     * Returns the number of files to be generated if
474761f14bca Initial load
duke
parents:
diff changeset
   293
     * {@link #build} is invoked now.
474761f14bca Initial load
duke
parents:
diff changeset
   294
     */
474761f14bca Initial load
duke
parents:
diff changeset
   295
    public int countArtifacts() {
474761f14bca Initial load
duke
parents:
diff changeset
   296
        int r = 0;
474761f14bca Initial load
duke
parents:
diff changeset
   297
        JPackage[] pkgs = packages.values().toArray(new JPackage[packages.size()]);
474761f14bca Initial load
duke
parents:
diff changeset
   298
        // avoid concurrent modification exception
474761f14bca Initial load
duke
parents:
diff changeset
   299
        for( JPackage pkg : pkgs )
474761f14bca Initial load
duke
parents:
diff changeset
   300
            r += pkg.countArtifacts();
474761f14bca Initial load
duke
parents:
diff changeset
   301
        return r;
474761f14bca Initial load
duke
parents:
diff changeset
   302
    }
474761f14bca Initial load
duke
parents:
diff changeset
   303
474761f14bca Initial load
duke
parents:
diff changeset
   304
474761f14bca Initial load
duke
parents:
diff changeset
   305
    /**
474761f14bca Initial load
duke
parents:
diff changeset
   306
     * Obtains a reference to an existing class from its Class object.
474761f14bca Initial load
duke
parents:
diff changeset
   307
     *
474761f14bca Initial load
duke
parents:
diff changeset
   308
     * <p>
474761f14bca Initial load
duke
parents:
diff changeset
   309
     * The parameter may not be primitive.
474761f14bca Initial load
duke
parents:
diff changeset
   310
     *
474761f14bca Initial load
duke
parents:
diff changeset
   311
     * @see #_ref(Class) for the version that handles more cases.
474761f14bca Initial load
duke
parents:
diff changeset
   312
     */
474761f14bca Initial load
duke
parents:
diff changeset
   313
    public JClass ref(Class clazz) {
474761f14bca Initial load
duke
parents:
diff changeset
   314
        JReferencedClass jrc = (JReferencedClass)refClasses.get(clazz);
474761f14bca Initial load
duke
parents:
diff changeset
   315
        if (jrc == null) {
474761f14bca Initial load
duke
parents:
diff changeset
   316
            if (clazz.isPrimitive())
474761f14bca Initial load
duke
parents:
diff changeset
   317
                throw new IllegalArgumentException(clazz+" is a primitive");
474761f14bca Initial load
duke
parents:
diff changeset
   318
            if (clazz.isArray()) {
474761f14bca Initial load
duke
parents:
diff changeset
   319
                return new JArrayClass(this, _ref(clazz.getComponentType()));
474761f14bca Initial load
duke
parents:
diff changeset
   320
            } else {
474761f14bca Initial load
duke
parents:
diff changeset
   321
                jrc = new JReferencedClass(clazz);
474761f14bca Initial load
duke
parents:
diff changeset
   322
                refClasses.put(clazz, jrc);
474761f14bca Initial load
duke
parents:
diff changeset
   323
            }
474761f14bca Initial load
duke
parents:
diff changeset
   324
        }
474761f14bca Initial load
duke
parents:
diff changeset
   325
        return jrc;
474761f14bca Initial load
duke
parents:
diff changeset
   326
    }
474761f14bca Initial load
duke
parents:
diff changeset
   327
474761f14bca Initial load
duke
parents:
diff changeset
   328
    public JType _ref(Class c) {
474761f14bca Initial load
duke
parents:
diff changeset
   329
        if(c.isPrimitive())
474761f14bca Initial load
duke
parents:
diff changeset
   330
            return JType.parse(this,c.getName());
474761f14bca Initial load
duke
parents:
diff changeset
   331
        else
474761f14bca Initial load
duke
parents:
diff changeset
   332
            return ref(c);
474761f14bca Initial load
duke
parents:
diff changeset
   333
    }
474761f14bca Initial load
duke
parents:
diff changeset
   334
474761f14bca Initial load
duke
parents:
diff changeset
   335
    /**
474761f14bca Initial load
duke
parents:
diff changeset
   336
     * Obtains a reference to an existing class from its fully-qualified
474761f14bca Initial load
duke
parents:
diff changeset
   337
     * class name.
474761f14bca Initial load
duke
parents:
diff changeset
   338
     *
474761f14bca Initial load
duke
parents:
diff changeset
   339
     * <p>
474761f14bca Initial load
duke
parents:
diff changeset
   340
     * First, this method attempts to load the class of the given name.
474761f14bca Initial load
duke
parents:
diff changeset
   341
     * If that fails, we assume that the class is derived straight from
474761f14bca Initial load
duke
parents:
diff changeset
   342
     * {@link Object}, and return a {@link JClass}.
474761f14bca Initial load
duke
parents:
diff changeset
   343
     */
474761f14bca Initial load
duke
parents:
diff changeset
   344
    public JClass ref(String fullyQualifiedClassName) {
474761f14bca Initial load
duke
parents:
diff changeset
   345
        try {
474761f14bca Initial load
duke
parents:
diff changeset
   346
            // try the context class loader first
474761f14bca Initial load
duke
parents:
diff changeset
   347
            return ref(Thread.currentThread().getContextClassLoader().loadClass(fullyQualifiedClassName));
474761f14bca Initial load
duke
parents:
diff changeset
   348
        } catch (ClassNotFoundException e) {
474761f14bca Initial load
duke
parents:
diff changeset
   349
            // fall through
474761f14bca Initial load
duke
parents:
diff changeset
   350
        }
474761f14bca Initial load
duke
parents:
diff changeset
   351
        // then the default mechanism.
474761f14bca Initial load
duke
parents:
diff changeset
   352
        try {
474761f14bca Initial load
duke
parents:
diff changeset
   353
            return ref(Class.forName(fullyQualifiedClassName));
474761f14bca Initial load
duke
parents:
diff changeset
   354
        } catch (ClassNotFoundException e1) {
474761f14bca Initial load
duke
parents:
diff changeset
   355
            // fall through
474761f14bca Initial load
duke
parents:
diff changeset
   356
        }
474761f14bca Initial load
duke
parents:
diff changeset
   357
474761f14bca Initial load
duke
parents:
diff changeset
   358
        // assume it's not visible to us.
474761f14bca Initial load
duke
parents:
diff changeset
   359
        return new JDirectClass(this,fullyQualifiedClassName);
474761f14bca Initial load
duke
parents:
diff changeset
   360
    }
474761f14bca Initial load
duke
parents:
diff changeset
   361
474761f14bca Initial load
duke
parents:
diff changeset
   362
    /**
474761f14bca Initial load
duke
parents:
diff changeset
   363
     * Cached for {@link #wildcard()}.
474761f14bca Initial load
duke
parents:
diff changeset
   364
     */
474761f14bca Initial load
duke
parents:
diff changeset
   365
    private JClass wildcard;
474761f14bca Initial load
duke
parents:
diff changeset
   366
474761f14bca Initial load
duke
parents:
diff changeset
   367
    /**
474761f14bca Initial load
duke
parents:
diff changeset
   368
     * Gets a {@link JClass} representation for "?",
474761f14bca Initial load
duke
parents:
diff changeset
   369
     * which is equivalent to "? extends Object".
474761f14bca Initial load
duke
parents:
diff changeset
   370
     */
474761f14bca Initial load
duke
parents:
diff changeset
   371
    public JClass wildcard() {
474761f14bca Initial load
duke
parents:
diff changeset
   372
        if(wildcard==null)
474761f14bca Initial load
duke
parents:
diff changeset
   373
            wildcard = ref(Object.class).wildcard();
474761f14bca Initial load
duke
parents:
diff changeset
   374
        return wildcard;
474761f14bca Initial load
duke
parents:
diff changeset
   375
    }
474761f14bca Initial load
duke
parents:
diff changeset
   376
474761f14bca Initial load
duke
parents:
diff changeset
   377
    /**
474761f14bca Initial load
duke
parents:
diff changeset
   378
     * Obtains a type object from a type name.
474761f14bca Initial load
duke
parents:
diff changeset
   379
     *
474761f14bca Initial load
duke
parents:
diff changeset
   380
     * <p>
474761f14bca Initial load
duke
parents:
diff changeset
   381
     * This method handles primitive types, arrays, and existing {@link Class}es.
474761f14bca Initial load
duke
parents:
diff changeset
   382
     *
474761f14bca Initial load
duke
parents:
diff changeset
   383
     * @exception ClassNotFoundException
474761f14bca Initial load
duke
parents:
diff changeset
   384
     *      If the specified type is not found.
474761f14bca Initial load
duke
parents:
diff changeset
   385
     */
474761f14bca Initial load
duke
parents:
diff changeset
   386
    public JType parseType(String name) throws ClassNotFoundException {
474761f14bca Initial load
duke
parents:
diff changeset
   387
        // array
474761f14bca Initial load
duke
parents:
diff changeset
   388
        if(name.endsWith("[]"))
474761f14bca Initial load
duke
parents:
diff changeset
   389
            return parseType(name.substring(0,name.length()-2)).array();
474761f14bca Initial load
duke
parents:
diff changeset
   390
474761f14bca Initial load
duke
parents:
diff changeset
   391
        // try primitive type
474761f14bca Initial load
duke
parents:
diff changeset
   392
        try {
474761f14bca Initial load
duke
parents:
diff changeset
   393
            return JType.parse(this,name);
474761f14bca Initial load
duke
parents:
diff changeset
   394
        } catch (IllegalArgumentException e) {
474761f14bca Initial load
duke
parents:
diff changeset
   395
            ;
474761f14bca Initial load
duke
parents:
diff changeset
   396
        }
474761f14bca Initial load
duke
parents:
diff changeset
   397
474761f14bca Initial load
duke
parents:
diff changeset
   398
        // existing class
474761f14bca Initial load
duke
parents:
diff changeset
   399
        return new TypeNameParser(name).parseTypeName();
474761f14bca Initial load
duke
parents:
diff changeset
   400
    }
474761f14bca Initial load
duke
parents:
diff changeset
   401
474761f14bca Initial load
duke
parents:
diff changeset
   402
    private final class TypeNameParser {
474761f14bca Initial load
duke
parents:
diff changeset
   403
        private final String s;
474761f14bca Initial load
duke
parents:
diff changeset
   404
        private int idx;
474761f14bca Initial load
duke
parents:
diff changeset
   405
474761f14bca Initial load
duke
parents:
diff changeset
   406
        public TypeNameParser(String s) {
474761f14bca Initial load
duke
parents:
diff changeset
   407
            this.s = s;
474761f14bca Initial load
duke
parents:
diff changeset
   408
        }
474761f14bca Initial load
duke
parents:
diff changeset
   409
474761f14bca Initial load
duke
parents:
diff changeset
   410
        /**
474761f14bca Initial load
duke
parents:
diff changeset
   411
         * Parses a type name token T (which can be potentially of the form Tr&ly;T1,T2,...>,
474761f14bca Initial load
duke
parents:
diff changeset
   412
         * or "? extends/super T".)
474761f14bca Initial load
duke
parents:
diff changeset
   413
         *
474761f14bca Initial load
duke
parents:
diff changeset
   414
         * @return the index of the character next to T.
474761f14bca Initial load
duke
parents:
diff changeset
   415
         */
474761f14bca Initial load
duke
parents:
diff changeset
   416
        JClass parseTypeName() throws ClassNotFoundException {
474761f14bca Initial load
duke
parents:
diff changeset
   417
            int start = idx;
474761f14bca Initial load
duke
parents:
diff changeset
   418
474761f14bca Initial load
duke
parents:
diff changeset
   419
            if(s.charAt(idx)=='?') {
474761f14bca Initial load
duke
parents:
diff changeset
   420
                // wildcard
474761f14bca Initial load
duke
parents:
diff changeset
   421
                idx++;
474761f14bca Initial load
duke
parents:
diff changeset
   422
                ws();
474761f14bca Initial load
duke
parents:
diff changeset
   423
                String head = s.substring(idx);
474761f14bca Initial load
duke
parents:
diff changeset
   424
                if(head.startsWith("extends")) {
474761f14bca Initial load
duke
parents:
diff changeset
   425
                    idx+=7;
474761f14bca Initial load
duke
parents:
diff changeset
   426
                    ws();
474761f14bca Initial load
duke
parents:
diff changeset
   427
                    return parseTypeName().wildcard();
474761f14bca Initial load
duke
parents:
diff changeset
   428
                } else
474761f14bca Initial load
duke
parents:
diff changeset
   429
                if(head.startsWith("super")) {
474761f14bca Initial load
duke
parents:
diff changeset
   430
                    throw new UnsupportedOperationException("? super T not implemented");
474761f14bca Initial load
duke
parents:
diff changeset
   431
                } else {
474761f14bca Initial load
duke
parents:
diff changeset
   432
                    // not supported
474761f14bca Initial load
duke
parents:
diff changeset
   433
                    throw new IllegalArgumentException("only extends/super can follow ?, but found "+s.substring(idx));
474761f14bca Initial load
duke
parents:
diff changeset
   434
                }
474761f14bca Initial load
duke
parents:
diff changeset
   435
            }
474761f14bca Initial load
duke
parents:
diff changeset
   436
474761f14bca Initial load
duke
parents:
diff changeset
   437
            while(idx<s.length()) {
474761f14bca Initial load
duke
parents:
diff changeset
   438
                char ch = s.charAt(idx);
474761f14bca Initial load
duke
parents:
diff changeset
   439
                if(Character.isJavaIdentifierStart(ch)
474761f14bca Initial load
duke
parents:
diff changeset
   440
                || Character.isJavaIdentifierPart(ch)
474761f14bca Initial load
duke
parents:
diff changeset
   441
                || ch=='.')
474761f14bca Initial load
duke
parents:
diff changeset
   442
                    idx++;
474761f14bca Initial load
duke
parents:
diff changeset
   443
                else
474761f14bca Initial load
duke
parents:
diff changeset
   444
                    break;
474761f14bca Initial load
duke
parents:
diff changeset
   445
            }
474761f14bca Initial load
duke
parents:
diff changeset
   446
474761f14bca Initial load
duke
parents:
diff changeset
   447
            JClass clazz = ref(s.substring(start,idx));
474761f14bca Initial load
duke
parents:
diff changeset
   448
2678
57cf2a1c1a05 6831313: update jaxws in OpenJDK7 to 2.1 plus bug fixes from OpenJDK 6
tbell
parents: 8
diff changeset
   449
            return parseSuffix(clazz);
57cf2a1c1a05 6831313: update jaxws in OpenJDK7 to 2.1 plus bug fixes from OpenJDK 6
tbell
parents: 8
diff changeset
   450
        }
57cf2a1c1a05 6831313: update jaxws in OpenJDK7 to 2.1 plus bug fixes from OpenJDK 6
tbell
parents: 8
diff changeset
   451
57cf2a1c1a05 6831313: update jaxws in OpenJDK7 to 2.1 plus bug fixes from OpenJDK 6
tbell
parents: 8
diff changeset
   452
        /**
57cf2a1c1a05 6831313: update jaxws in OpenJDK7 to 2.1 plus bug fixes from OpenJDK 6
tbell
parents: 8
diff changeset
   453
         * Parses additional left-associative suffixes, like type arguments
57cf2a1c1a05 6831313: update jaxws in OpenJDK7 to 2.1 plus bug fixes from OpenJDK 6
tbell
parents: 8
diff changeset
   454
         * and array specifiers.
57cf2a1c1a05 6831313: update jaxws in OpenJDK7 to 2.1 plus bug fixes from OpenJDK 6
tbell
parents: 8
diff changeset
   455
         */
57cf2a1c1a05 6831313: update jaxws in OpenJDK7 to 2.1 plus bug fixes from OpenJDK 6
tbell
parents: 8
diff changeset
   456
        private JClass parseSuffix(JClass clazz) throws ClassNotFoundException {
8
474761f14bca Initial load
duke
parents:
diff changeset
   457
            if(idx==s.length())
474761f14bca Initial load
duke
parents:
diff changeset
   458
                return clazz; // hit EOL
474761f14bca Initial load
duke
parents:
diff changeset
   459
474761f14bca Initial load
duke
parents:
diff changeset
   460
            char ch = s.charAt(idx);
474761f14bca Initial load
duke
parents:
diff changeset
   461
474761f14bca Initial load
duke
parents:
diff changeset
   462
            if(ch=='<')
2678
57cf2a1c1a05 6831313: update jaxws in OpenJDK7 to 2.1 plus bug fixes from OpenJDK 6
tbell
parents: 8
diff changeset
   463
                return parseSuffix(parseArguments(clazz));
57cf2a1c1a05 6831313: update jaxws in OpenJDK7 to 2.1 plus bug fixes from OpenJDK 6
tbell
parents: 8
diff changeset
   464
57cf2a1c1a05 6831313: update jaxws in OpenJDK7 to 2.1 plus bug fixes from OpenJDK 6
tbell
parents: 8
diff changeset
   465
            if(ch=='[') {
57cf2a1c1a05 6831313: update jaxws in OpenJDK7 to 2.1 plus bug fixes from OpenJDK 6
tbell
parents: 8
diff changeset
   466
                if(s.charAt(idx+1)==']') {
57cf2a1c1a05 6831313: update jaxws in OpenJDK7 to 2.1 plus bug fixes from OpenJDK 6
tbell
parents: 8
diff changeset
   467
                    idx+=2;
57cf2a1c1a05 6831313: update jaxws in OpenJDK7 to 2.1 plus bug fixes from OpenJDK 6
tbell
parents: 8
diff changeset
   468
                    return parseSuffix(clazz.array());
57cf2a1c1a05 6831313: update jaxws in OpenJDK7 to 2.1 plus bug fixes from OpenJDK 6
tbell
parents: 8
diff changeset
   469
                }
57cf2a1c1a05 6831313: update jaxws in OpenJDK7 to 2.1 plus bug fixes from OpenJDK 6
tbell
parents: 8
diff changeset
   470
                throw new IllegalArgumentException("Expected ']' but found "+s.substring(idx+1));
57cf2a1c1a05 6831313: update jaxws in OpenJDK7 to 2.1 plus bug fixes from OpenJDK 6
tbell
parents: 8
diff changeset
   471
            }
8
474761f14bca Initial load
duke
parents:
diff changeset
   472
474761f14bca Initial load
duke
parents:
diff changeset
   473
            return clazz;
474761f14bca Initial load
duke
parents:
diff changeset
   474
        }
474761f14bca Initial load
duke
parents:
diff changeset
   475
474761f14bca Initial load
duke
parents:
diff changeset
   476
        /**
474761f14bca Initial load
duke
parents:
diff changeset
   477
         * Skips whitespaces
474761f14bca Initial load
duke
parents:
diff changeset
   478
         */
474761f14bca Initial load
duke
parents:
diff changeset
   479
        private void ws() {
474761f14bca Initial load
duke
parents:
diff changeset
   480
            while(Character.isWhitespace(s.charAt(idx)) && idx<s.length())
474761f14bca Initial load
duke
parents:
diff changeset
   481
                idx++;
474761f14bca Initial load
duke
parents:
diff changeset
   482
        }
474761f14bca Initial load
duke
parents:
diff changeset
   483
474761f14bca Initial load
duke
parents:
diff changeset
   484
        /**
474761f14bca Initial load
duke
parents:
diff changeset
   485
         * Parses '&lt;T1,T2,...,Tn>'
474761f14bca Initial load
duke
parents:
diff changeset
   486
         *
474761f14bca Initial load
duke
parents:
diff changeset
   487
         * @return the index of the character next to '>'
474761f14bca Initial load
duke
parents:
diff changeset
   488
         */
474761f14bca Initial load
duke
parents:
diff changeset
   489
        private JClass parseArguments(JClass rawType) throws ClassNotFoundException {
474761f14bca Initial load
duke
parents:
diff changeset
   490
            if(s.charAt(idx)!='<')
474761f14bca Initial load
duke
parents:
diff changeset
   491
                throw new IllegalArgumentException();
474761f14bca Initial load
duke
parents:
diff changeset
   492
            idx++;
474761f14bca Initial load
duke
parents:
diff changeset
   493
474761f14bca Initial load
duke
parents:
diff changeset
   494
            List<JClass> args = new ArrayList<JClass>();
474761f14bca Initial load
duke
parents:
diff changeset
   495
474761f14bca Initial load
duke
parents:
diff changeset
   496
            while(true) {
474761f14bca Initial load
duke
parents:
diff changeset
   497
                args.add(parseTypeName());
474761f14bca Initial load
duke
parents:
diff changeset
   498
                if(idx==s.length())
474761f14bca Initial load
duke
parents:
diff changeset
   499
                    throw new IllegalArgumentException("Missing '>' in "+s);
474761f14bca Initial load
duke
parents:
diff changeset
   500
                char ch = s.charAt(idx);
474761f14bca Initial load
duke
parents:
diff changeset
   501
                if(ch=='>')
474761f14bca Initial load
duke
parents:
diff changeset
   502
                    return rawType.narrow(args.toArray(new JClass[args.size()]));
474761f14bca Initial load
duke
parents:
diff changeset
   503
474761f14bca Initial load
duke
parents:
diff changeset
   504
                if(ch!=',')
474761f14bca Initial load
duke
parents:
diff changeset
   505
                    throw new IllegalArgumentException(s);
474761f14bca Initial load
duke
parents:
diff changeset
   506
                idx++;
474761f14bca Initial load
duke
parents:
diff changeset
   507
            }
474761f14bca Initial load
duke
parents:
diff changeset
   508
474761f14bca Initial load
duke
parents:
diff changeset
   509
        }
474761f14bca Initial load
duke
parents:
diff changeset
   510
    }
474761f14bca Initial load
duke
parents:
diff changeset
   511
474761f14bca Initial load
duke
parents:
diff changeset
   512
    /**
474761f14bca Initial load
duke
parents:
diff changeset
   513
     * References to existing classes.
474761f14bca Initial load
duke
parents:
diff changeset
   514
     *
474761f14bca Initial load
duke
parents:
diff changeset
   515
     * <p>
474761f14bca Initial load
duke
parents:
diff changeset
   516
     * JReferencedClass is kept in a pool so that they are shared.
474761f14bca Initial load
duke
parents:
diff changeset
   517
     * There is one pool for each JCodeModel object.
474761f14bca Initial load
duke
parents:
diff changeset
   518
     *
474761f14bca Initial load
duke
parents:
diff changeset
   519
     * <p>
474761f14bca Initial load
duke
parents:
diff changeset
   520
     * It is impossible to cache JReferencedClass globally only because
474761f14bca Initial load
duke
parents:
diff changeset
   521
     * there is the _package() method, which obtains the owner JPackage
474761f14bca Initial load
duke
parents:
diff changeset
   522
     * object, which is scoped to JCodeModel.
474761f14bca Initial load
duke
parents:
diff changeset
   523
     */
474761f14bca Initial load
duke
parents:
diff changeset
   524
    private class JReferencedClass extends JClass implements JDeclaration {
474761f14bca Initial load
duke
parents:
diff changeset
   525
        private final Class _class;
474761f14bca Initial load
duke
parents:
diff changeset
   526
474761f14bca Initial load
duke
parents:
diff changeset
   527
        JReferencedClass(Class _clazz) {
474761f14bca Initial load
duke
parents:
diff changeset
   528
            super(JCodeModel.this);
474761f14bca Initial load
duke
parents:
diff changeset
   529
            this._class = _clazz;
474761f14bca Initial load
duke
parents:
diff changeset
   530
            assert !_class.isArray();
474761f14bca Initial load
duke
parents:
diff changeset
   531
        }
474761f14bca Initial load
duke
parents:
diff changeset
   532
474761f14bca Initial load
duke
parents:
diff changeset
   533
        public String name() {
474761f14bca Initial load
duke
parents:
diff changeset
   534
            return _class.getSimpleName().replace('$','.');
474761f14bca Initial load
duke
parents:
diff changeset
   535
        }
474761f14bca Initial load
duke
parents:
diff changeset
   536
474761f14bca Initial load
duke
parents:
diff changeset
   537
        public String fullName() {
474761f14bca Initial load
duke
parents:
diff changeset
   538
            return _class.getName().replace('$','.');
474761f14bca Initial load
duke
parents:
diff changeset
   539
        }
474761f14bca Initial load
duke
parents:
diff changeset
   540
474761f14bca Initial load
duke
parents:
diff changeset
   541
        public String binaryName() {
474761f14bca Initial load
duke
parents:
diff changeset
   542
            return _class.getName();
474761f14bca Initial load
duke
parents:
diff changeset
   543
        }
474761f14bca Initial load
duke
parents:
diff changeset
   544
474761f14bca Initial load
duke
parents:
diff changeset
   545
        public JClass outer() {
474761f14bca Initial load
duke
parents:
diff changeset
   546
            Class p = _class.getDeclaringClass();
474761f14bca Initial load
duke
parents:
diff changeset
   547
            if(p==null)     return null;
474761f14bca Initial load
duke
parents:
diff changeset
   548
            return ref(p);
474761f14bca Initial load
duke
parents:
diff changeset
   549
        }
474761f14bca Initial load
duke
parents:
diff changeset
   550
474761f14bca Initial load
duke
parents:
diff changeset
   551
        public JPackage _package() {
474761f14bca Initial load
duke
parents:
diff changeset
   552
            String name = fullName();
474761f14bca Initial load
duke
parents:
diff changeset
   553
474761f14bca Initial load
duke
parents:
diff changeset
   554
            // this type is array
474761f14bca Initial load
duke
parents:
diff changeset
   555
            if (name.indexOf('[') != -1)
474761f14bca Initial load
duke
parents:
diff changeset
   556
                return JCodeModel.this._package("");
474761f14bca Initial load
duke
parents:
diff changeset
   557
474761f14bca Initial load
duke
parents:
diff changeset
   558
            // other normal case
474761f14bca Initial load
duke
parents:
diff changeset
   559
            int idx = name.lastIndexOf('.');
474761f14bca Initial load
duke
parents:
diff changeset
   560
            if (idx < 0)
474761f14bca Initial load
duke
parents:
diff changeset
   561
                return JCodeModel.this._package("");
474761f14bca Initial load
duke
parents:
diff changeset
   562
            else
474761f14bca Initial load
duke
parents:
diff changeset
   563
                return JCodeModel.this._package(name.substring(0, idx));
474761f14bca Initial load
duke
parents:
diff changeset
   564
        }
474761f14bca Initial load
duke
parents:
diff changeset
   565
474761f14bca Initial load
duke
parents:
diff changeset
   566
        public JClass _extends() {
474761f14bca Initial load
duke
parents:
diff changeset
   567
            Class sp = _class.getSuperclass();
474761f14bca Initial load
duke
parents:
diff changeset
   568
            if (sp == null) {
474761f14bca Initial load
duke
parents:
diff changeset
   569
                if(isInterface())
474761f14bca Initial load
duke
parents:
diff changeset
   570
                    return owner().ref(Object.class);
474761f14bca Initial load
duke
parents:
diff changeset
   571
                return null;
474761f14bca Initial load
duke
parents:
diff changeset
   572
            } else
474761f14bca Initial load
duke
parents:
diff changeset
   573
                return ref(sp);
474761f14bca Initial load
duke
parents:
diff changeset
   574
        }
474761f14bca Initial load
duke
parents:
diff changeset
   575
474761f14bca Initial load
duke
parents:
diff changeset
   576
        public Iterator<JClass> _implements() {
474761f14bca Initial load
duke
parents:
diff changeset
   577
            final Class[] interfaces = _class.getInterfaces();
474761f14bca Initial load
duke
parents:
diff changeset
   578
            return new Iterator<JClass>() {
474761f14bca Initial load
duke
parents:
diff changeset
   579
                private int idx = 0;
474761f14bca Initial load
duke
parents:
diff changeset
   580
                public boolean hasNext() {
474761f14bca Initial load
duke
parents:
diff changeset
   581
                    return idx < interfaces.length;
474761f14bca Initial load
duke
parents:
diff changeset
   582
                }
474761f14bca Initial load
duke
parents:
diff changeset
   583
                public JClass next() {
474761f14bca Initial load
duke
parents:
diff changeset
   584
                    return JCodeModel.this.ref(interfaces[idx++]);
474761f14bca Initial load
duke
parents:
diff changeset
   585
                }
474761f14bca Initial load
duke
parents:
diff changeset
   586
                public void remove() {
474761f14bca Initial load
duke
parents:
diff changeset
   587
                    throw new UnsupportedOperationException();
474761f14bca Initial load
duke
parents:
diff changeset
   588
                }
474761f14bca Initial load
duke
parents:
diff changeset
   589
            };
474761f14bca Initial load
duke
parents:
diff changeset
   590
        }
474761f14bca Initial load
duke
parents:
diff changeset
   591
474761f14bca Initial load
duke
parents:
diff changeset
   592
        public boolean isInterface() {
474761f14bca Initial load
duke
parents:
diff changeset
   593
            return _class.isInterface();
474761f14bca Initial load
duke
parents:
diff changeset
   594
        }
474761f14bca Initial load
duke
parents:
diff changeset
   595
474761f14bca Initial load
duke
parents:
diff changeset
   596
        public boolean isAbstract() {
474761f14bca Initial load
duke
parents:
diff changeset
   597
            return Modifier.isAbstract(_class.getModifiers());
474761f14bca Initial load
duke
parents:
diff changeset
   598
        }
474761f14bca Initial load
duke
parents:
diff changeset
   599
474761f14bca Initial load
duke
parents:
diff changeset
   600
        public JPrimitiveType getPrimitiveType() {
474761f14bca Initial load
duke
parents:
diff changeset
   601
            Class v = boxToPrimitive.get(_class);
474761f14bca Initial load
duke
parents:
diff changeset
   602
            if(v!=null)
474761f14bca Initial load
duke
parents:
diff changeset
   603
                return JType.parse(JCodeModel.this,v.getName());
474761f14bca Initial load
duke
parents:
diff changeset
   604
            else
474761f14bca Initial load
duke
parents:
diff changeset
   605
                return null;
474761f14bca Initial load
duke
parents:
diff changeset
   606
        }
474761f14bca Initial load
duke
parents:
diff changeset
   607
474761f14bca Initial load
duke
parents:
diff changeset
   608
        public boolean isArray() {
474761f14bca Initial load
duke
parents:
diff changeset
   609
            return false;
474761f14bca Initial load
duke
parents:
diff changeset
   610
        }
474761f14bca Initial load
duke
parents:
diff changeset
   611
474761f14bca Initial load
duke
parents:
diff changeset
   612
        public void declare(JFormatter f) {
474761f14bca Initial load
duke
parents:
diff changeset
   613
        }
474761f14bca Initial load
duke
parents:
diff changeset
   614
474761f14bca Initial load
duke
parents:
diff changeset
   615
        public JTypeVar[] typeParams() {
474761f14bca Initial load
duke
parents:
diff changeset
   616
            // TODO: does JDK 1.5 reflection provides these information?
474761f14bca Initial load
duke
parents:
diff changeset
   617
            return super.typeParams();
474761f14bca Initial load
duke
parents:
diff changeset
   618
        }
474761f14bca Initial load
duke
parents:
diff changeset
   619
474761f14bca Initial load
duke
parents:
diff changeset
   620
        protected JClass substituteParams(JTypeVar[] variables, List<JClass> bindings) {
474761f14bca Initial load
duke
parents:
diff changeset
   621
            // TODO: does JDK 1.5 reflection provides these information?
474761f14bca Initial load
duke
parents:
diff changeset
   622
            return this;
474761f14bca Initial load
duke
parents:
diff changeset
   623
        }
474761f14bca Initial load
duke
parents:
diff changeset
   624
    }
474761f14bca Initial load
duke
parents:
diff changeset
   625
474761f14bca Initial load
duke
parents:
diff changeset
   626
    /**
474761f14bca Initial load
duke
parents:
diff changeset
   627
     * Conversion from primitive type {@link Class} (such as {@link Integer#TYPE}
474761f14bca Initial load
duke
parents:
diff changeset
   628
     * to its boxed type (such as <tt>Integer.class</tt>)
474761f14bca Initial load
duke
parents:
diff changeset
   629
     */
474761f14bca Initial load
duke
parents:
diff changeset
   630
    public static final Map<Class,Class> primitiveToBox;
474761f14bca Initial load
duke
parents:
diff changeset
   631
    /**
474761f14bca Initial load
duke
parents:
diff changeset
   632
     * The reverse look up for {@link #primitiveToBox}
474761f14bca Initial load
duke
parents:
diff changeset
   633
     */
474761f14bca Initial load
duke
parents:
diff changeset
   634
    public static final Map<Class,Class> boxToPrimitive;
474761f14bca Initial load
duke
parents:
diff changeset
   635
474761f14bca Initial load
duke
parents:
diff changeset
   636
    static {
474761f14bca Initial load
duke
parents:
diff changeset
   637
        Map<Class,Class> m1 = new HashMap<Class,Class>();
474761f14bca Initial load
duke
parents:
diff changeset
   638
        Map<Class,Class> m2 = new HashMap<Class,Class>();
474761f14bca Initial load
duke
parents:
diff changeset
   639
474761f14bca Initial load
duke
parents:
diff changeset
   640
        m1.put(Boolean.class,Boolean.TYPE);
474761f14bca Initial load
duke
parents:
diff changeset
   641
        m1.put(Byte.class,Byte.TYPE);
474761f14bca Initial load
duke
parents:
diff changeset
   642
        m1.put(Character.class,Character.TYPE);
474761f14bca Initial load
duke
parents:
diff changeset
   643
        m1.put(Double.class,Double.TYPE);
474761f14bca Initial load
duke
parents:
diff changeset
   644
        m1.put(Float.class,Float.TYPE);
474761f14bca Initial load
duke
parents:
diff changeset
   645
        m1.put(Integer.class,Integer.TYPE);
474761f14bca Initial load
duke
parents:
diff changeset
   646
        m1.put(Long.class,Long.TYPE);
474761f14bca Initial load
duke
parents:
diff changeset
   647
        m1.put(Short.class,Short.TYPE);
474761f14bca Initial load
duke
parents:
diff changeset
   648
        m1.put(Void.class,Void.TYPE);
474761f14bca Initial load
duke
parents:
diff changeset
   649
474761f14bca Initial load
duke
parents:
diff changeset
   650
        for (Map.Entry<Class, Class> e : m1.entrySet())
474761f14bca Initial load
duke
parents:
diff changeset
   651
            m2.put(e.getValue(),e.getKey());
474761f14bca Initial load
duke
parents:
diff changeset
   652
474761f14bca Initial load
duke
parents:
diff changeset
   653
        boxToPrimitive = Collections.unmodifiableMap(m1);
474761f14bca Initial load
duke
parents:
diff changeset
   654
        primitiveToBox = Collections.unmodifiableMap(m2);
474761f14bca Initial load
duke
parents:
diff changeset
   655
474761f14bca Initial load
duke
parents:
diff changeset
   656
    }
474761f14bca Initial load
duke
parents:
diff changeset
   657
}