1 /**
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 *
4 * Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
5 * Portions Copyright 2013-2018 Philip Helger + contributors
6 *
7 * The contents of this file are subject to the terms of either the GNU
8 * General Public License Version 2 only ("GPL") or the Common Development
9 * and Distribution License("CDDL") (collectively, the "License"). You
10 * may not use this file except in compliance with the License. You can
11 * obtain a copy of the License at
12 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
13 * or packager/legal/LICENSE.txt. See the License for the specific
14 * language governing permissions and limitations under the License.
15 *
16 * When distributing the software, include this License Header Notice in each
17 * file and include the License file at packager/legal/LICENSE.txt.
18 *
19 * GPL Classpath Exception:
20 * Oracle designates this particular file as subject to the "Classpath"
21 * exception as provided by Oracle in the GPL Version 2 section of the License
22 * file that accompanied this code.
23 *
24 * Modifications:
25 * If applicable, add the following below the License Header, with the fields
26 * enclosed by brackets [] replaced by your own identifying information:
27 * "Portions Copyright [year] [name of copyright owner]"
28 *
29 * Contributor(s):
30 * If you wish your version of this file to be governed by only the CDDL or
31 * only the GPL Version 2, indicate your decision by adding "[Contributor]
32 * elects to include this software in this distribution under the [CDDL or GPL
33 * Version 2] license." If you don't indicate a single choice of license, a
34 * recipient has the option to distribute your version of this file under
35 * either the CDDL, the GPL Version 2 or to extend the choice of license to
36 * its licensees as provided above. However, if you add GPL Version 2 code
37 * and therefore, elected the GPL Version 2 license, then the option applies
38 * only if the new code is made subject to such option by the copyright
39 * holder.
40 */
41 package com.helger.jcodemodel;
42
43 import javax.annotation.Nonnull;
44 import javax.annotation.Nullable;
45
46 import com.helger.jcodemodel.util.JCValueEnforcer;
47
48 /**
49 * This is a single Java 8 lambda method reference expression.
50 *
51 * @author Philip Helger
52 * @since 2.8.3
53 */
54 public class JLambdaMethodRef implements IJExpression
55 {
56 private final boolean m_bStatic;
57 private final AbstractJType m_aType;
58 private final JVar m_aVar;
59 private final JInvocation m_aInvocation;
60 private final JMethod m_aMethod;
61 private final String m_sMethodName;
62
63 /**
64 * Constructor to reference the passed static method. It uses the name of the
65 * owning class as base (<code>owning::method</code>).
66 *
67 * @param aMethod
68 * The static method to reference. May not be <code>null</code>.
69 * @throws IllegalArgumentException
70 * If the passed method is not static
71 */
72 public JLambdaMethodRef (@Nonnull final JMethod aMethod)
73 {
74 JCValueEnforcer.notNull (aMethod, "Method");
75 JCValueEnforcer.isTrue (aMethod.mods ().isStatic (),
76 "Only static methods can be used with this constructor. Use the constructor with JVar for instance methods.");
77
78 m_bStatic = true;
79 m_aType = aMethod.owningClass ();
80 m_aVar = null;
81 m_aInvocation = null;
82 m_aMethod = aMethod;
83 m_sMethodName = null;
84 }
85
86 /**
87 * Constructor for a static constructor method reference
88 * (<code>type::new</code>).
89 *
90 * @param aType
91 * Type to reference the constructor from. May not be <code>null</code>
92 * .
93 */
94 public JLambdaMethodRef (@Nonnull final AbstractJType aType)
95 {
96 this (aType, "new");
97 }
98
99 /**
100 * Constructor for an arbitrary static method reference
101 * (<code>type::name</code>).
102 *
103 * @param aType
104 * Type the method belongs to. May not be <code>null</code>.
105 * @param sMethod
106 * Name of the static method to reference. May neither be
107 * <code>null</code> nor empty.
108 */
109 public JLambdaMethodRef (@Nonnull final AbstractJType aType, @Nonnull final String sMethod)
110 {
111 JCValueEnforcer.notNull (aType, "Type");
112 JCValueEnforcer.notEmpty (sMethod, "Method");
113
114 m_bStatic = true;
115 m_aType = aType;
116 m_aVar = null;
117 m_aInvocation = null;
118 m_aMethod = null;
119 m_sMethodName = sMethod;
120 }
121
122 /**
123 * Constructor for an arbitrary instance method reference
124 * (<code>var::name</code>).
125 *
126 * @param aVar
127 * Variable containing the instance. May not be <code>null</code>.
128 * @param sMethod
129 * Name of the method to reference. May neither be <code>null</code>
130 * nor empty.
131 */
132 public JLambdaMethodRef (@Nonnull final JVar aVar, @Nonnull final String sMethod)
133 {
134 JCValueEnforcer.notNull (aVar, "Var");
135 JCValueEnforcer.notEmpty (sMethod, "Method");
136
137 m_bStatic = false;
138 m_aType = aVar.type ();
139 m_aVar = aVar;
140 m_aInvocation = null;
141 m_aMethod = null;
142 m_sMethodName = sMethod;
143 }
144
145 /**
146 * Constructor for an arbitrary instance method reference
147 * (<code>var::name</code>).
148 *
149 * @param aVar
150 * Variable containing the instance. May not be <code>null</code>.
151 * @param aMethod
152 * The instance method to reference. May not be <code>null</code>.
153 */
154 public JLambdaMethodRef (@Nonnull final JVar aVar, @Nonnull final JMethod aMethod)
155 {
156 JCValueEnforcer.notNull (aVar, "Var");
157 JCValueEnforcer.notNull (aMethod, "Method");
158 JCValueEnforcer.isFalse (aMethod.mods ().isStatic (),
159 "Only instance methods can be used with this constructor. Use the constructor with JMethod only for static methods.");
160
161 m_bStatic = false;
162 m_aType = aVar.type ();
163 m_aVar = aVar;
164 m_aInvocation = null;
165 m_aMethod = aMethod;
166 m_sMethodName = null;
167 }
168
169 /**
170 * Constructor for an arbitrary invocation method reference.
171 *
172 * @param aInvocation
173 * Variable containing the invocation. May not be <code>null</code>.
174 * @param sMethod
175 * Name of the method to reference. May neither be <code>null</code>
176 * nor empty.
177 */
178 public JLambdaMethodRef (@Nonnull final JInvocation aInvocation, @Nonnull final String sMethod)
179 {
180 JCValueEnforcer.notNull (aInvocation, "Invocation");
181 JCValueEnforcer.notEmpty (sMethod, "Method");
182
183 m_bStatic = false;
184 m_aType = null;
185 m_aVar = null;
186 m_aInvocation = aInvocation;
187 m_aMethod = null;
188 m_sMethodName = sMethod;
189 }
190
191 /**
192 * Constructor for an arbitrary invocation method reference.
193 *
194 * @param aInvocation
195 * Variable containing the invocation. May not be <code>null</code>.
196 * @param aMethod
197 * The instance method to reference. May not be <code>null</code>.
198 */
199 public JLambdaMethodRef (@Nonnull final JInvocation aInvocation, @Nonnull final JMethod aMethod)
200 {
201 JCValueEnforcer.notNull (aInvocation, "Invocation");
202 JCValueEnforcer.notNull (aMethod, "Method");
203 JCValueEnforcer.isFalse (aMethod.mods ().isStatic (),
204 "Only instance methods can be used with this constructor. Use the constructor with JMethod only for static methods.");
205
206 m_bStatic = false;
207 m_aType = aMethod.owningClass ();
208 m_aVar = null;
209 m_aInvocation = aInvocation;
210 m_aMethod = aMethod;
211 m_sMethodName = null;
212 }
213
214 /**
215 * @return <code>true</code> if this is a static reference, <code>false</code>
216 * if this is an instance reference.
217 */
218 public boolean isStaticRef ()
219 {
220 return m_bStatic;
221 }
222
223 /**
224 * @return The type owning the method. May be <code>null</code> if invoked
225 * with another JInvocation.
226 */
227 @Nullable
228 public AbstractJType type ()
229 {
230 return m_aType;
231 }
232
233 /**
234 * @return The variable for the instance reference. May be <code>null</code>
235 * if this is a static or invocation reference.
236 */
237 @Nullable
238 public JVar var ()
239 {
240 return m_aVar;
241 }
242
243 /**
244 * @return The invocation reference. May be <code>null</code> if this is a
245 * static or variable reference.
246 */
247 @Nullable
248 public JInvocation invocation ()
249 {
250 return m_aInvocation;
251 }
252
253 /**
254 * @return The owning method. May be <code>null</code> if a constructor with
255 * method name was used.
256 */
257 @Nullable
258 public JMethod method ()
259 {
260 return m_aMethod;
261 }
262
263 /**
264 * @return The name of the referenced method. Never <code>null</code>.
265 */
266 @Nonnull
267 public String methodName ()
268 {
269 return m_aMethod != null ? m_aMethod.name () : m_sMethodName;
270 }
271
272 @Override
273 public void generate (@Nonnull final IJFormatter f)
274 {
275 if (isStaticRef ())
276 f.type (type ());
277 else
278 if (m_aVar != null)
279 f.generable (m_aVar);
280 else
281 f.generable (m_aInvocation);
282 f.print ("::").print (methodName ());
283 }
284 }