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, 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: RuntimeMessage.java 5010 2014-11-17 04:00:16Z schulte $
32   *
33   */
34  // </editor-fold>
35  // SECTION-END
36  package org.jomc.ri.model;
37  
38  import java.text.MessageFormat;
39  import java.util.Locale;
40  import java.util.Map;
41  import javax.xml.bind.annotation.XmlTransient;
42  import org.jomc.model.Message;
43  import org.jomc.model.ModelObjectException;
44  import static org.jomc.ri.model.RuntimeModelObjects.createMap;
45  
46  // SECTION-START[Documentation]
47  // <editor-fold defaultstate="collapsed" desc=" Generated Documentation ">
48  /**
49   * Runtime {@code Message}.
50   *
51   * <dl>
52   *   <dt><b>Identifier:</b></dt><dd>org.jomc.ri.model.RuntimeMessage</dd>
53   *   <dt><b>Name:</b></dt><dd>JOMC ⁑ RI ⁑ RuntimeMessage</dd>
54   *   <dt><b>Specifications:</b></dt>
55   *     <dd>org.jomc.ri.model.RuntimeModelObject @ 1.2</dd>
56   *   <dt><b>Abstract:</b></dt><dd>No</dd>
57   *   <dt><b>Final:</b></dt><dd>No</dd>
58   *   <dt><b>Stateless:</b></dt><dd>No</dd>
59   * </dl>
60   *
61   * @author <a href="mailto:cs@schulte.it">Christian Schulte</a> 1.2
62   * @version 1.2
63   */
64  // </editor-fold>
65  // SECTION-END
66  // SECTION-START[Annotations]
67  // <editor-fold defaultstate="collapsed" desc=" Generated Annotations ">
68  @javax.annotation.Generated( value = "org.jomc.tools.SourceFileProcessor 1.8", comments = "See http://www.jomc.org/jomc/1.8/jomc-tools-1.8" )
69  // </editor-fold>
70  // SECTION-END
71  public class RuntimeMessage extends Message implements RuntimeModelObject
72  {
73      // SECTION-START[RuntimeMessage]
74  
75      /** Java messages by locale cache.*/
76      @XmlTransient
77      private final Map<Locale, MessageFormat> javaMessagesByLocaleCache = createMap();
78  
79      /**
80       * Creates a new {@code RuntimeMessage} instance by deeply copying a given {@code Message} instance.
81       *
82       * @param message The instance to copy.
83       *
84       * @throws NullPointerException if {@code message} is {@code null}.
85       */
86      public RuntimeMessage( final Message message )
87      {
88          super( message );
89  
90          if ( this.getArguments() != null )
91          {
92              this.setArguments( RuntimeModelObjects.getInstance().copyOf( this.getArguments() ) );
93          }
94          if ( this.getAuthors() != null )
95          {
96              this.setAuthors( RuntimeModelObjects.getInstance().copyOf( this.getAuthors() ) );
97          }
98          if ( this.getDocumentation() != null )
99          {
100             this.setDocumentation( RuntimeModelObjects.getInstance().copyOf( this.getDocumentation() ) );
101         }
102         if ( this.getTemplate() != null )
103         {
104             this.setTemplate( RuntimeModelObjects.getInstance().copyOf( this.getTemplate() ) );
105         }
106     }
107 
108     /**
109      * Gets a Java {@code MessageFormat} instance for a given locale.
110      * <p>This method queries an internal cache for a result object to return for the given argument values. If no
111      * cached result object is available, this method queries the super-class for a result object to return and caches
112      * the outcome of that query for use on successive calls.</p>
113      * <p><b>Note:</b><br/>Method {@code clear()} must be used to synchronize the state of the internal cache with the
114      * state of the instance, should the state of the instance change.</p>
115      *
116      * @param locale The locale to get a Java {@code MessageFormat} instance for.
117      *
118      * @return A Java {@code MessageFormat} instance for {@code locale}.
119      *
120      * @throws NullPointerException if {@code locale} is {@code null}.
121      * @throws ModelObjectException if compiling the template of the message for {@code locale} to a
122      * {@code MessageFormat} fails.
123      *
124      * @see #getTemplate()
125      * @see #clear()
126      */
127     @Override
128     public MessageFormat getJavaMessage( final Locale locale ) throws ModelObjectException
129     {
130         if ( locale == null )
131         {
132             throw new NullPointerException( "locale" );
133         }
134 
135         synchronized ( this.javaMessagesByLocaleCache )
136         {
137             MessageFormat javaMessage = this.javaMessagesByLocaleCache.get( locale );
138 
139             if ( javaMessage == null && !this.javaMessagesByLocaleCache.containsKey( locale ) )
140             {
141                 javaMessage = super.getJavaMessage( locale );
142                 this.javaMessagesByLocaleCache.put( locale, javaMessage );
143             }
144 
145             return javaMessage;
146         }
147     }
148 
149     // SECTION-END
150     // SECTION-START[RuntimeModelObject]
151     public void gc()
152     {
153         this.gcOrClear( true, false );
154     }
155 
156     public void clear()
157     {
158         synchronized ( this.javaMessagesByLocaleCache )
159         {
160             this.javaMessagesByLocaleCache.clear();
161         }
162 
163         this.gcOrClear( false, true );
164     }
165 
166     private void gcOrClear( final boolean gc, final boolean clear )
167     {
168         if ( this.getArguments() instanceof RuntimeModelObject )
169         {
170             if ( gc )
171             {
172                 ( (RuntimeModelObject) this.getArguments() ).gc();
173             }
174             if ( clear )
175             {
176                 ( (RuntimeModelObject) this.getArguments() ).clear();
177             }
178         }
179         if ( this.getAuthors() instanceof RuntimeModelObject )
180         {
181             if ( gc )
182             {
183                 ( (RuntimeModelObject) this.getAuthors() ).gc();
184             }
185             if ( clear )
186             {
187                 ( (RuntimeModelObject) this.getAuthors() ).clear();
188             }
189         }
190         if ( this.getDocumentation() instanceof RuntimeModelObject )
191         {
192             if ( gc )
193             {
194                 ( (RuntimeModelObject) this.getDocumentation() ).gc();
195             }
196             if ( clear )
197             {
198                 ( (RuntimeModelObject) this.getDocumentation() ).clear();
199             }
200         }
201         if ( this.getTemplate() instanceof RuntimeModelObject )
202         {
203             if ( gc )
204             {
205                 ( (RuntimeModelObject) this.getTemplate() ).gc();
206             }
207             if ( clear )
208             {
209                 ( (RuntimeModelObject) this.getTemplate() ).clear();
210             }
211         }
212     }
213 
214     // SECTION-END
215     // SECTION-START[Constructors]
216     // <editor-fold defaultstate="collapsed" desc=" Generated Constructors ">
217     /** Creates a new {@code RuntimeMessage} instance. */
218     @javax.annotation.Generated( value = "org.jomc.tools.SourceFileProcessor 1.8", comments = "See http://www.jomc.org/jomc/1.8/jomc-tools-1.8" )
219     public RuntimeMessage()
220     {
221         // SECTION-START[Default Constructor]
222         super();
223         // SECTION-END
224     }
225     // </editor-fold>
226     // SECTION-END
227     // SECTION-START[Dependencies]
228     // SECTION-END
229     // SECTION-START[Properties]
230     // SECTION-END
231     // SECTION-START[Messages]
232     // SECTION-END
233 }