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.cli;
019
020import static org.apiguardian.api.API.Status.INTERNAL;
021import static org.tquadrat.foundation.config.CmdLineException.MSGKEY_IllegalOperand;
022import static org.tquadrat.foundation.config.CmdLineException.MSGKEY_InvalidFormat;
023import static org.tquadrat.foundation.config.CmdLineException.MSG_IllegalOperand;
024import static org.tquadrat.foundation.config.CmdLineException.MSG_InvalidFormat;
025import static org.tquadrat.foundation.lang.Objects.requireNonNullArgument;
026
027import java.text.ParseException;
028import java.text.SimpleDateFormat;
029import java.util.Collection;
030import java.util.Date;
031import java.util.List;
032import java.util.Locale;
033import java.util.function.BiConsumer;
034
035import org.apiguardian.api.API;
036import org.tquadrat.foundation.annotation.ClassVersion;
037import org.tquadrat.foundation.config.CmdLineException;
038import org.tquadrat.foundation.config.spi.CLIDefinition;
039import org.tquadrat.foundation.config.spi.Parameters;
040
041/**
042 *  <p>{@summary An implementation of
043 *  {@link CmdLineValueHandler}
044 *  for
045 *  {@link Date}
046 *  values.}</p>
047 *  <p>The method
048 *  {@link #translate(Parameters)}
049 *  will use
050 *  {@link SimpleDateFormat}
051 *  to parse the given String to an instance of {@code Date}.</p>
052 *
053 *  @extauthor Thomas Thrien - thomas.thrien@tquadrat.org
054 *  @version $Id: DateValueHandler.java 1061 2023-09-25 16:32:43Z tquadrat $
055 *  @since 0.0.1
056 *
057 *  @UMLGraph.link
058 */
059@SuppressWarnings( "UseOfObsoleteDateTimeApi" )
060@ClassVersion( sourceVersion = "$Id: DateValueHandler.java 1061 2023-09-25 16:32:43Z tquadrat $" )
061@API( status = INTERNAL, since = "0.0.1" )
062public final class DateValueHandler extends CmdLineValueHandler<Date>
063{
064        /*--------------*\
065    ====** Constructors **=====================================================
066        \*--------------*/
067    /**
068     *  Creates a new {@code DateValueHandler} instance.
069     *
070     *  @param  context The CLI definition that provides the context for this
071     *      value handler.
072     *  @param  valueSetter The function that places the translated value to
073     *      the property.
074     */
075    public DateValueHandler( final CLIDefinition context, final BiConsumer<String,Date> valueSetter )
076    {
077        //---* Daddy will do the null check *----------------------------------
078        super( context, valueSetter );
079    }   //  DateValueHandler()
080
081    /**
082     *  Creates a new {@code DateValueHandler} instance.
083     *
084     *  @param  valueSetter The function that places the translated value to
085     *      the property.
086     */
087    public DateValueHandler( final BiConsumer<String,Date> valueSetter )
088    {
089        //---* Daddy will do the null check *----------------------------------
090        super( valueSetter );
091    }   //  DateValueHandler()
092
093        /*---------*\
094    ====** Methods **==========================================================
095        \*---------*/
096    /**
097     *  Retrieves the format that was given with the annotation; if that is
098     *  empty or {@code null}, the default &quot;{@code yyyy-MM-dd}&quot; will
099     *  be returned.<br>
100     *  <br>Override this method for a different default.
101     *
102     *  @return The date format to use by the parser.
103     */
104    private final String getFormat()
105    {
106        final var retValue = getCLIDefinition()
107            .flatMap( CLIDefinition::format )
108            .orElse( "yyyy-MM-dd" );
109
110        //---* Done *----------------------------------------------------------
111        return retValue;
112    }   //  getFormat()
113
114    /**
115     *  {@inheritDoc}
116     */
117    @Override
118    protected final Collection<Date> translate( final Parameters params ) throws CmdLineException
119    {
120        final Collection<Date> retValue;
121        final var argument = requireNonNullArgument( params, "params" ).getParameter( 0 );
122        try
123        {
124            final var parser = new SimpleDateFormat( getFormat(), Locale.getDefault() );
125            parser.setLenient( false );
126            final var date = parser.parse( requireNonNullArgument( argument, "argument" ) );
127            retValue = List.of( date );
128        }
129        catch( final ParseException e )
130        {
131            final var metaVar = getCLIDefinition()
132                .map( CLIDefinition::metaVar )
133                .orElse( "DATE" );
134            throw new CmdLineException( MSG_IllegalOperand, e, MSGKEY_IllegalOperand, metaVar, argument );
135        }
136        catch( final IllegalArgumentException e )
137        {
138            final var format = getFormat();
139            throw new CmdLineException( MSG_InvalidFormat, e, MSGKEY_InvalidFormat, format );
140        }
141
142        //---* Done *----------------------------------------------------------
143        return retValue;
144    }   //  translate()
145}
146//  class DateValueHandler
147
148/*
149 *  End of File
150 */