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: RuntimeImplementations.java 4588 2012-06-03 06:01:30Z schulte2005 $
032 *
033 */
034// </editor-fold>
035// SECTION-END
036package org.jomc.ri.model;
037
038import java.util.Map;
039import javax.xml.bind.annotation.XmlTransient;
040import org.jomc.model.Implementation;
041import org.jomc.model.ImplementationReference;
042import org.jomc.model.Implementations;
043import static org.jomc.ri.model.RuntimeModelObjects.createMap;
044
045// SECTION-START[Documentation]
046// <editor-fold defaultstate="collapsed" desc=" Generated Documentation ">
047/**
048 * Runtime {@code Implementations}.
049 *
050 * <dl>
051 *   <dt><b>Identifier:</b></dt><dd>org.jomc.ri.model.RuntimeImplementations</dd>
052 *   <dt><b>Name:</b></dt><dd>JOMC RI RuntimeImplementations</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.3", comments = "See http://jomc.sourceforge.net/jomc/1.3/jomc-tools-1.3" )
068// </editor-fold>
069// SECTION-END
070public class RuntimeImplementations extends Implementations implements RuntimeModelObject
071{
072    // SECTION-START[RuntimeImplementations]
073
074    /** Cache map. */
075    @XmlTransient
076    private transient final Map<String, Implementation> implementationsByIdentifierCache = createMap();
077
078    /** Cache map. */
079    @XmlTransient
080    private transient final Map<String, Implementation> implementationsByClassCache = createMap();
081
082    /** Cache map. */
083    @XmlTransient
084    private transient final Map<String, Implementation> implementationsByNameCache = createMap();
085
086    /** Cache map. */
087    @XmlTransient
088    private transient final Map<String, ImplementationReference> referencesByIdentifierCache = createMap();
089
090    /**
091     * Creates a new {@code RuntimeImplementations} instance by deeply copying a given {@code Implementations} instance.
092     *
093     * @param implementations The instance to copy.
094     *
095     * @throws NullPointerException if {@code implementations} is {@code null}.
096     */
097    public RuntimeImplementations( final Implementations implementations )
098    {
099        super( implementations );
100
101        if ( this.getAuthors() != null )
102        {
103            this.setAuthors( RuntimeModelObjects.getInstance().copyOf( this.getAuthors() ) );
104        }
105        if ( this.getDocumentation() != null )
106        {
107            this.setDocumentation( RuntimeModelObjects.getInstance().copyOf( this.getDocumentation() ) );
108        }
109
110        this.copyImplementations();
111        this.copyImplementationReferences();
112    }
113
114    /**
115     * Gets an implementation for a given identifier from the list of implementations.
116     * <p>This method queries an internal cache for a result object to return for the given argument values. If no
117     * cached result object is available, this method queries the super-class for a result object to return and caches
118     * the outcome of that query for use on successive calls.</p>
119     * <p><b>Note:</b><br/>Method {@code clear()} must be used to synchronize the state of the internal cache with the
120     * state of the instance, should the state of the instance change.</p>
121     *
122     * @param implementation The identifier of the implementation to return.
123     *
124     * @return The first matching implementation or {@code null}, if no such implementation is found.
125     *
126     * @throws NullPointerException if {@code implementation} is {@code null}.
127     *
128     * @see #getImplementation()
129     * @see Implementation#getIdentifier()
130     * @see #clear()
131     */
132    @Override
133    public Implementation getImplementation( final String implementation )
134    {
135        if ( implementation == null )
136        {
137            throw new NullPointerException( "implementation" );
138        }
139
140        synchronized ( this.implementationsByIdentifierCache )
141        {
142            Implementation i = this.implementationsByIdentifierCache.get( implementation );
143
144            if ( i == null && !this.implementationsByIdentifierCache.containsKey( implementation ) )
145            {
146                i = super.getImplementation( implementation );
147                this.implementationsByIdentifierCache.put( implementation, i );
148            }
149
150            return i;
151        }
152    }
153
154    /**
155     * Gets an implementation for a given class from the list of implementations.
156     * <p>This method queries an internal cache for a result object to return for the given argument values. If no
157     * cached result object is available, this method queries the super-class for a result object to return and caches
158     * the outcome of that query for use on successive calls.</p>
159     * <p><b>Note:</b><br/>Method {@code clear()} must be used to synchronize the state of the internal cache with the
160     * state of the instance, should the state of the instance change.</p>
161     *
162     * @param implementation The class of the implementation to return.
163     *
164     * @return The first matching implementation or {@code null}, if no such implementation is found.
165     *
166     * @throws NullPointerException if {@code implementation} is {@code null}.
167     *
168     * @see #getImplementation()
169     * @see Implementation#isClassDeclaration()
170     * @see Implementation#getClazz()
171     * @see #clear()
172     */
173    @Override
174    public Implementation getImplementation( final Class<?> implementation )
175    {
176        if ( implementation == null )
177        {
178            throw new NullPointerException( "implementation" );
179        }
180
181        synchronized ( this.implementationsByClassCache )
182        {
183            Implementation i = this.implementationsByClassCache.get( implementation.getName() );
184
185            if ( i == null && !this.implementationsByClassCache.containsKey( implementation.getName() ) )
186            {
187                i = super.getImplementation( implementation );
188                this.implementationsByClassCache.put( implementation.getName(), i );
189            }
190
191            return i;
192        }
193    }
194
195    /**
196     * Gets an implementation for a given name from the list of implementations.
197     * <p>This method queries an internal cache for a result object to return for the given argument values. If no
198     * cached result object is available, this method queries the super-class for a result object to return and caches
199     * the outcome of that query for use on successive calls.</p>
200     * <p><b>Note:</b><br/>Method {@code clear()} must be used to synchronize the state of the internal cache with the
201     * state of the instance, should the state of the instance change.</p>
202     *
203     * @param name The name of the implementation to return.
204     *
205     * @return The first matching implementation or {@code null}, if no such implementation is found.
206     *
207     * @throws NullPointerException if {@code name} is {@code null}.
208     *
209     * @see #getImplementation()
210     * @see Implementation#getName()
211     * @see #clear()
212     */
213    @Override
214    public Implementation getImplementationByName( final String name )
215    {
216        if ( name == null )
217        {
218            throw new NullPointerException( "name" );
219        }
220
221        synchronized ( this.implementationsByNameCache )
222        {
223            Implementation i = this.implementationsByNameCache.get( name );
224
225            if ( i == null && !this.implementationsByNameCache.containsKey( name ) )
226            {
227                i = super.getImplementationByName( name );
228                this.implementationsByNameCache.put( name, i );
229            }
230
231            return i;
232        }
233    }
234
235    /**
236     * Gets an implementation reference for a given identifier from the list of references.
237     * <p>This method queries an internal cache for a result object to return for the given argument values. If no
238     * cached result object is available, this method queries the super-class for a result object to return and caches
239     * the outcome of that query for use on successive calls.</p>
240     * <p><b>Note:</b><br/>Method {@code clear()} must be used to synchronize the state of the internal cache with the
241     * state of the instance, should the state of the instance change.</p>
242     *
243     * @param implementation The identifier of the reference to return.
244     *
245     * @return The first matching implementation reference or {@code null}, if no such reference is found.
246     *
247     * @throws NullPointerException if {@code implementation} is {@code null}.
248     *
249     * @see #getReference()
250     * @see ImplementationReference#getIdentifier()
251     * @see #clear()
252     */
253    @Override
254    public ImplementationReference getReference( final String implementation )
255    {
256        if ( implementation == null )
257        {
258            throw new NullPointerException( "implementation" );
259        }
260
261        synchronized ( this.referencesByIdentifierCache )
262        {
263            ImplementationReference r = this.referencesByIdentifierCache.get( implementation );
264
265            if ( r == null && !this.referencesByIdentifierCache.containsKey( implementation ) )
266            {
267                r = super.getReference( implementation );
268                this.referencesByIdentifierCache.put( implementation, r );
269            }
270
271            return r;
272        }
273    }
274
275    private void copyImplementations()
276    {
277        for ( int i = 0, s0 = this.getImplementation().size(); i < s0; i++ )
278        {
279            final Implementation impl = this.getImplementation().get( i );
280            this.getImplementation().set( i, RuntimeModelObjects.getInstance().copyOf( impl ) );
281        }
282    }
283
284    private void copyImplementationReferences()
285    {
286        for ( int i = 0, s0 = this.getReference().size(); i < s0; i++ )
287        {
288            final ImplementationReference r = this.getReference().get( i );
289            this.getReference().set( i, RuntimeModelObjects.getInstance().copyOf( r ) );
290        }
291    }
292
293    // SECTION-END
294    // SECTION-START[RuntimeModelObject]
295    public void gc()
296    {
297        this.gcOrClear( true, false );
298    }
299
300    public void clear()
301    {
302        synchronized ( this.implementationsByClassCache )
303        {
304            this.implementationsByClassCache.clear();
305        }
306        synchronized ( this.implementationsByIdentifierCache )
307        {
308            this.implementationsByIdentifierCache.clear();
309        }
310        synchronized ( this.implementationsByNameCache )
311        {
312            this.implementationsByNameCache.clear();
313        }
314        synchronized ( this.referencesByIdentifierCache )
315        {
316            this.referencesByIdentifierCache.clear();
317        }
318
319        this.gcOrClear( false, true );
320    }
321
322    private void gcOrClear( final boolean gc, final boolean clear )
323    {
324        if ( this.getAuthors() instanceof RuntimeModelObject )
325        {
326            if ( gc )
327            {
328                ( (RuntimeModelObject) this.getAuthors() ).gc();
329            }
330            if ( clear )
331            {
332                ( (RuntimeModelObject) this.getAuthors() ).clear();
333            }
334        }
335        if ( this.getDocumentation() instanceof RuntimeModelObject )
336        {
337            if ( gc )
338            {
339                ( (RuntimeModelObject) this.getDocumentation() ).gc();
340            }
341            if ( clear )
342            {
343                ( (RuntimeModelObject) this.getDocumentation() ).clear();
344            }
345        }
346
347        this.gcOrClearImplementationReferences( gc, clear );
348        this.gcOrClearImplementations( gc, clear );
349    }
350
351    private void gcOrClearImplementations( final boolean gc, final boolean clear )
352    {
353        for ( int i = 0, s0 = this.getImplementation().size(); i < s0; i++ )
354        {
355            final Implementation impl = this.getImplementation().get( i );
356            if ( impl instanceof RuntimeModelObject )
357            {
358                if ( gc )
359                {
360                    ( (RuntimeModelObject) impl ).gc();
361                }
362                if ( clear )
363                {
364                    ( (RuntimeModelObject) impl ).clear();
365                }
366            }
367        }
368    }
369
370    private void gcOrClearImplementationReferences( final boolean gc, final boolean clear )
371    {
372        for ( int i = 0, s0 = this.getReference().size(); i < s0; i++ )
373        {
374            final ImplementationReference r = this.getReference().get( i );
375            if ( r instanceof RuntimeModelObject )
376            {
377                if ( gc )
378                {
379                    ( (RuntimeModelObject) r ).gc();
380                }
381                if ( clear )
382                {
383                    ( (RuntimeModelObject) r ).clear();
384                }
385            }
386        }
387    }
388
389    // SECTION-END
390    // SECTION-START[Constructors]
391    // <editor-fold defaultstate="collapsed" desc=" Generated Constructors ">
392    /** Creates a new {@code RuntimeImplementations} instance. */
393    @javax.annotation.Generated( value = "org.jomc.tools.SourceFileProcessor 1.3", comments = "See http://jomc.sourceforge.net/jomc/1.3/jomc-tools-1.3" )
394    public RuntimeImplementations()
395    {
396        // SECTION-START[Default Constructor]
397        super();
398        // SECTION-END
399    }
400    // </editor-fold>
401    // SECTION-END
402    // SECTION-START[Dependencies]
403    // SECTION-END
404    // SECTION-START[Properties]
405    // SECTION-END
406    // SECTION-START[Messages]
407    // SECTION-END
408}