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.internal;
019
020import static org.apiguardian.api.API.Status.STABLE;
021import static org.tquadrat.foundation.config.internal.MessageRegistry.MSG_REGISTRY_FALLBACK;
022import static org.tquadrat.foundation.config.internal.MessageRegistry.m_MessageRegistry;
023import static org.tquadrat.foundation.lang.Objects.requireNonNullArgument;
024
025import java.util.MissingResourceException;
026import java.util.ResourceBundle;
027
028import org.apiguardian.api.API;
029import org.tquadrat.foundation.annotation.ClassVersion;
030import org.tquadrat.foundation.annotation.UtilityClass;
031import org.tquadrat.foundation.config.CmdLineException;
032import org.tquadrat.foundation.exception.PrivateConstructorForStaticClassCalledError;
033import org.tquadrat.foundation.i18n.BaseBundleName;
034import org.tquadrat.foundation.i18n.I18nUtil;
035import org.tquadrat.foundation.i18n.MessagePrefix;
036import org.tquadrat.foundation.i18n.UseAdditionalTexts;
037import org.tquadrat.foundation.lang.Objects;
038import org.tquadrat.foundation.lang.StringConverter;
039
040/**
041 *  The internal tools for the configuration module.
042 *
043 *  @extauthor Thomas Thrien - thomas.thrien@tquadrat.org
044 *  @version $Id: Commons.java 1061 2023-09-25 16:32:43Z tquadrat $
045 *  @UMLGraph.link
046 *  @since 0.1.0
047 */
048@UtilityClass
049@ClassVersion( sourceVersion = "$Id: Commons.java 1061 2023-09-25 16:32:43Z tquadrat $" )
050@API( status = STABLE, since = "0.1.0" )
051@UseAdditionalTexts
052public final class Commons
053{
054        /*-----------*\
055    ====** Constants **========================================================
056        \*-----------*/
057    /**
058     *  The name of the resource bundle with the messages and texts for this
059     *  module: {@value}.
060     */
061    @SuppressWarnings( "DefaultAnnotationParam" )
062    @BaseBundleName( defaultLanguage = "en" )
063    public static final String BASE_BUNDLE_NAME = "org.tquadrat.foundation.config.MessagesAndTexts";
064
065    /**
066     *  The message prefix: {@value}.
067     */
068    @MessagePrefix
069    public static final String MESSAGE_PREFIX = "CFG";
070
071        /*------------*\
072    ====** Attributes **=======================================================
073        \*------------*/
074
075        /*------------------------*\
076    ====** Static Initialisations **===========================================
077        \*------------------------*/
078    /**
079     *  The resource bundle that is used by this module.
080     */
081    private static final ResourceBundle m_ResourceBundle;
082
083    static
084    {
085        final var module = Commons.class.getModule();
086        try
087        {
088            if( module.isNamed() )
089            {
090                m_ResourceBundle = ResourceBundle.getBundle( BASE_BUNDLE_NAME, module );
091            }
092            else
093            {
094                m_ResourceBundle = ResourceBundle.getBundle( BASE_BUNDLE_NAME );
095            }
096        }
097        catch( final MissingResourceException e )
098        {
099            final var error = new ExceptionInInitializerError( "Cannot load ResourceBundle '%s'".formatted( BASE_BUNDLE_NAME ) );
100            error.initCause( e );
101            throw error;
102        }
103    }
104
105        /*--------------*\
106    ====** Constructors **=====================================================
107        \*--------------*/
108    /**
109     *  No instance allowed for this class!
110     */
111    private Commons() { throw new PrivateConstructorForStaticClassCalledError( Commons.class ); }
112
113        /*---------*\
114    ====** Methods **==========================================================
115        \*---------*/
116    /**
117     *  Creates an instance of
118     *  {@link org.tquadrat.foundation.config.CmdLineException}
119     *  based on the given arguments.
120     *   @param  stringConverterClass    The class of the
121     *      {@link StringConverter}
122     *      implementation.
123     *  @param  cause   The causing
124     *      {@link Exception}.
125     *  @param  value   The problematic value.
126     *  @return The instance of
127     *      {@link CmdLineException}.
128     */
129    @SuppressWarnings( {"rawtypes"} )
130    public static final CmdLineException createException( final Class<? extends StringConverter> stringConverterClass, final Throwable cause, final String value )
131    {
132        final var entry = m_MessageRegistry.getOrDefault( requireNonNullArgument( stringConverterClass, "stringConverterClass" ), MSG_REGISTRY_FALLBACK );
133        final var retValue = new CmdLineException( entry.message(), cause, entry.key(), value );
134
135        //---* Done *----------------------------------------------------------
136        return retValue;
137    }   //  createException()
138
139    /**
140     *  <p>{@summary Retrieves the message with the given key from the resource
141     *  bundle and applies the given arguments to it.}</p>
142     *  <p>If the resource bundle does not contain a message for the given key,
143     *  the key itself will be returned, appended with the arguments.</p>
144     *
145     *  @param  key The key for the message.
146     *  @param  addKey  The recommended value is {@code true}; this means that
147     *      the message will be prefixed with the generated message key.
148     *  @param  args    The arguments for the message.
149     *  @return The text.
150     *
151     *  @see Objects#toString(Object)
152     */
153    public static final String retrieveMessage( final int key, final boolean addKey, final Object... args )
154    {
155        final var retValue = I18nUtil.retrieveMessage( m_ResourceBundle, MESSAGE_PREFIX, key, addKey, args );
156
157        //---* Done *----------------------------------------------------------
158        return retValue;
159    }   //  retrieveMessage()
160
161    /**
162     *  <p>{@summary Retrieves the text with the given key from the resource
163     *  bundle and applies the given arguments to it.}</p>
164     *  <p>If the resource bundle does not contain a text for the given key,
165     *  the key itself will be returned, appended with the arguments.</p>
166     *
167     *  @param  key The key for the text.
168     *  @param  args    The arguments for the text.
169     *  @return The text.
170     *
171     *  @see Objects#toString(Object)
172     */
173    public static final String retrieveText( final String key, final Object... args )
174    {
175        final var retValue = I18nUtil.retrieveText( m_ResourceBundle, key, args );
176
177        //---* Done *----------------------------------------------------------
178        return retValue;
179    }   //  retrieveText()
180}
181//  class Commons
182
183/*
184 *  End of File
185 */