001/*
002 * ============================================================================
003 *  Copyright © 2002-2023 by Thomas Thrien.
004 *  All Rights Reserved.
005 * ============================================================================
006 *  Licensed to the public under the agreements of the GNU Lesser General Public
007 *  License, version 3.0 (the "License"). You may obtain a copy of the License at
008 *
009 *       http://www.gnu.org/licenses/lgpl.html
010 *
011 *  Unless required by applicable law or agreed to in writing, software
012 *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
013 *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
014 *  License for the specific language governing permissions and limitations
015 *  under the License.
016 */
017
018package org.tquadrat.foundation.config.ap.impl.specialprops;
019
020import static javax.lang.model.element.Modifier.FINAL;
021import static javax.lang.model.element.Modifier.PRIVATE;
022import static org.apiguardian.api.API.Status.STABLE;
023import static org.tquadrat.foundation.config.SpecialPropertyType.CONFIG_PROPERTY_CLOCK;
024import static org.tquadrat.foundation.config.ap.PropertySpec.PropertyFlag.EXEMPT_FROM_TOSTRING;
025import static org.tquadrat.foundation.config.ap.PropertySpec.PropertyFlag.PROPERTY_IS_MUTABLE;
026import static org.tquadrat.foundation.config.ap.PropertySpec.PropertyFlag.SETTER_CHECK_NULL;
027import static org.tquadrat.foundation.lang.Objects.requireNonNullArgument;
028
029import java.time.Clock;
030import java.util.Optional;
031import java.util.function.BiFunction;
032
033import org.apiguardian.api.API;
034import org.tquadrat.foundation.annotation.ClassVersion;
035import org.tquadrat.foundation.config.SpecialPropertyType;
036import org.tquadrat.foundation.config.ap.impl.CodeBuilder;
037import org.tquadrat.foundation.config.ap.impl.PropertySpecImpl;
038import org.tquadrat.foundation.javacomposer.ClassName;
039import org.tquadrat.foundation.javacomposer.CodeBlock;
040import org.tquadrat.foundation.javacomposer.FieldSpec;
041import org.tquadrat.foundation.javacomposer.TypeName;
042
043/**
044 *  The implementation of
045 *  {@link SpecialPropertySpecBase}
046 *  for
047 *  {@link SpecialPropertyType#CONFIG_PROPERTY_CLOCK}.
048 *
049 *  @version $Id: ClockProperty.java 1061 2023-09-25 16:32:43Z tquadrat $
050 *  @extauthor Thomas Thrien - thomas.thrien@tquadrat.org
051 *  @UMLGraph.link
052 *  @since 0.1.0
053 */
054@ClassVersion( sourceVersion = "$Id: ClockProperty.java 1061 2023-09-25 16:32:43Z tquadrat $" )
055@API( status = STABLE, since = "0.1.0" )
056public final class ClockProperty extends SpecialPropertySpecBase
057{
058        /*--------------*\
059    ====** Constructors **=====================================================
060        \*--------------*/
061    /**
062     *  Creates a new instance of {@code ClockProperty}.
063     */
064    public ClockProperty()
065    {
066        super( CONFIG_PROPERTY_CLOCK, EXEMPT_FROM_TOSTRING, PROPERTY_IS_MUTABLE, SETTER_CHECK_NULL );
067    }   //  ClockProperty()
068
069        /*---------*\
070    ====** Methods **==========================================================
071        \*---------*/
072    /**
073     *  Composes the constructor fragment for the initialisation of this
074     *  property.
075     *
076     *  @param  codeBuilder The factory for the code generation.
077     *  @param  property    The property.
078     *  @return The field specification.
079     */
080    @SuppressWarnings( "TypeMayBeWeakened" )
081    private static final CodeBlock composeConstructorFragment( final CodeBuilder codeBuilder, @SuppressWarnings( "UseOfConcreteClass" ) final PropertySpecImpl property )
082    {
083        final var builder = requireNonNullArgument( codeBuilder, "codeBuilder" ).getComposer()
084            .codeBlockBuilder()
085            .add(
086                """
087                
088                /*
089                 * Initialise the property '$N'.
090                 */
091                """, property.getPropertyName()
092            )
093            .addStatement( "$1N = $2T.systemDefaultZone()", property.getFieldName(), Clock.class );
094
095        //---* Create the return value *---------------------------------------
096        final var retValue = builder.build();
097
098        //---* Done *----------------------------------------------------------
099        return retValue;
100    }   //  composeConstructorFragment()
101
102    /**
103     *  The method that composes the field for the 'clock' property.
104     *
105     *  @param  codeBuilder The factory for the code generation.
106     *  @param  property    The property.
107     *  @return The field specification.
108     */
109    @SuppressWarnings( "TypeMayBeWeakened" )
110    public static FieldSpec composeField( final CodeBuilder codeBuilder, @SuppressWarnings( "UseOfConcreteClass" ) final PropertySpecImpl property )
111    {
112        final var composer = requireNonNullArgument( codeBuilder, "codeBuilder" ).getComposer();
113
114        final var builder = composer.fieldBuilder( property.getPropertyType(), property.getFieldName(), PRIVATE )
115            .addJavadoc(
116                """
117                Special Property: "$L".
118                """, property.getPropertyName() );
119        if( !property.hasFlag( PROPERTY_IS_MUTABLE ) ) builder.addModifiers( FINAL );
120
121        //---* Create the return value *--------------------------------------
122        final var retValue = builder.build();
123
124        //---* Done *----------------------------------------------------------
125        return retValue;
126    }   //  composeField()
127
128    /**
129     *  {@inheritDoc}
130     */
131    @Override
132    public final Optional<TypeName> getCLIValueHandlerClass() { return Optional.empty(); }
133
134    /**
135     *  {@inheritDoc}
136     */
137    @Override
138    public final Optional<BiFunction<CodeBuilder,PropertySpecImpl,CodeBlock>> getConstructorFragmentComposer() { return Optional.of( ClockProperty::composeConstructorFragment );}
139
140    /**
141     * {@inheritDoc}
142     */
143    @Override
144    public final Optional<BiFunction<CodeBuilder,PropertySpecImpl, FieldSpec>> getFieldComposer() { return Optional.of( ClockProperty::composeField ); }
145
146    /**
147     *  {@inheritDoc}
148     */
149    @Override
150    public final Optional<TypeName> getPrefsAccessorClass() { return Optional.empty(); }
151
152    /**
153     *  {@inheritDoc}
154     */
155    @Override
156    public final TypeName getPropertyType() { return ClassName.from( Clock.class ); }
157
158    /**
159     *  {@inheritDoc}
160     */
161    @Override
162    public final Optional<TypeName> getStringConverterClass() { return Optional.empty(); }
163}
164//  class ClockProperty
165
166/*
167 *  End of File
168 */