View Javadoc
1   // SECTION-START[License Header]
2   // <editor-fold defaultstate="collapsed" desc=" Generated License ">
3   /*
4    * Java Object Management and Configuration
5    * Copyright (C) Christian Schulte <cs@schulte.it>, 2011-313
6    * All rights reserved.
7    *
8    * Redistribution and use in source and binary forms, with or without
9    * modification, are permitted provided that the following conditions
10   * are met:
11   *
12   *   o Redistributions of source code must retain the above copyright
13   *     notice, this list of conditions and the following disclaimer.
14   *
15   *   o Redistributions in binary form must reproduce the above copyright
16   *     notice, this list of conditions and the following disclaimer in
17   *     the documentation and/or other materials provided with the
18   *     distribution.
19   *
20   * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
21   * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
22   * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
23   * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
24   * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27   * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29   * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30   *
31   * $JOMC: RuntimeTexts.java 5061 2015-05-31 13:20:40Z schulte $
32   *
33   */
34  // </editor-fold>
35  // SECTION-END
36  package org.jomc.ri.model;
37  
38  import java.util.Locale;
39  import java.util.Map;
40  import javax.xml.bind.annotation.XmlTransient;
41  import org.jomc.model.Text;
42  import org.jomc.model.Texts;
43  import static org.jomc.ri.model.RuntimeModelObjects.createMap;
44  
45  // SECTION-START[Documentation]
46  // <editor-fold defaultstate="collapsed" desc=" Generated Documentation ">
47  /**
48   * Runtime {@code Texts}.
49   *
50   * <dl>
51   *   <dt><b>Identifier:</b></dt><dd>org.jomc.ri.model.RuntimeTexts</dd>
52   *   <dt><b>Name:</b></dt><dd>JOMC ⁑ RI ⁑ RuntimeTexts</dd>
53   *   <dt><b>Specifications:</b></dt>
54   *     <dd>org.jomc.ri.model.RuntimeModelObject @ 1.2</dd>
55   *   <dt><b>Abstract:</b></dt><dd>No</dd>
56   *   <dt><b>Final:</b></dt><dd>No</dd>
57   *   <dt><b>Stateless:</b></dt><dd>No</dd>
58   * </dl>
59   *
60   * @author <a href="mailto:cs@schulte.it">Christian Schulte</a> 1.2
61   * @version 1.2
62   */
63  // </editor-fold>
64  // SECTION-END
65  // SECTION-START[Annotations]
66  // <editor-fold defaultstate="collapsed" desc=" Generated Annotations ">
67  @javax.annotation.Generated( value = "org.jomc.tools.SourceFileProcessor 1.9", comments = "See http://www.jomc.org/jomc/1.9/jomc-tools-1.9" )
68  // </editor-fold>
69  // SECTION-END
70  public class RuntimeTexts extends Texts implements RuntimeModelObject
71  {
72      // SECTION-START[RuntimeTexts]
73  
74      /**
75       * Cache map.
76       */
77      @XmlTransient
78      private transient final Map<String, Text> textsByLanguageCache = createMap();
79  
80      /**
81       * Cache map.
82       */
83      @XmlTransient
84      private transient final Map<Locale, Text> textsByLocaleCache = createMap();
85  
86      /**
87       * Creates a new {@code RuntimeTexts} instance by deeply copying a given {@code Texts} instance.
88       *
89       * @param texts The instance to copy.
90       *
91       * @throws NullPointerException if {@code texts} is {@code null}.
92       */
93      public RuntimeTexts( final Texts texts )
94      {
95          super( texts );
96          this.copyTexts();
97      }
98  
99      /**
100      * Gets a text for a given language from the list of texts.
101      * <p>
102      * This method queries an internal cache for a result object to return for the given argument values. If no
103      * cached result object is available, this method queries the super-class for a result object to return and caches
104      * the outcome of that query for use on successive calls.
105      * </p>
106      * <p>
107      * <b>Note:</b><br/>Method {@code clear()} must be used to synchronize the state of the internal cache with the
108      * state of the instance, should the state of the instance change.
109      * </p>
110      *
111      * @param language The language of the text to return.
112      *
113      * @return The first matching text or the default text, if no such text is found.
114      *
115      * @throws NullPointerException if {@code language} is {@code null}.
116      *
117      * @see #getText()
118      * @see #getDefaultLanguage()
119      * @see Text#getLanguage()
120      * @see #clear()
121      */
122     @Override
123     public Text getText( final String language )
124     {
125         if ( language == null )
126         {
127             throw new NullPointerException( "language" );
128         }
129 
130         synchronized ( this.textsByLanguageCache )
131         {
132             Text t = this.textsByLanguageCache.get( language );
133 
134             if ( t == null && !this.textsByLanguageCache.containsKey( language ) )
135             {
136                 t = super.getText( language );
137                 this.textsByLanguageCache.put( language, t );
138             }
139 
140             return t;
141         }
142     }
143 
144     /**
145      * Gets a text for a given language from the list of texts.
146      * <p>
147      * This method queries an internal cache for a result object to return for the given argument values. If no
148      * cached result object is available, this method queries the super-class for a result object to return and caches
149      * the outcome of that query for use on successive calls.
150      * </p>
151      * <p>
152      * <b>Note:</b><br/>Method {@code clear()} must be used to synchronize the state of the internal cache with the
153      * state of the instance, should the state of the instance change.
154      * </p>
155      *
156      * @param locale The locale of the text to return.
157      *
158      * @return The first matching text or the default text, if no such text is found.
159      *
160      * @throws NullPointerException if {@code locale} is {@code null}.
161      *
162      * @see #getText()
163      * @see #getDefaultLanguage()
164      * @see Text#getLanguage()
165      * @see #clear()
166      *
167      * @since 1.4
168      */
169     @Override
170     public Text getText( final Locale locale )
171     {
172         if ( locale == null )
173         {
174             throw new NullPointerException( "locale" );
175         }
176 
177         synchronized ( this.textsByLocaleCache )
178         {
179             Text t = this.textsByLocaleCache.get( locale );
180 
181             if ( t == null && !this.textsByLocaleCache.containsKey( locale ) )
182             {
183                 t = super.getText( locale );
184                 this.textsByLocaleCache.put( locale, t );
185             }
186 
187             return t;
188         }
189     }
190 
191     private void copyTexts()
192     {
193         for ( int i = 0, s0 = this.getText().size(); i < s0; i++ )
194         {
195             final Text t = this.getText().get( i );
196             this.getText().set( i, RuntimeModelObjects.getInstance().copyOf( t ) );
197         }
198     }
199 
200     // SECTION-END
201     // SECTION-START[RuntimeModelObject]
202     public void gc()
203     {
204         this.gcOrClear( true, false );
205     }
206 
207     public void clear()
208     {
209         synchronized ( this.textsByLanguageCache )
210         {
211             this.textsByLanguageCache.clear();
212         }
213         synchronized ( this.textsByLocaleCache )
214         {
215             this.textsByLocaleCache.clear();
216         }
217 
218         this.gcOrClear( false, true );
219     }
220 
221     private void gcOrClear( final boolean gc, final boolean clear )
222     {
223         this.gcOrClearTexts( gc, clear );
224     }
225 
226     private void gcOrClearTexts( final boolean gc, final boolean clear )
227     {
228         for ( int i = 0, s0 = this.getText().size(); i < s0; i++ )
229         {
230             final Text t = this.getText().get( i );
231             if ( t instanceof RuntimeModelObject )
232             {
233                 if ( gc )
234                 {
235                     ( (RuntimeModelObject) t ).gc();
236                 }
237                 if ( clear )
238                 {
239                     ( (RuntimeModelObject) t ).clear();
240                 }
241             }
242         }
243     }
244 
245     // SECTION-END
246     // SECTION-START[Constructors]
247     // <editor-fold defaultstate="collapsed" desc=" Generated Constructors ">
248     /** Creates a new {@code RuntimeTexts} instance. */
249     @javax.annotation.Generated( value = "org.jomc.tools.SourceFileProcessor 1.9", comments = "See http://www.jomc.org/jomc/1.9/jomc-tools-1.9" )
250     public RuntimeTexts()
251     {
252         // SECTION-START[Default Constructor]
253         super();
254         // SECTION-END
255     }
256     // </editor-fold>
257     // SECTION-END
258     // SECTION-START[Dependencies]
259     // SECTION-END
260     // SECTION-START[Properties]
261     // SECTION-END
262     // SECTION-START[Messages]
263     // SECTION-END
264 
265 }