View Javadoc
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 }