001    // SECTION-START[License Header]
002    // <editor-fold defaultstate="collapsed" desc=" Generated License ">
003    /*
004     *   Java Object Management and Configuration
005     *   Copyright (C) Christian Schulte, 2011-313
006     *   All rights reserved.
007     *
008     *   Redistribution and use in source and binary forms, with or without
009     *   modification, are permitted provided that the following conditions
010     *   are met:
011     *
012     *     o Redistributions of source code must retain the above copyright
013     *       notice, this list of conditions and the following disclaimer.
014     *
015     *     o Redistributions in binary form must reproduce the above copyright
016     *       notice, this list of conditions and the following disclaimer in
017     *       the documentation and/or other materials provided with the
018     *       distribution.
019     *
020     *   THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
021     *   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
022     *   AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
023     *   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
024     *   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
025     *   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
026     *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
027     *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
028     *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
029     *   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
030     *
031     *   $JOMC: RuntimeMessage.java 4381 2012-03-04 19:29:29Z schulte2005 $
032     *
033     */
034    // </editor-fold>
035    // SECTION-END
036    package org.jomc.ri.model;
037    
038    import java.text.MessageFormat;
039    import java.util.Locale;
040    import java.util.Map;
041    import javax.xml.bind.annotation.XmlTransient;
042    import org.jomc.model.Message;
043    import static org.jomc.ri.model.RuntimeModelObjects.createMap;
044    
045    // SECTION-START[Documentation]
046    // <editor-fold defaultstate="collapsed" desc=" Generated Documentation ">
047    /**
048     * Runtime {@code Message}.
049     *
050     * <dl>
051     *   <dt><b>Identifier:</b></dt><dd>org.jomc.ri.model.RuntimeMessage</dd>
052     *   <dt><b>Name:</b></dt><dd>JOMC RI RuntimeMessage</dd>
053     *   <dt><b>Specifications:</b></dt>
054     *     <dd>org.jomc.ri.model.RuntimeModelObject @ 1.2</dd>
055     *   <dt><b>Abstract:</b></dt><dd>No</dd>
056     *   <dt><b>Final:</b></dt><dd>No</dd>
057     *   <dt><b>Stateless:</b></dt><dd>No</dd>
058     * </dl>
059     *
060     * @author <a href="mailto:schulte2005@users.sourceforge.net">Christian Schulte</a> 1.2
061     * @version 1.2
062     */
063    // </editor-fold>
064    // SECTION-END
065    // SECTION-START[Annotations]
066    // <editor-fold defaultstate="collapsed" desc=" Generated Annotations ">
067    @javax.annotation.Generated( value = "org.jomc.tools.SourceFileProcessor 1.2.2", comments = "See http://jomc.sourceforge.net/jomc/1.2/jomc-tools-1.2.2" )
068    // </editor-fold>
069    // SECTION-END
070    public class RuntimeMessage extends Message implements RuntimeModelObject
071    {
072        // SECTION-START[RuntimeMessage]
073    
074        /** Java messages by locale cache.*/
075        @XmlTransient
076        private final Map<Locale, MessageFormat> javaMessagesByLocaleCache = createMap();
077    
078        /**
079         * Creates a new {@code RuntimeMessage} instance by deeply copying a given {@code Message} instance.
080         *
081         * @param message The instance to copy.
082         *
083         * @throws NullPointerException if {@code message} is {@code null}.
084         */
085        public RuntimeMessage( final Message message )
086        {
087            super( message );
088    
089            if ( this.getArguments() != null )
090            {
091                this.setArguments( RuntimeModelObjects.getInstance().copyOf( this.getArguments() ) );
092            }
093            if ( this.getAuthors() != null )
094            {
095                this.setAuthors( RuntimeModelObjects.getInstance().copyOf( this.getAuthors() ) );
096            }
097            if ( this.getDocumentation() != null )
098            {
099                this.setDocumentation( RuntimeModelObjects.getInstance().copyOf( this.getDocumentation() ) );
100            }
101            if ( this.getTemplate() != null )
102            {
103                this.setTemplate( RuntimeModelObjects.getInstance().copyOf( this.getTemplate() ) );
104            }
105        }
106    
107        /**
108         * Gets a Java {@code MessageFormat} instance for a given locale.
109         * <p>This method queries an internal cache for a result object to return for the given argument values. If no
110         * cached result object is available, this method queries the super-class for a result object to return and caches
111         * the outcome of that query for use on successive calls.</p>
112         * <p><b>Note:</b><br/>Method {@code clear()} must be used to synchronize the state of the internal cache with the
113         * state of the instance, should the state of the instance change.</p>
114         *
115         * @param locale The locale to get a Java {@code MessageFormat} instance for.
116         *
117         * @return A Java {@code MessageFormat} instance for {@code locale}.
118         *
119         * @throws NullPointerException if {@code locale} is {@code null}.
120         *
121         * @see #getTemplate()
122         * @see #clear()
123         */
124        @Override
125        public MessageFormat getJavaMessage( final Locale locale )
126        {
127            if ( locale == null )
128            {
129                throw new NullPointerException( "locale" );
130            }
131    
132            synchronized ( this.javaMessagesByLocaleCache )
133            {
134                MessageFormat javaMessage = this.javaMessagesByLocaleCache.get( locale );
135    
136                if ( javaMessage == null && !this.javaMessagesByLocaleCache.containsKey( locale ) )
137                {
138                    javaMessage = super.getJavaMessage( locale );
139                    this.javaMessagesByLocaleCache.put( locale, javaMessage );
140                }
141    
142                return javaMessage;
143            }
144        }
145    
146        // SECTION-END
147        // SECTION-START[RuntimeModelObject]
148        public void gc()
149        {
150            this.gcOrClear( true, false );
151        }
152    
153        public void clear()
154        {
155            synchronized ( this.javaMessagesByLocaleCache )
156            {
157                this.javaMessagesByLocaleCache.clear();
158            }
159    
160            this.gcOrClear( false, true );
161        }
162    
163        private void gcOrClear( final boolean gc, final boolean clear )
164        {
165            if ( this.getArguments() instanceof RuntimeModelObject )
166            {
167                if ( gc )
168                {
169                    ( (RuntimeModelObject) this.getArguments() ).gc();
170                }
171                if ( clear )
172                {
173                    ( (RuntimeModelObject) this.getArguments() ).clear();
174                }
175            }
176            if ( this.getAuthors() instanceof RuntimeModelObject )
177            {
178                if ( gc )
179                {
180                    ( (RuntimeModelObject) this.getAuthors() ).gc();
181                }
182                if ( clear )
183                {
184                    ( (RuntimeModelObject) this.getAuthors() ).clear();
185                }
186            }
187            if ( this.getDocumentation() instanceof RuntimeModelObject )
188            {
189                if ( gc )
190                {
191                    ( (RuntimeModelObject) this.getDocumentation() ).gc();
192                }
193                if ( clear )
194                {
195                    ( (RuntimeModelObject) this.getDocumentation() ).clear();
196                }
197            }
198            if ( this.getTemplate() instanceof RuntimeModelObject )
199            {
200                if ( gc )
201                {
202                    ( (RuntimeModelObject) this.getTemplate() ).gc();
203                }
204                if ( clear )
205                {
206                    ( (RuntimeModelObject) this.getTemplate() ).clear();
207                }
208            }
209        }
210    
211        // SECTION-END
212        // SECTION-START[Constructors]
213        // <editor-fold defaultstate="collapsed" desc=" Generated Constructors ">
214        /** Creates a new {@code RuntimeMessage} instance. */
215        @javax.annotation.Generated( value = "org.jomc.tools.SourceFileProcessor 1.2.2", comments = "See http://jomc.sourceforge.net/jomc/1.2/jomc-tools-1.2.2" )
216        public RuntimeMessage()
217        {
218            // SECTION-START[Default Constructor]
219            super();
220            // SECTION-END
221        }
222        // </editor-fold>
223        // SECTION-END
224        // SECTION-START[Dependencies]
225        // SECTION-END
226        // SECTION-START[Properties]
227        // SECTION-END
228        // SECTION-START[Messages]
229        // SECTION-END
230    }