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;
019
020import static org.apiguardian.api.API.Status.STABLE;
021import static org.tquadrat.foundation.config.SpecialPropertyType.CONFIG_PROPERTY_MESSAGEPREFIX;
022import static org.tquadrat.foundation.i18n.I18nUtil.composeMessageKey;
023import static org.tquadrat.foundation.i18n.I18nUtil.composeTextKey;
024import static org.tquadrat.foundation.i18n.I18nUtil.createFallback;
025import static org.tquadrat.foundation.i18n.I18nUtil.retrieveMessage;
026import static org.tquadrat.foundation.i18n.I18nUtil.retrieveText;
027
028import org.apiguardian.api.API;
029import org.tquadrat.foundation.annotation.ClassVersion;
030import org.tquadrat.foundation.i18n.TextUse;
031
032/**
033 *  <p>{@summary A configuration bean specification has to extend this
034 *  interface in order to get the i18n support.}</p>
035 *  <p>The extending bean needs to provide two String constants:</p>
036 *  <ul>
037 *      <li>The base bundle name, marked with the annotation
038 *      {@link org.tquadrat.foundation.i18n.BaseBundleName &#64;BaseBundleName}</li>
039 *      <li>The message prefix, marked with the annotation
040 *      {@link org.tquadrat.foundation.i18n.MessagePrefix &#64;MessagePrefix}</li>
041 *  </ul>
042 *  <p>If the annotation processor cannot find these annotations in the
043 *  configuration bean specification, it will throw an error. This behaviour is
044 *  different from that when the i18n support is used independent from a
045 *  configuration bean.</p>
046 *  <p>When the methods</p>
047 *  <ul>
048 *      <li>{@link #getMessage(int,Object...)}</li>
049 *      <li>{@link #getMessage(String,Object...)}</li>
050 *      <li>{@link #getString(Enum)}</li>
051 *      <li>{@link #getText(String, Object...)}</li>
052 *      <li>{@link #getText(Class, TextUse, String, Object...)}</li>
053 *  </ul> TODO ??
054 *
055 *  @note   The configuration bean specification may not define a setter for
056 *      the resource bundle property if it extends this interface!
057 *
058 *  @extauthor Thomas Thrien - thomas.thrien@tquadrat.org
059 *  @version $Id: I18nSupport.java 1061 2023-09-25 16:32:43Z tquadrat $
060 *  @since 0.0.2
061 *
062 *  @UMLGraph.link
063 */
064@ClassVersion( sourceVersion = "$Id: I18nSupport.java 1061 2023-09-25 16:32:43Z tquadrat $" )
065@API( status = STABLE, since = "0.0.2" )
066public interface I18nSupport extends ConfigBeanSpec
067{
068        /*---------*\
069    ====** Methods **==========================================================
070        \*---------*/
071    /**
072     *  Returns the message for the given message id.
073     *
074     *  @param  messageId   The message id.
075     *  @param  args    The message arguments.
076     *  @return The message.
077     */
078    public default String getMessage( final String messageId, final Object... args )
079    {
080        final var retValue = getResourceBundle().map( resourceBundle -> retrieveMessage( resourceBundle, getMessagePrefix(), messageId, true, args ) )
081            .orElseGet( () -> createFallback( composeMessageKey( getMessagePrefix(), messageId ), args ) );
082
083        //---* Done *----------------------------------------------------------
084        return retValue;
085    }   //  getMessage()
086
087    /**
088     *  Returns the message for the given message id.
089     *
090     *  @param  messageId   The message id.
091     *  @param  args    The message arguments.
092     *  @return The message.
093     */
094    public default String getMessage( final int messageId, final Object... args )
095    {
096        final var retValue = getResourceBundle().map( resourceBundle -> retrieveMessage( resourceBundle, getMessagePrefix(), messageId, true, args ) )
097            .orElseGet( () -> createFallback( composeMessageKey( getMessagePrefix(), messageId ), args ) );
098
099        //---* Done *----------------------------------------------------------
100        return retValue;
101    }   //  getMessage()
102
103    /**
104     *  Returns the message prefix.
105     *
106     *  @return The message prefix.
107     *
108     *  @see org.tquadrat.foundation.i18n.MessagePrefix
109     */
110    @SpecialProperty( CONFIG_PROPERTY_MESSAGEPREFIX )
111    public String getMessagePrefix();
112
113    /**
114     *  Returns the String representation for the given {@code enum}.
115     *
116     *  @param  <E> The type of the {@code enum} value.
117     *  @param  value   The enum value.
118     *  @return The String representation.
119     */
120    public default <E extends Enum<?>> String getString( final E value )
121    {
122        final var retValue = getResourceBundle()
123            .map( bundle -> retrieveText( bundle, value ) )
124            .orElse( createFallback( composeTextKey( value ) ) );
125
126        //---* Done *----------------------------------------------------------
127        return retValue;
128    }   //  getString()
129
130    /**
131     *  Returns the text for the key that will be composed of the given
132     *  components.
133     *
134     *  @param  sourceClass The class that defines the text.
135     *  @param  use The text use.
136     *  @param  id  The id for the text.
137     *  @param  args    The text arguments.
138     *  @return The text.
139     *
140     *  @see org.tquadrat.foundation.i18n.I18nUtil#composeTextKey(Class, TextUse, String)
141     */
142    public default String getText( final Class<?> sourceClass, final TextUse use, final String id, final Object... args )
143    {
144        return getText( composeTextKey( sourceClass, use, id ), args );
145    }   //  getText()
146
147    /**
148     *  Returns the text for the given key.
149     *
150     *  @param  key The resource bundle key for the text.
151     *  @param  args    The text arguments.
152     *  @return The text.
153     */
154    public default String getText( final String key, final Object... args )
155    {
156        final var retValue = getResourceBundle()
157            .map( bundle -> retrieveText( bundle, key, args ) )
158            .orElse( createFallback( key, args ) )
159            .translateEscapes();
160
161        //---* Done *----------------------------------------------------------
162        return retValue;
163    }   //  getText()
164}
165//  class I18nSupport
166
167/*
168 *  End of File
169 */