001/*
002 * ============================================================================
003 * Copyright © 2015 Square, Inc.
004 * Copyright for the modifications © 2018-2024 by Thomas Thrien.
005 * ============================================================================
006 *
007 * Licensed under the Apache License, Version 2.0 (the "License");
008 * you may not use this file except in compliance with the License.
009 * You may obtain a copy of the License at
010 *
011 * http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 */
019
020package org.tquadrat.foundation.javacomposer;
021
022import static org.apiguardian.api.API.Status.STABLE;
023
024import javax.lang.model.element.Modifier;
025import java.lang.reflect.Type;
026import java.util.Collection;
027import java.util.Map;
028import java.util.Set;
029
030import org.apiguardian.api.API;
031import org.tquadrat.foundation.annotation.ClassVersion;
032import org.tquadrat.foundation.javacomposer.internal.MethodSpecImpl;
033
034/**
035 *  The specification for a generated constructor or method declaration.
036 *
037 *  @author Square,Inc.
038 *  @modified   Thomas Thrien - thomas.thrien@tquadrat.org
039 *  @version $Id: MethodSpec.java 1085 2024-01-05 16:23:28Z tquadrat $
040 *  @since 0.0.5
041 *
042 *  @UMLGraph.link
043 */
044@ClassVersion( sourceVersion = "$Id: MethodSpec.java 1085 2024-01-05 16:23:28Z tquadrat $" )
045@API( status = STABLE, since = "0.0.5" )
046public sealed interface MethodSpec
047    permits MethodSpecImpl
048{
049        /*---------------*\
050    ====** Inner Classes **====================================================
051        \*---------------*/
052    /**
053     *  The builder for an instance of
054     *  {@link MethodSpec}
055     *
056     *  @author Square,Inc.
057     *  @modified   Thomas Thrien - thomas.thrien@tquadrat.org
058     *  @version $Id: MethodSpec.java 1085 2024-01-05 16:23:28Z tquadrat $
059     *  @since 0.0.5
060     *
061     *  @UMLGraph.link
062     */
063    @SuppressWarnings( {"ClassWithTooManyMethods", "InnerClassOfInterface"} )
064    @ClassVersion( sourceVersion = "$Id: MethodSpec.java 1085 2024-01-05 16:23:28Z tquadrat $" )
065    @API( status = STABLE, since = "0.0.5" )
066    public static sealed interface Builder
067        permits MethodSpecImpl.BuilderImpl
068    {
069            /*---------*\
070        ====** Methods **======================================================
071            \*---------*/
072        /**
073         *  Adds an annotation for the method.
074         *
075         *  @note No debug information can be added when adding an annotation.
076         *
077         *  @param  annotationSpec  The annotation.
078         *  @return This {@code Builder} instance.
079         */
080        public Builder addAnnotation( final AnnotationSpec annotationSpec );
081
082        /**
083         *  Adds an annotation for the method.
084         *
085         *  @note No debug information can be added when adding an annotation.
086         *
087         *  @param  annotation  The annotation.
088         *  @return This {@code Builder} instance.
089         */
090        public Builder addAnnotation( final Class<?> annotation );
091
092        /**
093         *  Adds an annotation for the method.
094         *
095         *  @note No debug information can be added when adding an annotation.
096         *
097         *  @param  annotationClass The annotation.
098         *  @return This {@code Builder} instance.
099         */
100        public Builder addAnnotation( final ClassName annotationClass );
101
102        /**
103         *  Adds annotations for the method.
104         *
105         *  @note No debug information can be added when adding an annotation.
106         *
107         *  @param  annotationSpecs The annotations.
108         *  @return This {@code Builder} instance.
109         */
110        public Builder addAnnotations( final Iterable<? extends AnnotationSpec> annotationSpecs );
111
112        /**
113         *  Adds code for the method.
114         *
115         *  @param  codeBlock   The code.
116         *  @return This {@code Builder} instance.
117         */
118        public Builder addCode( final CodeBlock codeBlock );
119
120        /**
121         *  Adds code for the method.
122         *
123         *  @param  format  The format.
124         *  @param  args    The arguments.
125         *  @return This {@code Builder} instance.
126         */
127        public Builder addCode( final String format, final Object... args );
128
129        /**
130         *  Adds a comment for the method.
131         *
132         *  @note   No debug info is added when a comment is added.
133         *
134         *  @param  format  The format.
135         *  @param  args    The arguments.
136         *  @return This {@code Builder} instance.
137         */
138        public Builder addComment( final String format, final Object... args );
139
140        /**
141         *  Adds the declaration for an exception for the method.
142         *
143         *  @note   No debug info is added when an exception is added.
144         *
145         *  @param  exception   The exception.
146         *  @return This {@code Builder} instance.
147         */
148        public Builder addException( final Type exception );
149
150        /**
151         *  Adds the declaration for an exception for the method.
152         *
153         *  @note   No debug info is added when an exception is added.
154         *
155         *  @param  exception   The exception.
156         *  @return This {@code Builder} instance.
157         */
158        public Builder addException( final TypeName exception );
159
160        /**
161         *  Adds the declarations for exceptions for the method.
162         *
163         *  @note   No debug info is added when an exception is added.
164         *
165         *  @param  exceptions  The exceptions.
166         *  @return This {@code Builder} instance.
167         */
168        @SuppressWarnings( "UnusedReturnValue" )
169        public Builder addExceptions( final Iterable<? extends TypeName> exceptions );
170
171        /**
172         *  Adds a Javadoc comment for the method.
173         *
174         *  @note   No debug info is added when a comment is added.
175         *
176         *  @param  block   The Javadoc comment.
177         *  @return This {@code Builder} instance.
178         */
179        public Builder addJavadoc( final CodeBlock block );
180
181        /**
182         *  Adds a Javadoc comment for the method.
183         *
184         *  @note   No debug info is added when a comment is added.
185         *
186         *  @param  format  The format.
187         *  @param  args    The arguments.
188         *  @return This {@code Builder} instance.
189         */
190        public Builder addJavadoc( final String format, final Object... args );
191
192        /**
193         *  Adds modifiers for the method.
194         *
195         *  @param  modifiers   The modifiers.
196         *  @return This {@code Builder} instance.
197         */
198        public Builder addModifiers( final Iterable<Modifier> modifiers );
199
200        /**
201         *  Adds modifiers for the method.
202         *
203         *  @param  modifiers   The modifiers.
204         *  @return This {@code Builder} instance.
205         */
206        public Builder addModifiers( final Modifier... modifiers );
207
208        /**
209         *  <p>{@summary Adds code using named arguments for the method.}</p>
210         *  <p>Named arguments specify their name after the '$' followed by a
211         *  colon {@code ":"} and the corresponding type character. Argument
212         *  names consist of characters in {@code a-z, A-Z, 0-9, and _} and
213         *  must start with a lowercase character.</p>
214         *  <p>For example, to refer to the type
215         *  {@link java.lang.Integer}
216         *  with the argument name {@code clazz} use a format string containing
217         *  {@code $clazz:T} and include the key {@code clazz} with value
218         *  {@code java.lang.Integer.class} in the argument map.</p>
219         *
220         *  @param  format  The format.
221         *  @param  args    The arguments.
222         *  @return This {@code Builder} instance.
223         */
224        public Builder addNamedCode( final String format, final Map<String,?> args );
225
226        /**
227         *  Adds a parameter for the method.
228         *
229         *  @note   No debug info is added when a parameter is added.
230         *
231         *  @param  parameterSpec   The parameter.
232         *  @return This {@code Builder} instance.
233         */
234        public Builder addParameter( final ParameterSpec parameterSpec );
235
236        /**
237         *  Adds a parameter for the method.
238         *
239         *  @note   No debug info is added when a parameter is added.
240         *
241         *  @param  type    The type of the parameter.
242         *  @param  name    The name of the parameter.
243         *  @param  modifiers   The modifiers for the parameter.
244         *  @return This {@code Builder} instance.
245         */
246        public Builder addParameter( final Type type, final String name, final Modifier... modifiers );
247
248        /**
249         *  Adds a parameter for the method.
250         *
251         *  @note   No debug info is added when a parameter is added.
252         *
253         *  @param  type    The type of the parameter.
254         *  @param  name    The name of the parameter.
255         *  @param  modifiers   The modifiers for the parameter.
256         *  @return This {@code Builder} instance.
257         */
258        public Builder addParameter( final TypeName type, final String name, final Modifier... modifiers );
259
260        /**
261         *  Adds parameters for the method.
262         *
263         *  @note   No debug info is added when a parameter is added.
264         *
265         *  @param  parameterSpecs  The parameters.
266         *  @return This {@code Builder} instance.
267         */
268        @SuppressWarnings( "UnusedReturnValue" )
269        public Builder addParameters( final Iterable<? extends ParameterSpec> parameterSpecs );
270
271        /**
272         *  Adds a statement to the code for the method.
273         *
274         *  @param  format  The format.
275         *  @param  args    The arguments.
276         *  @return This {@code Builder} instance.
277         */
278        public Builder addStatement( final String format, final Object... args );
279
280        /**
281         *  Adds a static import.
282         *
283         *  @param  clazz   The class.
284         *  @param  names   The names of the elements from the given class that
285         *      are to be imported.
286         *  @return This {@code Builder} instance.
287         *
288         *  @since 0.2.0
289         */
290        @API( status = STABLE, since = "0.2.0" )
291        public MethodSpec.Builder addStaticImport( final Class<?> clazz, final String... names );
292
293        /**
294         *  Adds a static import.
295         *
296         *  @param  className   The class.
297         *  @param  names   The names of the elements from the given class that
298         *      are to be imported.
299         *  @return This {@code Builder} instance.
300         *
301         *  @since 0.2.0
302         */
303        @API( status = STABLE, since = "0.2.0" )
304        public MethodSpec.Builder addStaticImport( final ClassName className, final String... names );
305
306        /**
307         *  Adds a static import for the given {@code enum} value.
308         *
309         *  @param  constant    The {@code enum} value.
310         *  @return This {@code Builder} instance.
311         *
312         *  @since 0.2.0
313         */
314        @API( status = STABLE, since = "0.2.0" )
315        public MethodSpec.Builder addStaticImport( final Enum<?> constant );
316
317        /**
318         *  Adds a type variable for the method.
319         *
320         *  @note   No debug info is added when a type variable is added.
321         *
322         *  @param  typeVariable    The type variable.
323         *  @return This {@code Builder} instance.
324         */
325        public Builder addTypeVariable( final TypeVariableName typeVariable );
326
327        /**
328         *  Adds type variables for the method.
329         *
330         *  @note   No debug info is added when a parameter is added.
331         *
332         *  @param  typeVariables   The type variables.
333         *  @return This {@code Builder} instance.
334         */
335        @SuppressWarnings( "UnusedReturnValue" )
336        public Builder addTypeVariables( final Iterable<TypeVariableName> typeVariables );
337
338        /**
339         *  Adds the beginning of a control flow for the method.
340         *
341         *  @param  controlFlow The control flow construct and its code, such
342         *      as &quot;{@code if (foo == 5)}&quot;; it should not contain
343         *      braces or newline characters.
344         *  @param  args    The arguments.
345         *  @return This {@code Builder} instance.
346         *
347         *  @see #endControlFlow()
348         *  @see #endControlFlow(String, Object...)
349         *  @see #nextControlFlow(String, Object...)
350         */
351        public Builder beginControlFlow( final String controlFlow, final Object... args );
352
353        /**
354         *  Creates a new
355         *  {@link MethodSpec}
356         *  instance from the components that have been added to this builder.
357         *
358         *  @return The {@code MethodSpec} instance.
359         */
360        public MethodSpec build();
361
362        /**
363         *  Sets the default value for this method.
364         *
365         *  @param  defaultValue    The default value.
366         *  @return This {@code Builder} instance.
367         */
368        public Builder defaultValue( final CodeBlock defaultValue );
369
370        /**
371         *  Sets the default value for this method.
372         *
373         *  @param  format  The format.
374         *  @param  args    The arguments.
375         *  @return This {@code Builder} instance.
376         */
377        public Builder defaultValue( final String format, final Object... args );
378
379        /**
380         *  Ends the current control flow for the method.
381         *
382         *  @return This {@code Builder} instance.
383         *
384         *  @see #beginControlFlow(String, Object...)
385         *  @see #endControlFlow(String, Object...)
386         *  @see #nextControlFlow(String, Object...)
387         */
388        public Builder endControlFlow();
389
390        /**
391         *  Ends the current control flow for the method; this version is only
392         *  used for {@code do-while} constructs.
393         *
394         *  @param  controlFlow The optional control flow construct and its
395         *      code, such as &quot;{@code while(foo == 20)}&quot;; it should
396         *      not contain braces or newline characters.
397         *  @param  args    The arguments.
398         *  @return This {@code Builder} instance.
399         *
400         *  @see #beginControlFlow(String, Object...)
401         *  @see #endControlFlow()
402         */
403        public Builder endControlFlow( final String controlFlow, final Object... args );
404
405        /**
406         *  Begins another control flow for the method.
407         *
408         *  @param  controlFlow The control flow construct and its code, such
409         *      as &quot;{@code else if (foo == 10)}&quot;; it should not
410         *      contain braces or newline characters.
411         *  @param  args    The arguments.
412         *  @return This {@code Builder} instance.
413         *
414         *  @see #beginControlFlow(String, Object...)
415         *  @see #endControlFlow()
416         */
417        public Builder nextControlFlow( final String controlFlow, final Object... args );
418
419        /**
420         *  Sets the return type for the method.
421         *
422         *  @param  returnType  The return type.
423         *  @return This {@code Builder} instance.
424         */
425        public Builder returns( final Type returnType );
426
427        /**
428         *  Sets the return type for the method and adds the respective Javadoc
429         *  comment.
430         *
431         *  @param  returnType  The return type.
432         *  @param  format  The format for the return comment.
433         *  @param  args    The arguments for the return comment.
434         *  @return This {@code Builder} instance.
435         */
436        public Builder returns( final Type returnType, final String format, final Object... args );
437
438        /**
439         *  Sets the return type for the method.
440         *
441         *  @param  returnType  The return type.
442         *  @return This {@code Builder} instance.
443         */
444        public Builder returns( final TypeName returnType );
445
446        /**
447         *  Sets the return type for the method and adds the respective Javadoc
448         *  comment.
449         *
450         *  @param  returnType  The return type.
451         *  @param  format  The format for the return comment.
452         *  @param  args    The arguments for the return comment.
453         *  @return This {@code Builder} instance.
454         */
455        public Builder returns( final TypeName returnType, final String format, final Object... args  );
456
457        /**
458         *  Sets the flag that indicates whether a parameter (the last one) is
459         *  a {@code varargs} parameter to {@code true}.
460         *
461         *  @return This {@code Builder} instance.
462         */
463        public default Builder varargs() { return varargs( true ); }
464
465        /**
466         *  Sets the flag that indicates whether a parameter (the last one) is
467         *  a {@code varargs} parameter.
468         *
469         *  @param  varargs {@code true} if the last parameter is a
470         *      {@code varargs} parameter, {@code false} if not.
471         *  @return This {@code Builder} instance.
472         */
473        public Builder varargs( final boolean varargs );
474    }
475    //  interface Builder
476
477        /*-----------*\
478    ====** Constants **========================================================
479        \*-----------*/
480    /**
481     *  The &quot;name&quot; for a method that is in fact a constructor:
482     *  {@value}.
483     */
484    public static final String CONSTRUCTOR = "<init>";
485
486        /*---------*\
487    ====** Methods **==========================================================
488        \*---------*/
489    /**
490     *  {@inheritDoc}
491     */
492    @Override
493    public boolean equals( final Object o );
494
495    /**
496     *  {@inheritDoc}
497     */
498    @Override
499    public int hashCode();
500
501    /**
502     *  Checks whether the method has the given modifier.
503     *
504     *  @param  modifier    The modifier.
505     *  @return {@code true} if the given modifier has been applied to this
506     *      method, {@code false} otherwise.
507     */
508    public boolean hasModifier( final Modifier modifier );
509
510    /**
511     *  Checks whether this method is a constructor.
512     *
513     *  @return {@code true} if the method is a constructor, {@code false} if
514     *      it is a regular method.
515     */
516    public boolean isConstructor();
517
518    /**
519     *  Returns the modifiers of this method.
520     *
521     *  @return The modifiers.
522     */
523    public Set<Modifier> modifiers();
524
525    /**
526     *  Returns the name of this method.
527     *
528     *  @return The name
529     */
530    public String name();
531
532    /**
533     *  Returns the parameters for this method.
534     *
535     *  @return The parameters.
536     */
537    public Collection<ParameterSpec> parameters();
538
539    /**
540     *  Returns the signature for this method.
541     *
542     *  @return The signature.
543     */
544    public String signature();
545
546    /**
547     *  Return the return type for this method.
548     *
549     *  @return The return type; will never be {@code null}, not even for a
550     *      constructor.
551     */
552    public TypeName returnType();
553
554    /**
555     *  Returns a builder that is initialised with all the components of this
556     *  method. Use this to implement a method from an interface.
557     *
558     *  @return The builder.
559     *
560     *  @see #toBuilder(boolean)
561     */
562    public default Builder toBuilder() { return toBuilder( false ); }
563
564    /**
565     *  <p>{@summary Returns a builder that is initialised with all the
566     *  components of this method, like the result of a call to
567     *  {@link #toBuilder},
568     *  but without the body code, if specified that way.}</p>
569     *  <p>If the body is not copied, the method will be marked as
570     *  {@link Modifier#ABSTRACT ABSTRACT},
571     *  too.</p>
572     *
573     *  @param  omitCode    {@code true} if the body code should not be copied,
574     *      {@code false} otherwise; in the latter case, the result is the same
575     *      as for
576     *      {@link #toBuilder()}.
577     *  @return The builder.
578     */
579    @API( status = STABLE, since = "0.0.8" )
580    public Builder toBuilder( final boolean omitCode );
581
582    /**
583     *  {@inheritDoc}
584     */
585    @Override
586    public String toString();
587}
588//  interface MethodSpec
589
590/*
591 *  End of File
592 */