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, 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 4795 2013-04-21 09:09:02Z 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.5", comments = "See http://www.jomc.org/jomc/1.5/jomc-tools-1.5" )
68 // </editor-fold>
69 // SECTION-END
70 public class RuntimeTexts extends Texts implements RuntimeModelObject
71 {
72 // SECTION-START[RuntimeTexts]
73
74 /** Cache map. */
75 @XmlTransient
76 private transient final Map<String, Text> textsByLanguageCache = createMap();
77
78 /** Cache map. */
79 @XmlTransient
80 private transient final Map<Locale, Text> textsByLocaleCache = createMap();
81
82 /**
83 * Creates a new {@code RuntimeTexts} instance by deeply copying a given {@code Texts} instance.
84 *
85 * @param texts The instance to copy.
86 *
87 * @throws NullPointerException if {@code texts} is {@code null}.
88 */
89 public RuntimeTexts( final Texts texts )
90 {
91 super( texts );
92 this.copyTexts();
93 }
94
95 /**
96 * Gets a text for a given language from the list of texts.
97 * <p>This method queries an internal cache for a result object to return for the given argument values. If no
98 * cached result object is available, this method queries the super-class for a result object to return and caches
99 * the outcome of that query for use on successive calls.</p>
100 * <p><b>Note:</b><br/>Method {@code clear()} must be used to synchronize the state of the internal cache with the
101 * state of the instance, should the state of the instance change.</p>
102 *
103 * @param language The language of the text to return.
104 *
105 * @return The first matching text or the default text, if no such text is found.
106 *
107 * @throws NullPointerException if {@code language} is {@code null}.
108 *
109 * @see #getText()
110 * @see #getDefaultLanguage()
111 * @see Text#getLanguage()
112 * @see #clear()
113 */
114 @Override
115 public Text getText( final String language )
116 {
117 if ( language == null )
118 {
119 throw new NullPointerException( "language" );
120 }
121
122 synchronized ( this.textsByLanguageCache )
123 {
124 Text t = this.textsByLanguageCache.get( language );
125
126 if ( t == null && !this.textsByLanguageCache.containsKey( language ) )
127 {
128 t = super.getText( language );
129 this.textsByLanguageCache.put( language, t );
130 }
131
132 return t;
133 }
134 }
135
136 /**
137 * Gets a text for a given language from the list of texts.
138 * <p>This method queries an internal cache for a result object to return for the given argument values. If no
139 * cached result object is available, this method queries the super-class for a result object to return and caches
140 * the outcome of that query for use on successive calls.</p>
141 * <p><b>Note:</b><br/>Method {@code clear()} must be used to synchronize the state of the internal cache with the
142 * state of the instance, should the state of the instance change.</p>
143 *
144 * @param locale The locale of the text to return.
145 *
146 * @return The first matching text or the default text, if no such text is found.
147 *
148 * @throws NullPointerException if {@code locale} is {@code null}.
149 *
150 * @see #getText()
151 * @see #getDefaultLanguage()
152 * @see Text#getLanguage()
153 * @see #clear()
154 *
155 * @since 1.4
156 */
157 @Override
158 public Text getText( final Locale locale )
159 {
160 if ( locale == null )
161 {
162 throw new NullPointerException( "locale" );
163 }
164
165 synchronized ( this.textsByLocaleCache )
166 {
167 Text t = this.textsByLocaleCache.get( locale );
168
169 if ( t == null && !this.textsByLocaleCache.containsKey( locale ) )
170 {
171 t = super.getText( locale );
172 this.textsByLocaleCache.put( locale, t );
173 }
174
175 return t;
176 }
177 }
178
179 private void copyTexts()
180 {
181 for ( int i = 0, s0 = this.getText().size(); i < s0; i++ )
182 {
183 final Text t = this.getText().get( i );
184 this.getText().set( i, RuntimeModelObjects.getInstance().copyOf( t ) );
185 }
186 }
187
188 // SECTION-END
189 // SECTION-START[RuntimeModelObject]
190 public void gc()
191 {
192 this.gcOrClear( true, false );
193 }
194
195 public void clear()
196 {
197 synchronized ( this.textsByLanguageCache )
198 {
199 this.textsByLanguageCache.clear();
200 }
201 synchronized ( this.textsByLocaleCache )
202 {
203 this.textsByLocaleCache.clear();
204 }
205
206 this.gcOrClear( false, true );
207 }
208
209 private void gcOrClear( final boolean gc, final boolean clear )
210 {
211 this.gcOrClearTexts( gc, clear );
212 }
213
214 private void gcOrClearTexts( final boolean gc, final boolean clear )
215 {
216 for ( int i = 0, s0 = this.getText().size(); i < s0; i++ )
217 {
218 final Text t = this.getText().get( i );
219 if ( t instanceof RuntimeModelObject )
220 {
221 if ( gc )
222 {
223 ( (RuntimeModelObject) t ).gc();
224 }
225 if ( clear )
226 {
227 ( (RuntimeModelObject) t ).clear();
228 }
229 }
230 }
231 }
232 // SECTION-END
233 // SECTION-START[Constructors]
234 // <editor-fold defaultstate="collapsed" desc=" Generated Constructors ">
235 /** Creates a new {@code RuntimeTexts} instance. */
236 @javax.annotation.Generated( value = "org.jomc.tools.SourceFileProcessor 1.5", comments = "See http://www.jomc.org/jomc/1.5/jomc-tools-1.5" )
237 public RuntimeTexts()
238 {
239 // SECTION-START[Default Constructor]
240 super();
241 // SECTION-END
242 }
243 // </editor-fold>
244 // SECTION-END
245 // SECTION-START[Dependencies]
246 // SECTION-END
247 // SECTION-START[Properties]
248 // SECTION-END
249 // SECTION-START[Messages]
250 // SECTION-END
251 }