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.i18n;
019
020import static java.lang.annotation.ElementType.FIELD;
021import static java.lang.annotation.ElementType.METHOD;
022import static java.lang.annotation.RetentionPolicy.SOURCE;
023import static org.apiguardian.api.API.Status.STABLE;
024import static org.tquadrat.foundation.i18n.TextUse.TEXTUSE_DEFAULT;
025
026import java.lang.annotation.Repeatable;
027import java.lang.annotation.Retention;
028import java.lang.annotation.Target;
029
030import org.apiguardian.api.API;
031import org.tquadrat.foundation.annotation.ClassVersion;
032
033/**
034 *  <p>{@summary Use this annotation to define a text &ndash; usually for a UI
035 *  element or alike &ndash; that has to be translated.} Messages will be
036 *  defined with the annotation
037 *  {@link Message}.</p>
038 *  <p>The texts will be stored in a
039 *  {@link java.util.ResourceBundle ResourceBundle}
040 *  with the base bundle name that is identified through the annotation
041 *  {@link BaseBundleName &#64;BaseBundleName}.
042 *  The documentation for the method
043 *  {@link java.util.ResourceBundle#getBundle(String,java.util.Locale,ClassLoader) getBundle()}
044 *  describes the detection strategy. The build process takes care of the
045 *  generation of the resource bundle properties file.</p>
046 *  <p>Use this annotation as follows:</p>
047 *  <pre><code>  &hellip;
048 *  &#64;Text
049 *  (
050 *      description = "A text",
051 *      translations =
052 *      {
053 *          &#64;Translation( language = "en", text = "English text" ),
054 *          &#64;Translation( language = "de", text = "Text in Deutsch" )
055 *      }
056 *  )
057 *  private static final String TXT_TextKey = I18nUtil.composeTextKey( SampleClass.class, TextUse.TXT, "TextKey" );
058 *  &hellip;</code></pre>
059 *  <p>For the generation, the content of the field {@code TXT_TextKey} is
060 *  irrelevant, the key will be built from the name of the field plus the
061 *  fully qualified name of the class. But for the retrieval of the text, the
062 *  contents of the field needs to match that generated key.</p>
063 *  <p>The prefix {@code TXT} is defined in
064 *  {@link TextUse}
065 *  and will be derived from the name; if this is not desired, an alternative
066 *  form of the annotation can be used:</p>
067 *  <pre><code>  &hellip;
068 *  &#64;Text
069 *  (
070 *      &hellip;
071 *  )
072 *  private static final String m_TextKey = I18nUtil.composeTextKey( SampleClass.class, TextUse.TXT, "TextKey" );
073 *  &hellip;</code></pre>
074 *  <p>This works because {@code TXT} is the default for the text use.</p>
075 *  <p>It is also possible to define the id and the text use explicitly:</p>
076 *  <pre><code>  &hellip;
077 *  &#64;Text
078 *  (
079 *      description = "A text",
080 *      id = "TextKey",
081 *      use = TextUse.TXT,
082 *      translations =
083 *      {
084 *          &#64;Translation( language = "en", text = "English text" ),
085 *          &#64;Translation( language = "de", text = "Text in Deutsch" )
086 *      }
087 *  )
088 *  private static final String m_Text = I18nUtil.composeTextKey( SampleClass.class, TextUse.TXT, "TextKey" );
089 *  &hellip;</code></pre>
090 *  <p>This format is required when the annotation is applied to a method, in
091 *  this case to a getter:</p>
092 *  <pre><code>  &hellip;
093 *  &#64;Text
094 *  (
095 *      description = "The name of the property",
096 *      translations =
097 *      {
098 *          &#64;Translation( language = "en", text = "Property" ),
099 *          &#64;Translation( language = "de", text = "Eigenschaft" )
100 *      }
101 *  )
102 *  &#64;Text
103 *  (
104 *      description = "The caption for the property",
105 *      use = TextUse.CAPTION,
106 *      translations =
107 *      {
108 *          &#64;Translation( language = "en", text = "Property: " ),
109 *          &#64;Translation( language = "de", text = "Eigenschaft: " )
110 *      }
111 *  )
112 *  &#64;Text
113 *  (
114 *      description = "The tooltip for the property",
115 *      use = TextUse.TOOLTIP,
116 *      translations =
117 *      {
118 *          &#64;Translation( language = "en", text = "The property" ),
119 *          &#64;Translation( language = "de", text = "Die Eigenschaft" )
120 *      }
121 *  )
122 *  public String getProperty();
123 *  &hellip;</code></pre>
124 *  <p>This sample would generate texts with the keys below, given that the
125 *  method belongs to the interface {@code com.sample.Example}:</p>
126 *  <ul>
127 *      <li>{@code com.sample.Example.NAME_Property}</li>
128 *      <li>{@code com.sample.Example.CAPTION_Property}</li>
129 *      <li>{@code com.sample.Example.TOOLTIP_Property}</li>
130 *  </ul>
131 *  <p>If the method is not a getter, a setter or an &quot;add&quot; method,
132 *  both {@code id} and {@code use} are always mandatory.</p>
133 *  <p>For {@code enum}s, this form is applicable:</p>
134 *  <pre><code>  &hellip;
135 *  public enum WhatEver
136 *  {
137 *      &#64;Text
138 *      (
139 *          description = "The name for an enum value",
140 *          translations =
141 *          {
142 *              &#64;Translation( language = "en", text = "Enumeration Value" ),
143 *              &#64;Translation( language = "de", text = "Aufz&auml;hlungswert" )
144 *          }
145 *      )
146 *      ENUM_VALUE;
147 *
148 *      &hellip;
149 *  }
150 *  //  enum WhatEver</code></pre>
151 *  <p>The argument for
152 *  {@link java.util.ResourceBundle#getString(String) ResourceBundle.getString()}
153 *  in this case can be composed through a call to
154 *  {@link org.tquadrat.foundation.i18n.I18nUtil#composeTextKey(Enum) I18nUtil.composeTextKey()};
155 *  that can be used for the implementation of
156 *  {@code WhatEver.toString()} like this:</p>
157 *  <pre><code>  &hellip;
158 *  public final toString()
159 *  {
160 *      String key = composeTextKey( this );
161 *      String retValue = getBundle().getString( key );
162 *
163 *      &#47;&#47;---* Done *-----------------------------------------------------------
164 *      return retValue;
165 *  }  &#47;&#47;  toString()
166 *  &hellip;</code></pre>
167 *  <p>Different from messages, it is somehow expected that the returned values
168 *  may contain escape sequences that can be converted by a call to
169 *  {@link String#translateEscapes()}.</p>
170 *
171 *  @extauthor Thomas Thrien - thomas.thrien@tquadrat.org
172 *  @version $Id: Text.java 1062 2023-09-25 23:11:41Z tquadrat $
173 *  @since 0.1.0
174 */
175@SuppressWarnings( "NewClassNamingConvention" )
176@Retention( SOURCE )
177@Target( {FIELD, METHOD} )
178@Repeatable( Texts.class )
179@ClassVersion( sourceVersion = "$Id: Text.java 1062 2023-09-25 23:11:41Z tquadrat $" )
180@API( status = STABLE, since = "0.1.0" )
181public @interface Text
182{
183        /*------------*\
184    ====** Attributes **=======================================================
185        \*------------*/
186    /**
187     *  Returns the description for the text.
188     *
189     *  @return The description.
190     */
191    String description();
192
193    /**
194     *  <p>{@summary The use of the text; the default is
195     *  {@link TextUse#TEXTUSE_DEFAULT}.}</p>
196     *  <p>This will be replaced with
197     *  {@link TextUse#NAME}
198     *  if the annotated element is method for a property (a getter, setter or
199     *  an &quot;add&quot; method),
200     *  with
201     *  {@link TextUse#STRING}
202     *  if an {@code enum} is annotated, and with
203     *  {@link TextUse#TXT}
204     *  for any other case.</p>
205     *
206     *  @return The text use.
207     */
208    TextUse use() default TEXTUSE_DEFAULT;
209
210    /**
211     *  Returns the text id for the text. If empty, the <i>name</i> of the
212     *  annotated field is used when the annotation is applied to field;
213     *  otherwise the annotation processor will throw an error.
214     *
215     *  @return The id, if set; otherwise the empty String.
216     */
217    @SuppressWarnings( "NewMethodNamingConvention" ) String id() default "";
218
219    /**
220     *  Returns the list of valid translations for the text.
221     *
222     *  @return The translations.
223     */
224    Translation [] translations();
225}
226//  annotation Text
227
228/*
229 *  End of File
230 */