001/*
002 * ============================================================================
003 * Copyright © 2015 Square, Inc.
004 * Copyright for the modifications © 2018-2025 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.internal;
021
022import static java.lang.String.format;
023import static java.util.Collections.addAll;
024import static javax.lang.model.element.Modifier.ABSTRACT;
025import static javax.lang.model.element.Modifier.NATIVE;
026import static org.apiguardian.api.API.Status.DEPRECATED;
027import static org.apiguardian.api.API.Status.INTERNAL;
028import static org.apiguardian.api.API.Status.STABLE;
029import static org.tquadrat.foundation.javacomposer.internal.TypeNameImpl.VOID_PRIMITIVE;
030import static org.tquadrat.foundation.javacomposer.internal.Util.createDebugOutput;
031import static org.tquadrat.foundation.lang.Objects.checkState;
032import static org.tquadrat.foundation.lang.Objects.hash;
033import static org.tquadrat.foundation.lang.Objects.isNull;
034import static org.tquadrat.foundation.lang.Objects.nonNull;
035import static org.tquadrat.foundation.lang.Objects.requireNonNullArgument;
036import static org.tquadrat.foundation.lang.Objects.requireNotEmptyArgument;
037import static org.tquadrat.foundation.lang.Objects.requireValidArgument;
038import static org.tquadrat.foundation.lang.Objects.requireValidNonNullArgument;
039import static org.tquadrat.foundation.util.JavaUtils.isValidName;
040
041import javax.lang.model.element.ExecutableElement;
042import javax.lang.model.element.Modifier;
043import javax.lang.model.type.DeclaredType;
044import javax.lang.model.util.Types;
045import java.io.UncheckedIOException;
046import java.lang.reflect.Method;
047import java.lang.reflect.Type;
048import java.util.ArrayList;
049import java.util.Arrays;
050import java.util.Collection;
051import java.util.EnumSet;
052import java.util.HashSet;
053import java.util.LinkedHashSet;
054import java.util.List;
055import java.util.Map;
056import java.util.Optional;
057import java.util.SequencedCollection;
058import java.util.Set;
059import java.util.StringJoiner;
060import java.util.TreeSet;
061
062import org.apiguardian.api.API;
063import org.tquadrat.foundation.annotation.ClassVersion;
064import org.tquadrat.foundation.exception.UnexpectedExceptionError;
065import org.tquadrat.foundation.exception.UnsupportedEnumError;
066import org.tquadrat.foundation.exception.ValidationException;
067import org.tquadrat.foundation.javacomposer.AnnotationSpec;
068import org.tquadrat.foundation.javacomposer.ClassName;
069import org.tquadrat.foundation.javacomposer.CodeBlock;
070import org.tquadrat.foundation.javacomposer.JavaComposer;
071import org.tquadrat.foundation.javacomposer.MethodSpec;
072import org.tquadrat.foundation.javacomposer.ParameterSpec;
073import org.tquadrat.foundation.javacomposer.TypeName;
074import org.tquadrat.foundation.javacomposer.TypeVariableName;
075import org.tquadrat.foundation.lang.Lazy;
076import org.tquadrat.foundation.lang.Objects;
077
078/**
079 *  The implementation for
080 *  {@link MethodSpec}.
081 *
082 *  @author Square,Inc.
083 *  @modified   Thomas Thrien - thomas.thrien@tquadrat.org
084 *  @version $Id: MethodSpecImpl.java 1258 2026-06-04 18:33:06Z tquadrat $
085 *  @since 0.0.5
086 *
087 *  @UMLGraph.link
088 */
089@SuppressWarnings( {"ClassWithTooManyFields"} )
090@ClassVersion( sourceVersion = "$Id: MethodSpecImpl.java 1258 2026-06-04 18:33:06Z tquadrat $" )
091@API( status = INTERNAL, since = "0.0.5" )
092public final class MethodSpecImpl implements MethodSpec
093{
094        /*---------------*\
095    ====** Inner Classes **====================================================
096        \*---------------*/
097    /**
098     *  The implementation for
099     *  {@link org.tquadrat.foundation.javacomposer.MethodSpec.Builder}
100     *
101     *  @author Square,Inc.
102     *  @modified   Thomas Thrien - thomas.thrien@tquadrat.org
103     *  @version $Id: MethodSpecImpl.java 1258 2026-06-04 18:33:06Z tquadrat $
104     *  @since 0.0.5
105     *
106     *  @UMLGraph.link
107     */
108    @ClassVersion( sourceVersion = "$Id: MethodSpecImpl.java 1258 2026-06-04 18:33:06Z tquadrat $" )
109    @API( status = INTERNAL, since = "0.0.5" )
110    public static final class BuilderImpl implements MethodSpec.Builder
111    {
112            /*------------*\
113        ====** Attributes **===================================================
114            \*------------*/
115        /**
116         *  The annotations for the method.
117         */
118        private final Collection<AnnotationSpecImpl> m_Annotations = new ArrayList<>();
119
120        /**
121         *  The code for the method.
122         */
123        @SuppressWarnings( "UseOfConcreteClass" )
124        private final CodeBlockImpl.BuilderImpl m_Code;
125
126        /**
127         *  The reference to the factory.
128         */
129        @SuppressWarnings( "UseOfConcreteClass" )
130        private final JavaComposer m_Composer;
131
132        /**
133         *  The default value for the method; this is for annotations only.
134         */
135        @SuppressWarnings( "UseOfConcreteClass" )
136        private CodeBlockImpl m_DefaultValue;
137
138        /**
139         *  The declared exceptions for the method.
140         */
141        private final Collection<TypeNameImpl> m_Exceptions = new LinkedHashSet<>();
142
143        /**
144         *  The Javadoc comment for the method.
145         */
146        @SuppressWarnings( "UseOfConcreteClass" )
147        private final CodeBlockImpl.BuilderImpl m_Javadoc;
148
149        /**
150         *  The modifiers for the method.
151         */
152        private final Set<Modifier> m_Modifiers = EnumSet.noneOf( Modifier.class );
153
154        /**
155         *  The name for the method.
156         */
157        private final String m_Name;
158
159        /**
160         *  The parameters for the method.
161         */
162        private final List<ParameterSpecImpl> m_Parameters = new ArrayList<>();
163
164        /**
165         *  The comment for the return value for the method.
166         */
167        @SuppressWarnings( "UseOfConcreteClass" )
168        private final CodeBlockImpl.BuilderImpl m_ReturnComment;
169
170        /**
171         *  The return type for the method.
172         */
173        @SuppressWarnings( "UseOfConcreteClass" )
174        private TypeNameImpl m_ReturnType;
175
176        /**
177         *  The static imports.
178         */
179        private final Collection<String> m_StaticImports = new TreeSet<>();
180
181        /**
182         *  The type variables for the method.
183         */
184        private final Collection<TypeVariableNameImpl> m_TypeVariables = new ArrayList<>();
185
186        /**
187         *  The flag that indicates whether a parameter (the last one) is a
188         *  {@code varargs} parameter.
189         */
190        private boolean m_Varargs = false;
191
192            /*--------------*\
193        ====** Constructors **=================================================
194            \*--------------*/
195        /**
196         *  Creates a new {@code BuilderImpl} instance.
197         *
198         *  @param  composer    The reference to the factory that created this
199         *      builder instance.
200         *  @param  name    The name for the method.
201         */
202        public BuilderImpl( @SuppressWarnings( "UseOfConcreteClass" ) final JavaComposer composer, final CharSequence name )
203        {
204            m_Composer = requireNonNullArgument( composer, "composer" );
205            m_Name = requireValidArgument( requireNotEmptyArgument( name, "name" ), "name", v -> v.equals( CONSTRUCTOR ) || isValidName( v ), (_,v) -> "not a valid name: %s".formatted( v ) ).toString().intern();
206            m_ReturnType = name.equals( CONSTRUCTOR ) ? null : VOID_PRIMITIVE;
207
208            m_Code = (CodeBlockImpl.BuilderImpl) m_Composer.codeBlockBuilder();
209            m_Javadoc = (CodeBlockImpl.BuilderImpl) m_Composer.codeBlockBuilder();
210            m_ReturnComment = (CodeBlockImpl.BuilderImpl) m_Composer.codeBlockBuilder();
211        }   //  BuilderImpl()
212
213            /*---------*\
214        ====** Methods **======================================================
215            \*---------*/
216        /**
217         *  {@inheritDoc}
218         */
219        @Override
220        public final BuilderImpl addAnnotation( final AnnotationSpec annotationSpec )
221        {
222            m_Annotations.add( (AnnotationSpecImpl) requireNonNullArgument( annotationSpec, "annotationSpec" ) );
223
224            //---* Done *------------------------------------------------------
225            return this;
226        }   //  addAnnotation()
227
228        /**
229         *  {@inheritDoc}
230         */
231        @Override
232        public final BuilderImpl addAnnotation( final Class<?> annotation )
233        {
234            return addAnnotation( ClassNameImpl.from( requireNonNullArgument( annotation, "annotation" ) ) );
235        }   //  addAnnotation()
236
237        /**
238         *  {@inheritDoc}
239         */
240        @Override
241        public final BuilderImpl addAnnotation( final ClassName annotationClass )
242        {
243            final var annotation = (AnnotationSpecImpl) m_Composer.annotationBuilder( requireNonNullArgument( annotationClass, "annotationClass" ) )
244                .build();
245            m_Annotations.add( annotation );
246
247            //---* Done *------------------------------------------------------
248            return this;
249        }   //  addAnnotation()
250
251        /**
252         *  {@inheritDoc}
253         */
254        @Override
255        public final BuilderImpl addAnnotations( final Iterable<? extends AnnotationSpec> annotationSpecs )
256        {
257            for( final var annotationSpec : requireNonNullArgument( annotationSpecs, "annotationSpecs" ) )
258            {
259                m_Annotations.add( (AnnotationSpecImpl) annotationSpec );
260            }
261
262            //---* Done *------------------------------------------------------
263            return this;
264        }   //  addAnnotations()
265
266        /**
267         *  {@inheritDoc}
268         */
269        @Override
270        public final BuilderImpl addCode( final CodeBlock codeBlock )
271        {
272            m_Code.add( requireNonNullArgument( codeBlock, "codeBlock" ) );
273
274            //---* Done *------------------------------------------------------
275            return this;
276        }   //  addCode()
277
278        /**
279         *  {@inheritDoc}
280         */
281        @Override
282        public final BuilderImpl addCode( final String format, final Object... args )
283        {
284            m_Code.add( format, args );
285
286            //---* Done *------------------------------------------------------
287            return this;
288        }   //  addCode()
289
290        /**
291         *  {@inheritDoc}
292         */
293        @Override
294        public final BuilderImpl addComment( final String format, final Object... args )
295        {
296            m_Code.addWithoutDebugInfo( "// " + requireNonNullArgument( format, "format" ) + "\n", args );
297
298            //---* Done *------------------------------------------------------
299            return this;
300        }   //  addComment()
301
302        /**
303         *  {@inheritDoc}
304         */
305        @Override
306        public final BuilderImpl addException( final Type exception )
307        {
308            return addException( TypeNameImpl.from( requireNonNullArgument( exception, "exception" ) ) );
309        }   //  addException()
310
311        /**
312         *  {@inheritDoc}
313         */
314        @Override
315        public final BuilderImpl addException( final TypeName exception )
316        {
317            m_Exceptions.add( (TypeNameImpl) requireNonNullArgument( exception, "exception" ) );
318
319            //---* Done *------------------------------------------------------
320            return this;
321        }   //  addException()
322
323        /**
324         *  {@inheritDoc}
325         */
326        @Override
327        public final BuilderImpl addExceptions( final Iterable<? extends TypeName> exceptions )
328        {
329            for( final var exception : requireNonNullArgument( exceptions, "exceptions" ) )
330            {
331                m_Exceptions.add( (TypeNameImpl) exception );
332            }
333
334            //---* Done *------------------------------------------------------
335            return this;
336        }   //  addExceptions()
337
338        /**
339         *  {@inheritDoc}
340         */
341        @Override
342        public final BuilderImpl addJavadoc( final CodeBlock block )
343        {
344            m_Javadoc.add( block );
345
346            //---* Done *------------------------------------------------------
347            return this;
348        }   //  addJavadoc()
349
350        /**
351         *  {@inheritDoc}
352         */
353        @Override
354        public final BuilderImpl addJavadoc( final String format, final Object... args )
355        {
356            m_Javadoc.addWithoutDebugInfo( format, args );
357
358            //---* Done *------------------------------------------------------
359            return this;
360        }   //  addJavadoc()
361
362        /**
363         *  {@inheritDoc}
364         */
365        @SuppressWarnings( {"BoundedWildcard"} )
366        @Override
367        public final BuilderImpl addModifiers( final Iterable<Modifier> modifiers )
368        {
369            for( final var modifier : requireNonNullArgument( modifiers, "modifiers" ) )
370            {
371                m_Modifiers.add( modifier );
372            }
373
374            //---* Done *------------------------------------------------------
375            return this;
376        }   //  addModifiers()
377
378        /**
379         *  {@inheritDoc}
380         */
381        @Override
382        public final BuilderImpl addModifiers( final Modifier... modifiers )
383        {
384            addAll( m_Modifiers, requireNonNullArgument( modifiers, "modifiers" ) );
385
386            //---* Done *------------------------------------------------------
387            return this;
388        }   //  addModifiers()
389
390        /**
391         *  {@inheritDoc}
392         */
393        @Override
394        public final BuilderImpl addNamedCode( final String format, final Map<String,?> args )
395        {
396            m_Code.addNamed( format, args );
397
398            //---* Done *------------------------------------------------------
399            return this;
400        }   //  addNamedCode()
401
402        /**
403         *  {@inheritDoc}
404         */
405        @Override
406        public final BuilderImpl addParameter( final ParameterSpec parameterSpec )
407        {
408            m_Parameters.add( (ParameterSpecImpl) requireNonNullArgument( parameterSpec, "parameterSpec" ) );
409
410            //---* Done *------------------------------------------------------
411            return this;
412        }   //  addParameter()
413
414        /**
415         *  {@inheritDoc}
416         */
417        @Override
418        public final BuilderImpl addParameter( final Type type, final String name, final Modifier... modifiers )
419        {
420            return addParameter( TypeName.from( requireNonNullArgument( type, "type" ) ), name, modifiers );
421        }   //  addParameter()
422
423        /**
424         *  {@inheritDoc}
425         */
426        @Override
427        public final BuilderImpl addParameter( final TypeName type, final String name, final Modifier... modifiers )
428        {
429            final var parameter =  m_Composer.parameterBuilder( type, name, modifiers )
430                .build();
431            final var retValue = addParameter( parameter );
432
433            //---* Done *----------------------------------------------------------
434            return retValue;
435        }   //  addParameter()
436
437        /**
438         *  {@inheritDoc}
439         */
440        @Override
441        public final BuilderImpl addParameters( final Iterable<? extends ParameterSpec> parameterSpecs )
442        {
443            for( final var parameterSpec : requireNonNullArgument( parameterSpecs, "parameterSpecs" ) )
444            {
445                m_Parameters.add( (ParameterSpecImpl) parameterSpec );
446            }
447
448            //---* Done *------------------------------------------------------
449            return this;
450        }   //  addParameters()
451
452        /**
453         *  {@inheritDoc}
454         */
455        @Override
456        public final BuilderImpl addStatement( final String format, final Object... args )
457        {
458            m_Code.addStatement( format, args );
459
460            //---* Done *------------------------------------------------------
461            return this;
462        }   //  addStatement()
463
464        /**
465         *  {@inheritDoc}
466         */
467        @API( status = STABLE, since = "0.2.0" )
468        @Override
469        public final MethodSpecImpl.BuilderImpl addStaticImport( final Class<?> clazz, final String... names )
470        {
471            return addStaticImport( ClassNameImpl.from( clazz ), names );
472        }   //  addStaticImport()
473
474        /**
475         *  {@inheritDoc}
476         */
477        @API( status = STABLE, since = "0.2.0" )
478        @Override
479        public final MethodSpecImpl.BuilderImpl addStaticImport( final ClassName className, final String... names )
480        {
481            final var canonicalName = requireNonNullArgument( className, "className" ).canonicalName();
482            //noinspection StandardVariableNames
483            for( final var name : requireValidNonNullArgument( names, "names", v -> v.length > 0, (n,_) -> "%s array is empty".formatted( n ) ) )
484            {
485                m_StaticImports.add(
486                    format(
487                        "%s.%s",
488                        canonicalName,
489                        requireValidArgument(
490                            name,
491                            "name",
492                            Objects::nonNull,
493                            (_,_) -> "null entry in names array: %s".formatted( Arrays.toString( names ) )
494                        )
495                    )
496                );
497            }
498
499            //---* Done *------------------------------------------------------
500            return this;
501        }   //  addStaticImport()
502
503        /**
504         *  {@inheritDoc}
505         */
506        @API( status = STABLE, since = "0.2.0" )
507        @Override
508        public final MethodSpecImpl.BuilderImpl addStaticImport( final Enum<?> constant )
509        {
510            return addStaticImport( ClassNameImpl.from( requireNonNullArgument( constant, "constant" ).getDeclaringClass() ), constant.name() );
511        }   //  addStaticImport()
512
513        /**
514         *  {@inheritDoc}
515         */
516        @Override
517        public final BuilderImpl addTypeVariable( final TypeVariableName typeVariable )
518        {
519            m_TypeVariables.add( (TypeVariableNameImpl) typeVariable );
520
521            //---* Done *------------------------------------------------------
522            return this;
523        }   //  addTypeVariable()
524
525        /**
526         *  {@inheritDoc}
527         */
528        @Override
529        public final BuilderImpl addTypeVariables( final Iterable<TypeVariableName> typeVariables )
530        {
531            for( final var typeVariable : requireNonNullArgument( typeVariables, "typeVariables" ) )
532            {
533                m_TypeVariables.add( (TypeVariableNameImpl) typeVariable );
534            }
535
536            //---* Done *------------------------------------------------------
537            return this;
538        }   //  addTypeVariables()
539
540        /**
541         *  {@inheritDoc}
542         */
543        @Override
544        public final BuilderImpl beginControlFlow( final String controlFlow, final Object... args )
545        {
546            m_Code.beginControlFlow( controlFlow, args );
547
548            //---* Done *------------------------------------------------------
549            return this;
550        }   //  beginControlFlow()
551
552        /**
553         *  {@inheritDoc}
554         */
555        @Override
556        public final MethodSpecImpl build()
557        {
558            /*
559             * A method with a body cannot be abstract.
560             * We remove the modifier abstract here so that
561             * MethodSpec.toBuilder() will work properly.
562             */
563            if( !m_Code.isEmpty() )
564            {
565                m_Modifiers.remove( ABSTRACT );
566            }
567            final var retValue = new MethodSpecImpl( this );
568
569            //---* Done *------------------------------------------------------
570            return retValue;
571        }   //  build()
572
573        /**
574         *  {@inheritDoc}
575         */
576        @Override
577        public final BuilderImpl defaultValue( final CodeBlock defaultValue )
578        {
579            checkState( isNull( m_DefaultValue ), () -> new IllegalStateException( "defaultValue was already set" ) );
580            var codeBlockImpl = (CodeBlockImpl) requireNonNullArgument( defaultValue, "defaultValue" );
581            if( m_Composer.addDebugOutput() )
582            {
583                codeBlockImpl = (CodeBlockImpl) createDebugOutput( true )
584                    .map( DebugOutput::asComment )
585                    .map( m_Composer::codeBlockOf )
586                    .map( block -> block.join( " ", defaultValue ) )
587                    .orElse( defaultValue );
588            }
589            m_DefaultValue = codeBlockImpl;
590
591            //---* Done *------------------------------------------------------
592            return this;
593        }   //  defaultValue()
594
595        /**
596         *  {@inheritDoc}
597         */
598        @Override
599        public final BuilderImpl defaultValue( final String format, final Object... args )
600        {
601            return defaultValue( m_Composer.codeBlockOf( format, args ) );
602        }   //  defaultValue()
603
604        /**
605         *  {@inheritDoc}
606         */
607        @Override
608        public final BuilderImpl endControlFlow()
609        {
610            m_Code.endControlFlow();
611
612            //---* Done *------------------------------------------------------
613            return this;
614        }   //  endControlFlow()
615
616        /**
617         *  {@inheritDoc}
618         */
619        @Override
620        public final BuilderImpl endControlFlow( final String controlFlow, final Object... args )
621        {
622            m_Code.endControlFlow( controlFlow, args );
623
624            //---* Done *------------------------------------------------------
625            return this;
626        }   //  endControlFlow()
627
628        /**
629         *  Returns <i>a reference to</i> the declared exceptions.
630         *
631         *  @return The exceptions.
632         */
633        @SuppressWarnings( {"PublicMethodNotExposedInInterface", "AssignmentOrReturnOfFieldWithMutableType"} )
634        public final Collection<TypeNameImpl> exceptions()
635        {
636            return m_Exceptions ;
637        }   //  exceptions()
638
639        /**
640         *  {@inheritDoc}
641         */
642        @Override
643        public final BuilderImpl nextControlFlow( final String controlFlow, final Object... args )
644        {
645            m_Code.nextControlFlow( controlFlow, args );
646
647            //---* Done *------------------------------------------------------
648            return this;
649        }   //  nextControlFlow()
650
651        /**
652         *  Returns <i>a reference to</i> the parameters.
653         *
654         *  @return The parameters.
655         */
656        @SuppressWarnings( {"PublicMethodNotExposedInInterface", "AssignmentOrReturnOfFieldWithMutableType"} )
657        public final List<ParameterSpecImpl> parameters()
658        {
659            return m_Parameters;
660        }   //  parameters()
661        /**
662         *  {@inheritDoc}
663         */
664        @Override
665        public final BuilderImpl returns( final Type returnType )
666        {
667            return returns( TypeNameImpl.from( requireNonNullArgument( returnType, "returnType" ) ) );
668        }   //  returns()
669
670        /**
671         *  {@inheritDoc}
672         */
673        @Override
674        public final BuilderImpl returns( final Type returnType, final String format, final Object... args )
675        {
676            return returns( TypeNameImpl.from( requireNonNullArgument( returnType, "returnType" ) ), format, args );
677        }   //  returns()
678
679        /**
680         *  {@inheritDoc}
681         */
682        @Override
683        public final BuilderImpl returns( final TypeName returnType )
684        {
685            checkState( !m_Name.equals( CONSTRUCTOR ), () -> new IllegalStateException( "constructor cannot have return type." ) );
686            m_ReturnType = (TypeNameImpl) requireNonNullArgument( returnType, "returnType" );
687            createDebugOutput( m_Composer.addDebugOutput() )
688                .ifPresent( debug -> m_ReturnComment.addWithoutDebugInfo( debug.asLiteral() ) );
689
690            //---* Done *------------------------------------------------------
691            return this;
692        }   //  returns()
693
694        /**
695         *  {@inheritDoc}
696         */
697        @Override
698        public final BuilderImpl returns( final TypeName returnType, final String format, final Object... args )
699        {
700            returns( returnType );
701            m_ReturnComment.addWithoutDebugInfo( format, args );
702
703            //---* Done *------------------------------------------------------
704            return this;
705        }   //  returns()
706
707        /**
708         *  {@inheritDoc}
709         */
710        @Override
711        public final BuilderImpl varargs() { return varargs( true ); }
712
713        /**
714         *  {@inheritDoc}
715         */
716        @Override
717        public final BuilderImpl varargs( final boolean varargs )
718        {
719            m_Varargs = varargs;
720
721            //---* Done *------------------------------------------------------
722            return this;
723        }   //  varargs()
724    }
725    //  class BuilderImpl
726
727        /*------------*\
728    ====** Attributes **=======================================================
729        \*------------*/
730    /**
731     *  The annotations of this method.
732     */
733    private final List<AnnotationSpecImpl> m_Annotations;
734
735    /**
736     *  Lazily initialised return value of
737     *  {@link #toString()}
738     *  for this instance.
739     */
740    private final Lazy<String> m_CachedString;
741
742    /**
743     *  The code of this method.
744     */
745    @SuppressWarnings( "UseOfConcreteClass" )
746    private final CodeBlockImpl m_Code;
747
748    /**
749     *  The reference to the factory.
750     */
751    @SuppressWarnings( "UseOfConcreteClass" )
752    private final JavaComposer m_Composer;
753
754    /**
755     *  The default value of this method; only applicable for annotations.
756     */
757    @SuppressWarnings( "OptionalUsedAsFieldOrParameterType" )
758    private final Optional<CodeBlockImpl> m_DefaultValue;
759
760    /**
761     *  The declared exceptions for this method.
762     */
763    private final List<TypeNameImpl> m_Exceptions;
764
765    /**
766     *  The Javadoc comment of this method.
767     */
768    @SuppressWarnings( "UseOfConcreteClass" )
769    private final CodeBlockImpl m_Javadoc;
770
771    /**
772     *  The modifiers of this method.
773     */
774    private final Set<Modifier> m_Modifiers;
775
776    /**
777     *  The name of this method.
778     */
779    private final String m_Name;
780
781    /**
782     *  The parameters of this method.
783     */
784    private final List<ParameterSpecImpl> m_Parameters;
785
786    /**
787     *  The comment for the return value of the method.
788     */
789    @SuppressWarnings( "UseOfConcreteClass" )
790    private final CodeBlockImpl m_ReturnComment;
791
792    /**
793     *  The return type of the method.
794     */
795    @SuppressWarnings( "UseOfConcreteClass" )
796    private final TypeNameImpl m_ReturnType;
797
798    /**
799     *  The static imports.
800     */
801    private final Set<String> m_StaticImports;
802
803    /**
804     *  The type variables of this method.
805     */
806    private final List<TypeVariableNameImpl> m_TypeVariables;
807
808    /**
809     *  The flag that indicates whether a parameter (the last one) is a
810     *  {@code varargs} parameter.
811     */
812    private final boolean m_Varargs;
813
814        /*--------------*\
815    ====** Constructors **=====================================================
816        \*--------------*/
817    /**
818     *  Creates a new {@code MethodSpecImpl} instance.
819     *
820     *  @param  builder The builder.
821     */
822    @SuppressWarnings( {"AccessingNonPublicFieldOfAnotherObject"} )
823    public MethodSpecImpl( @SuppressWarnings( "UseOfConcreteClass" ) final BuilderImpl builder )
824    {
825        checkState( !builder.m_Varargs || lastParameterIsArray( builder.m_Parameters ), () -> new ValidationException( "last parameter of varargs method %s must be an array".formatted( builder.m_Name ) ) );
826
827        final var code = builder.m_Code.build();
828        checkState( code.isEmpty() || !builder.m_Modifiers.contains( ABSTRACT ), () -> new ValidationException( "abstract method %s cannot have code".formatted( builder.m_Name ) ) );
829
830        m_Composer = builder.m_Composer;
831        m_Name = builder.m_Name;
832        m_Javadoc = builder.m_Javadoc.build();
833        m_Annotations = List.copyOf( builder.m_Annotations );
834        m_Modifiers = Set.copyOf( builder.m_Modifiers );
835        m_TypeVariables = List.copyOf( builder.m_TypeVariables );
836        m_ReturnType = builder.m_ReturnType;
837        m_ReturnComment = builder.m_ReturnComment.build();
838        m_Parameters = List.copyOf( builder.parameters() );
839        m_Varargs = builder.m_Varargs;
840        m_Exceptions = List.copyOf( builder.exceptions() );
841        m_DefaultValue = Optional.ofNullable( builder.m_DefaultValue );
842        m_Code = code;
843
844        final Collection<String> staticImports = new HashSet<>( builder.m_StaticImports );
845        staticImports.addAll( m_Javadoc.getStaticImports() );
846        staticImports.addAll( m_ReturnComment.getStaticImports() );
847        m_Parameters.stream()
848            .map( ParameterSpecImpl::javadoc )
849            .filter( Optional::isPresent )
850            .map( codeBlock -> codeBlock.map( block -> (CodeBlockImpl) block ).get().getStaticImports() )
851            .forEach( staticImports::addAll );
852        m_DefaultValue.ifPresent( codeBlock -> staticImports.addAll( codeBlock.getStaticImports() ) );
853        staticImports.addAll( m_Code.getStaticImports() );
854        m_StaticImports = Set.copyOf( staticImports );
855
856        m_CachedString = Lazy.use( this::initializeCachedString );
857    }   //  MethodSpecImpl()
858
859        /*---------*\
860    ====** Methods **==========================================================
861        \*---------*/
862    /**
863     *  Returns the default value of this method.
864     *
865     *  @return An instance of
866     *      {@link Optional}
867     *      that holds the default value.
868     */
869    @SuppressWarnings( "PublicMethodNotExposedInInterface" )
870    public final Optional<CodeBlockImpl> defaultValue() { return m_DefaultValue; }
871
872    /**
873     *  Emits the Javadoc to the given code writer.
874     *
875     *  @param  codeWriter  The code writer.
876     *  @throws UncheckedIOException A problem occurred when writing to the
877     *      output target.
878     */
879    private final void emitJavadoc( @SuppressWarnings( "UseOfConcreteClass" ) final CodeWriter codeWriter ) throws UncheckedIOException
880    {
881        final var javaDocBuilder = m_Javadoc.toBuilder();
882        var addNewLine = false;
883        @SuppressWarnings( {"OptionalGetWithoutIsPresent"} )
884        final var paramComments = m_Parameters.stream()
885            .filter( p -> p.javadoc().isPresent() )
886            .map( p -> (CodeBlockImpl) p.javadoc().get() )
887            .toArray( CodeBlockImpl[]::new );
888        addNewLine = paramComments.length > 0;
889        for( final var comment : paramComments )
890        {
891            javaDocBuilder.add( comment );
892        }
893        if( !m_ReturnComment.isEmpty() )
894        {
895            javaDocBuilder.add( m_Composer.codeBlockOf( "\n@return $L", m_ReturnComment ) );
896            addNewLine = true;
897        }
898        if( addNewLine ) javaDocBuilder.add( "\n" );
899        codeWriter.emitJavadoc( javaDocBuilder.build() );
900    }   //  emitJavadoc()
901
902    /**
903     *  Emits this method to the given code writer.
904     *
905     *  @param  codeWriter  The code writer.
906     *  @param  enclosingName   The name of the type that owns this method.
907     *  @param  implicitModifiers   The implicit modifiers for this method.
908     *  @throws UncheckedIOException A problem occurred when writing to the
909     *      output target.
910     */
911    @SuppressWarnings( {"PublicMethodNotExposedInInterface", "OptionalUsedAsFieldOrParameterType"} )
912    public final void emit( @SuppressWarnings( "UseOfConcreteClass" ) final CodeWriter codeWriter, final Optional<String> enclosingName, final Collection<Modifier> implicitModifiers ) throws UncheckedIOException
913    {
914        switch( codeWriter.layout() )
915        {
916            case LAYOUT_FOUNDATION -> emit4Foundation( codeWriter, enclosingName, implicitModifiers );
917            case LAYOUT_DEFAULT, LAYOUT_JAVAPOET, LAYOUT_JAVAPOET_WITH_TAB -> emit4JavaPoet( codeWriter, enclosingName, implicitModifiers );
918            default -> throw new UnsupportedEnumError( codeWriter.layout() );
919        }
920    }   //  emit()
921
922    /**
923     *  Emits this method to the given code writer, using the Foundation
924     *  layout.
925     *
926     *  @param  codeWriter  The code writer.
927     *  @param  enclosingName   The name of the type that owns this method.
928     *  @param  implicitModifiers   The implicit modifiers for this method.
929     *  @throws UncheckedIOException A problem occurred when writing to the
930     *      output target.
931     */
932    @SuppressWarnings( {"OptionalUsedAsFieldOrParameterType", "OverlyComplexMethod"} )
933    private final void emit4Foundation( @SuppressWarnings( "UseOfConcreteClass" ) final CodeWriter codeWriter, final Optional<String> enclosingName, final Collection<Modifier> implicitModifiers ) throws UncheckedIOException
934    {
935        emitJavadoc( codeWriter );
936        codeWriter.emitAnnotations( m_Annotations, false );
937        codeWriter.emitModifiers( m_Modifiers, implicitModifiers );
938
939        if( !m_TypeVariables.isEmpty() )
940        {
941            codeWriter.emitTypeVariables( m_TypeVariables );
942            codeWriter.emit( " " );
943        }
944
945        if( isConstructor() )
946        {
947            /*
948             * Anonymous types do not have a constructor, therefore there is
949             * no check required for the name.
950             */
951            //noinspection OptionalGetWithoutIsPresent
952            codeWriter.emit( "$L", enclosingName.get() );
953        }
954        else
955        {
956            codeWriter.emit( "$T $L", m_ReturnType, m_Name );
957        }
958
959        if( !m_Parameters.isEmpty() )
960        {
961            codeWriter.emit( "( " );
962            var firstParameter = true;
963            for( final var iterator = m_Parameters.iterator(); iterator.hasNext(); )
964            {
965                final var parameter = iterator.next();
966                if( !firstParameter ) codeWriter.emit( "," ).emitWrappingSpace();
967                parameter.emit( codeWriter, !iterator.hasNext() && m_Varargs );
968                firstParameter = false;
969            }
970            codeWriter.emit( " )" );
971        }
972        else
973        {
974            codeWriter.emit( "()" );
975        }
976
977        if( m_DefaultValue.isPresent() && !m_DefaultValue.get().isEmpty() )
978        {
979            codeWriter.emit( " default " );
980            codeWriter.emit( m_DefaultValue.get() );
981        }
982
983        if( !m_Exceptions.isEmpty() )
984        {
985            codeWriter.emitWrappingSpace().emit( "throws" );
986            var firstException = true;
987            for( final var exception : m_Exceptions )
988            {
989                if( !firstException ) codeWriter.emit( "," );
990                codeWriter.emitWrappingSpace().emit( "$T", exception );
991                firstException = false;
992            }
993        }
994
995        if( hasModifier( ABSTRACT ) )
996        {
997            codeWriter.emit( ";\n" );
998        }
999        else if( hasModifier( NATIVE ) )
1000        {
1001            //---* Code is allowed to support stuff like GWT JSNI *------------
1002            codeWriter.emit( m_Code );
1003            codeWriter.emit( ";\n" );
1004        }
1005        else
1006        {
1007            codeWriter.emit( "\n{" );
1008
1009            if( !m_Code.isEmpty() )
1010            {
1011                codeWriter.emit( "\n" )
1012                    .indent()
1013                    .emit( m_Code )
1014                    .unindent();
1015            }
1016
1017            if( isConstructor() )
1018            {
1019                //noinspection OptionalGetWithoutIsPresent
1020                codeWriter.emit( "}  //  $L()\n", enclosingName.get() );
1021            }
1022            else
1023            {
1024                codeWriter.emit( "}  //  $L()\n", m_Name );
1025            }
1026        }
1027    }   //  emit4Foundation()
1028
1029    /**
1030     *  Emits this method to the given code writer, using the JavaPoet layout.
1031     *
1032     *  @param  codeWriter  The code writer.
1033     *  @param  enclosingName   The name of the type that owns this method.
1034     *  @param  implicitModifiers   The implicit modifiers for this method.
1035     *  @throws UncheckedIOException A problem occurred when writing to the
1036     *      output target.
1037     */
1038    @SuppressWarnings( {"OptionalUsedAsFieldOrParameterType", "OverlyComplexMethod"} )
1039    private final void emit4JavaPoet( @SuppressWarnings( "UseOfConcreteClass" ) final CodeWriter codeWriter, final Optional<String> enclosingName, final Collection<Modifier> implicitModifiers ) throws UncheckedIOException
1040    {
1041        emitJavadoc( codeWriter );
1042        codeWriter.emitAnnotations( m_Annotations, false );
1043        codeWriter.emitModifiers( m_Modifiers, implicitModifiers );
1044
1045        if( !m_TypeVariables.isEmpty() )
1046        {
1047            codeWriter.emitTypeVariables( m_TypeVariables );
1048            codeWriter.emit( " " );
1049        }
1050
1051        if( isConstructor() )
1052        {
1053            /*
1054             * Anonymous types do not have a constructor, therefore there is
1055             * no check required for the name.
1056             */
1057            //noinspection OptionalGetWithoutIsPresent
1058            codeWriter.emit( "$L($Z", enclosingName.get() );
1059        }
1060        else
1061        {
1062            codeWriter.emit( "$T $L($Z", m_ReturnType, m_Name );
1063        }
1064
1065        var firstParameter = true;
1066        for( final var iterator = m_Parameters.iterator(); iterator.hasNext(); )
1067        {
1068            final var parameter = iterator.next();
1069            if( !firstParameter ) codeWriter.emit( "," ).emitWrappingSpace();
1070            parameter.emit( codeWriter, !iterator.hasNext() && m_Varargs );
1071            firstParameter = false;
1072        }
1073
1074        codeWriter.emit( ")" );
1075
1076        if( m_DefaultValue.isPresent() && !m_DefaultValue.get().isEmpty() )
1077        {
1078            codeWriter.emit( " default " );
1079            codeWriter.emit( m_DefaultValue.get() );
1080        }
1081
1082        if( !m_Exceptions.isEmpty() )
1083        {
1084            codeWriter.emitWrappingSpace().emit( "throws" );
1085            var firstException = true;
1086            for( final var exception : m_Exceptions )
1087            {
1088                if( !firstException ) codeWriter.emit( "," );
1089                codeWriter.emitWrappingSpace().emit( "$T", exception );
1090                firstException = false;
1091            }
1092        }
1093
1094        if( hasModifier( ABSTRACT ) )
1095        {
1096            codeWriter.emit( ";\n" );
1097        }
1098        else if( hasModifier( NATIVE ) )
1099        {
1100            //---* Code is allowed to support stuff like GWT JSNI *------------
1101            codeWriter.emit( m_Code );
1102            codeWriter.emit( ";\n" );
1103        }
1104        else
1105        {
1106            codeWriter.emit( " {\n" );
1107
1108            codeWriter.indent();
1109            codeWriter.emit( m_Code );
1110            codeWriter.unindent();
1111
1112            codeWriter.emit( "}\n" );
1113        }
1114    }   //  emit4JavaPoet()
1115
1116    /**
1117     *  {@inheritDoc}
1118     */
1119    @Override
1120    public final boolean equals( final Object o )
1121    {
1122        var retValue = this == o;
1123        if( !retValue && (o instanceof final MethodSpecImpl other) )
1124        {
1125            retValue = m_Composer.equals( other.m_Composer ) && toString().equals( o.toString() );
1126        }
1127
1128        //---* Done *----------------------------------------------------------
1129        return retValue;
1130    }   //  equals()
1131
1132    /**
1133     *  Returns the declared exceptions for this method.
1134     *
1135     *  @return The declared exceptions.
1136     */
1137    @SuppressWarnings( "PublicMethodNotExposedInInterface" )
1138    public final List<TypeNameImpl> exceptions() { return m_Exceptions; }
1139
1140    /**
1141     *  Returns the
1142     *  {@link JavaComposer}
1143     *  factory.
1144     *
1145     *  @return The reference to the factory.
1146     */
1147    @SuppressWarnings( {"PublicMethodNotExposedInInterface"} )
1148    public final JavaComposer getFactory() { return m_Composer; }
1149
1150    /**
1151     *  Returns the static imports for this code block.
1152     *
1153     *  @return The static imports.
1154     */
1155    @SuppressWarnings( "PublicMethodNotExposedInInterface" )
1156    @API( status = INTERNAL, since = "0.2.0" )
1157    public final Set<String> getStaticImports() { return m_StaticImports; }
1158
1159    /**
1160     *  {@inheritDoc}
1161     */
1162    @Override
1163    public final int hashCode() { return hash( m_Composer, toString() ); }
1164
1165    /**
1166     *  {@inheritDoc}
1167     */
1168    @Override
1169    public final boolean hasModifier( final Modifier modifier ) { return m_Modifiers.contains( requireNonNullArgument( modifier, "modifier" ) ); }
1170
1171    /**
1172     *  The initialiser for
1173     *  {@link #m_CachedString}.
1174     *
1175     *  @return The return value for
1176     *      {@link #toString()}.
1177     */
1178    private final String initializeCachedString()
1179    {
1180        final var resultBuilder = new StringBuilder();
1181        final var codeWriter = new CodeWriter( m_Composer, resultBuilder );
1182        try
1183        {
1184            emit( codeWriter, Optional.of( "Constructor" ), Set.of() );
1185        }
1186        catch( final UncheckedIOException e )
1187        {
1188            throw new UnexpectedExceptionError( e.getCause() );
1189        }
1190        final var retValue = resultBuilder.toString();
1191
1192        //---* Done *----------------------------------------------------------
1193        return retValue;
1194    }   //  initializeCachedString()
1195
1196    /**
1197     *  {@inheritDoc}
1198     */
1199    @Override
1200    public final boolean isConstructor() { return m_Name.equals( CONSTRUCTOR ); }
1201
1202    /**
1203     *  Checks whether the last entry of the given parameter list is an array.
1204     *
1205     *  @param  parameters  The parameter list.
1206     *  @return {@true} if the last entry of the given parameter list is
1207     *      an array type, {@false} if not.
1208     */
1209    @SuppressWarnings( "BooleanMethodNameMustStartWithQuestion" )
1210    private static final boolean lastParameterIsArray( final SequencedCollection<ParameterSpecImpl> parameters )
1211    {
1212        final var retValue = !parameters.isEmpty() && TypeName.asArray( (parameters.getLast().type() ) ).isPresent();
1213
1214        //---* Done *----------------------------------------------------------
1215        return retValue;
1216    }   //  lastParameterIsArray()
1217
1218    /**
1219     *  Returns a builder for a regular method.
1220     *
1221     *  @param  name    The name for the method.
1222     *  @return The builder.
1223     *
1224     *  @deprecated Got obsolete with the introduction of
1225     *      {@link JavaComposer}.
1226     */
1227    @Deprecated( since = "0.2.0", forRemoval = true )
1228    @API( status = DEPRECATED, since = "0.0.5" )
1229    public static final BuilderImpl methodBuilder( final CharSequence name )
1230    {
1231        final var retValue = new BuilderImpl( new JavaComposer(), name );
1232
1233        //---* Done *----------------------------------------------------------
1234        return retValue;
1235    }   //  methodBuilder()
1236
1237    /**
1238     *  {@inheritDoc}
1239     */
1240    @Override
1241    public final Set<Modifier> modifiers() { return m_Modifiers; }
1242
1243    /**
1244     *  {@inheritDoc}
1245     */
1246    @Override
1247    public final String name() { return m_Name; }
1248
1249    /**
1250     *  <p>{@summary Returns a new method spec builder for a method that
1251     *  overrides the given method.}</p>
1252     *  <p>This new builder will copy visibility modifiers, type parameters,
1253     *  return type, name, parameters, and throws declarations. An
1254     *  {@link Override}
1255     *  annotation will be added.</p>
1256     *
1257     *  @note   In JavaPoet&nbsp;1.2 through 1.7 this method retained
1258     *      annotations from the method and parameters of the overridden
1259     *      method. Since JavaPoet&nbsp;1.8 and in JavaComposer annotations
1260     *      must be added separately.
1261     *
1262     *  @param  method  The method to override.
1263     *  @return The builder.
1264     *
1265     *  @deprecated Got obsolete with the introduction of
1266     *      {@link JavaComposer}.
1267     */
1268    @Deprecated( since = "0.2.0", forRemoval = true )
1269    @API( status = DEPRECATED, since = "0.0.5" )
1270    public static final BuilderImpl overriding( final ExecutableElement method )
1271    {
1272        final var composer = new JavaComposer();
1273        final var retValue = (BuilderImpl) composer.overridingMethodBuilder( method );
1274
1275        //---* Done *----------------------------------------------------------
1276        return retValue;
1277    }   //  overriding()
1278
1279    /**
1280     *  <p>{@summary Returns a new method spec builder that overrides the given
1281     *  method as a member of of the given enclosing class.} This will resolve
1282     *  type parameters: for example overriding
1283     *  {@link Comparable#compareTo}
1284     *  in a type that implements {@code Comparable<Movie>}, the {@code T}
1285     *  parameter will be resolved to {@code Movie}.</p>
1286     *  <p>This will copy its visibility modifiers, type parameters, return
1287     *  type, name, parameters, and throws declarations. An
1288     *  {@link Override}
1289     *  annotation will be added.</p>
1290     *
1291     *  @note   In JavaPoet&nbsp;1.2 through 1.7 this method retained
1292     *      annotations from the method and parameters of the overridden
1293     *      method. Since JavaPoet&nbsp;1.8 and in JavaComposer annotations
1294     *      must be added separately.
1295     *
1296     *  @param  method  The method to override.
1297     *  @param  enclosing   The enclosing class for the method.
1298     *  @param  types   The type variables.
1299     *  @return The builder.
1300     *
1301     *  @deprecated Got obsolete with the introduction of
1302     *      {@link JavaComposer}.
1303     */
1304    @Deprecated( since = "0.2.0", forRemoval = true )
1305    @API( status = DEPRECATED, since = "0.0.5" )
1306    public static final BuilderImpl overriding( final ExecutableElement method, final DeclaredType enclosing, final Types types )
1307    {
1308        final var composer = new JavaComposer();
1309        final var retValue = (BuilderImpl) composer.overridingMethodBuilder( method, enclosing, types );
1310
1311        //---* Done *----------------------------------------------------------
1312        return retValue;
1313    }   //  overriding()
1314
1315    /**
1316     *  <p>{@summary Returns a new method spec builder for a method that
1317     *  overrides the given method.}</p>
1318     *  <p>This new builder will copy visibility modifiers, type parameters,
1319     *  return type, name, parameters, and throws declarations. An
1320     *  {@link Override}
1321     *  annotation will be added, but any other annotation will be omitted;
1322     *  this is consistent with the behaviour of
1323     *  {@link #overriding(ExecutableElement)}
1324     *  and
1325     *  {@link #overriding(ExecutableElement, DeclaredType, Types)}.</p>
1326     *
1327     *  @param  method  The method to override.
1328     *  @return The builder.
1329     *
1330     *  @deprecated Got obsolete with the introduction of
1331     *      {@link JavaComposer}.
1332     */
1333    @Deprecated( since = "0.2.0", forRemoval = true )
1334    @API( status = DEPRECATED, since = "0.0.8" )
1335    public static final BuilderImpl overriding( final Method method )
1336    {
1337        final var composer = new JavaComposer();
1338        final var retValue = (BuilderImpl) composer.overridingMethodBuilder( method );
1339
1340        //---* Done *----------------------------------------------------------
1341        return retValue;
1342    }   //  overriding()
1343
1344    /**
1345     *  {@inheritDoc}
1346     */
1347    @Override
1348    public final Collection<ParameterSpec> parameters() { return List.copyOf( m_Parameters ); }
1349
1350    /**
1351     *  {@inheritDoc}
1352     */
1353    @Override
1354    public final TypeName returnType()
1355    {
1356        final var retValue = nonNull( m_ReturnType ) ? m_ReturnType : VOID_PRIMITIVE;
1357
1358        //---* Done *----------------------------------------------------------
1359        return retValue;
1360    }   //  returnType()
1361
1362    /**
1363     *  {@inheritDoc}
1364     */
1365    @Override
1366    public final String signature()
1367    {
1368        final var joiner = new StringJoiner( ", ", format( "%s( ", name() ), " )" );
1369        joiner.setEmptyValue( format( "%s()", name() ) );
1370        m_Parameters.stream()
1371            .map( parameter -> parameter.type().toString() )
1372            .forEach( joiner::add );
1373        final var retValue = joiner.toString();
1374
1375        //---* Done *----------------------------------------------------------
1376        return retValue;
1377    }   //  signature()
1378
1379    /**
1380     *  {@inheritDoc}
1381     */
1382    @SuppressWarnings( {"AccessingNonPublicFieldOfAnotherObject"} )
1383    @Override
1384    public final BuilderImpl toBuilder( final boolean omitCode )
1385    {
1386        final var retValue = new BuilderImpl( m_Composer, m_Name );
1387        retValue.m_Javadoc.addWithoutDebugInfo( m_Javadoc );
1388        retValue.m_Annotations.addAll( m_Annotations );
1389        retValue.m_Modifiers.addAll( m_Modifiers );
1390        if( omitCode ) retValue.m_Modifiers.add( ABSTRACT );
1391        retValue.m_TypeVariables.addAll( m_TypeVariables );
1392        retValue.m_ReturnType = m_ReturnType;
1393        retValue.m_ReturnComment.addWithoutDebugInfo( m_ReturnComment );
1394        retValue.m_Parameters.addAll( m_Parameters );
1395        retValue.m_Exceptions.addAll( m_Exceptions );
1396        if( !omitCode ) retValue.m_Code.addWithoutDebugInfo( m_Code );
1397        retValue.m_Varargs = m_Varargs;
1398        retValue.m_DefaultValue = m_DefaultValue.orElse( null );
1399        retValue.m_StaticImports.addAll( m_StaticImports );
1400
1401        //---* Done *----------------------------------------------------------
1402        return retValue;
1403    }   //  toBuilder()
1404
1405    /**
1406     *  {@inheritDoc}
1407     */
1408    @Override
1409    public final String toString() { return m_CachedString.get(); }
1410}
1411//  class MethodSpecImpl
1412
1413/*
1414 *  End of File
1415 */