View Javadoc
1   /*
2    * Copyright (c) 1997, 2010, 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  import java.util.ArrayList;
29  import java.util.List;
30  
31  
32  /**
33   * JMethod invocation
34   */
35  public final class JInvocation extends JExpressionImpl implements JStatement {
36  
37      /**
38       * Object expression upon which this method will be invoked, or null if
39       * this is a constructor invocation
40       */
41      private JGenerable object;
42  
43      /**
44       * Name of the method to be invoked.
45       * Either this field is set, or {@link #method}, or {@link #type} (in which case it's a
46       * constructor invocation.)
47       * This allows {@link JMethod#name(String) the name of the method to be changed later}.
48       */
49      private String name;
50  
51      private JMethod method;
52  
53      private boolean isConstructor = false;
54  
55      /**
56       * List of argument expressions for this method invocation
57       */
58      private List<JExpression> args = new ArrayList<JExpression>();
59  
60      /**
61       * If isConstructor==true, this field keeps the type to be created.
62       */
63      private JType type = null;
64  
65      /**
66       * Invokes a method on an object.
67       *
68       * @param object
69       *        JExpression for the object upon which
70       *        the named method will be invoked,
71       *        or null if none
72       *
73       * @param name
74       *        Name of method to invoke
75       */
76      JInvocation(JExpression object, String name) {
77          this( (JGenerable)object, name );
78      }
79  
80      JInvocation(JExpression object, JMethod method) {
81          this( (JGenerable)object, method );
82      }
83  
84      /**
85       * Invokes a static method on a class.
86       */
87      JInvocation(JClass type, String name) {
88          this( (JGenerable)type, name );
89      }
90  
91      JInvocation(JClass type, JMethod method) {
92          this( (JGenerable)type, method );
93      }
94  
95      private JInvocation(JGenerable object, String name) {
96          this.object = object;
97          if (name.indexOf('.') >= 0)
98              throw new IllegalArgumentException("method name contains '.': " + name);
99          this.name = name;
100     }
101 
102     private JInvocation(JGenerable object, JMethod method) {
103         this.object = object;
104         this.method =method;
105     }
106 
107     /**
108      * Invokes a constructor of an object (i.e., creates
109      * a new object.)
110      *
111      * @param c
112      *      Type of the object to be created. If this type is
113      *      an array type, added arguments are treated as array
114      *      initializer. Thus you can create an expression like
115      *      <code>new int[]{1,2,3,4,5}</code>.
116      */
117     JInvocation(JType c) {
118         this.isConstructor = true;
119         this.type = c;
120     }
121 
122     /**
123      *  Add an expression to this invocation's argument list
124      *
125      * @param arg
126      *        Argument to add to argument list
127      */
128     public JInvocation arg(JExpression arg) {
129         if(arg==null)   throw new IllegalArgumentException();
130         args.add(arg);
131         return this;
132     }
133 
134     /**
135      * Adds a literal argument.
136      *
137      * Short for {@code arg(JExpr.lit(v))}
138      */
139     public JInvocation arg(String v) {
140         return arg(JExpr.lit(v));
141     }
142 
143         /**
144          * Returns all arguments of the invocation.
145          * @return
146          *      If there's no arguments, an empty array will be returned.
147          */
148         public JExpression[] listArgs() {
149                 return args.toArray(new JExpression[args.size()]);
150         }
151 
152     public void generate(JFormatter f) {
153         if (isConstructor && type.isArray()) {
154             // [RESULT] new T[]{arg1,arg2,arg3,...};
155             f.p("new").g(type).p('{');
156         } else {
157             if (isConstructor)
158                 f.p("new").g(type).p('(');
159             else {
160                 String name = this.name;
161                 if(name==null)  name=this.method.name();
162 
163                 if (object != null)
164                     f.g(object).p('.').p(name).p('(');
165                 else
166                     f.id(name).p('(');
167             }
168         }
169 
170         f.g(args);
171 
172         if (isConstructor && type.isArray())
173             f.p('}');
174         else
175             f.p(')');
176 
177         if( type instanceof JDefinedClass && ((JDefinedClass)type).isAnonymous() ) {
178             ((JAnonymousClass)type).declareBody(f);
179         }
180     }
181 
182     public void state(JFormatter f) {
183         f.g(this).p(';').nl();
184     }
185 
186 }