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: RuntimeImplementations.java 4712 2013-01-02 13:56:12Z schulte $
32   *
33   */
34  // </editor-fold>
35  // SECTION-END
36  package org.jomc.ri.model;
37  
38  import java.util.Map;
39  import javax.xml.bind.annotation.XmlTransient;
40  import org.jomc.model.Implementation;
41  import org.jomc.model.ImplementationReference;
42  import org.jomc.model.Implementations;
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 Implementations}.
50   *
51   * <dl>
52   *   <dt><b>Identifier:</b></dt><dd>org.jomc.ri.model.RuntimeImplementations</dd>
53   *   <dt><b>Name:</b></dt><dd>JOMC ⁑ RI ⁑ RuntimeImplementations</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.4", comments = "See http://www.jomc.org/jomc/1.4/jomc-tools-1.4" )
69  // </editor-fold>
70  // SECTION-END
71  public class RuntimeImplementations extends Implementations implements RuntimeModelObject
72  {
73      // SECTION-START[RuntimeImplementations]
74  
75      /** Cache map. */
76      @XmlTransient
77      private transient final Map<String, Implementation> implementationsByIdentifierCache = createMap();
78  
79      /** Cache map. */
80      @XmlTransient
81      private transient final Map<String, Implementation> implementationsByClassCache = createMap();
82  
83      /** Cache map. */
84      @XmlTransient
85      private transient final Map<String, Implementation> implementationsByNameCache = createMap();
86  
87      /** Cache map. */
88      @XmlTransient
89      private transient final Map<String, ImplementationReference> referencesByIdentifierCache = createMap();
90  
91      /**
92       * Creates a new {@code RuntimeImplementations} instance by deeply copying a given {@code Implementations} instance.
93       *
94       * @param implementations The instance to copy.
95       *
96       * @throws NullPointerException if {@code implementations} is {@code null}.
97       */
98      public RuntimeImplementations( final Implementations implementations )
99      {
100         super( implementations );
101 
102         if ( this.getAuthors() != null )
103         {
104             this.setAuthors( RuntimeModelObjects.getInstance().copyOf( this.getAuthors() ) );
105         }
106         if ( this.getDocumentation() != null )
107         {
108             this.setDocumentation( RuntimeModelObjects.getInstance().copyOf( this.getDocumentation() ) );
109         }
110 
111         this.copyImplementations();
112         this.copyImplementationReferences();
113     }
114 
115     /**
116      * Gets an implementation for a given identifier from the list of implementations.
117      * <p>This method queries an internal cache for a result object to return for the given argument values. If no
118      * cached result object is available, this method queries the super-class for a result object to return and caches
119      * the outcome of that query for use on successive calls.</p>
120      * <p><b>Note:</b><br/>Method {@code clear()} must be used to synchronize the state of the internal cache with the
121      * state of the instance, should the state of the instance change.</p>
122      *
123      * @param implementation The identifier of the implementation to return.
124      *
125      * @return The first matching implementation or {@code null}, if no such implementation is found.
126      *
127      * @throws NullPointerException if {@code implementation} is {@code null}.
128      *
129      * @see #getImplementation()
130      * @see Implementation#getIdentifier()
131      * @see #clear()
132      */
133     @Override
134     public Implementation getImplementation( final String implementation )
135     {
136         if ( implementation == null )
137         {
138             throw new NullPointerException( "implementation" );
139         }
140 
141         synchronized ( this.implementationsByIdentifierCache )
142         {
143             Implementation i = this.implementationsByIdentifierCache.get( implementation );
144 
145             if ( i == null && !this.implementationsByIdentifierCache.containsKey( implementation ) )
146             {
147                 i = super.getImplementation( implementation );
148                 this.implementationsByIdentifierCache.put( implementation, i );
149             }
150 
151             return i;
152         }
153     }
154 
155     /**
156      * Gets an implementation for a given class from the list of implementations.
157      * <p>This method queries an internal cache for a result object to return for the given argument values. If no
158      * cached result object is available, this method queries the super-class for a result object to return and caches
159      * the outcome of that query for use on successive calls.</p>
160      * <p><b>Note:</b><br/>Method {@code clear()} must be used to synchronize the state of the internal cache with the
161      * state of the instance, should the state of the instance change.</p>
162      *
163      * @param implementation The class of the implementation to return.
164      *
165      * @return The first matching implementation or {@code null}, if no such implementation is found.
166      *
167      * @throws NullPointerException if {@code implementation} is {@code null}.
168      * @throws ModelObjectException if parsing the name of a referenced type fails.
169      *
170      * @see #getImplementation()
171      * @see Implementation#isClassDeclaration()
172      * @see Implementation#getClazz()
173      * @see #clear()
174      */
175     @Override
176     public Implementation getImplementation( final Class<?> implementation ) throws ModelObjectException
177     {
178         if ( implementation == null )
179         {
180             throw new NullPointerException( "implementation" );
181         }
182 
183         synchronized ( this.implementationsByClassCache )
184         {
185             Implementation i = this.implementationsByClassCache.get( implementation.getName() );
186 
187             if ( i == null && !this.implementationsByClassCache.containsKey( implementation.getName() ) )
188             {
189                 i = super.getImplementation( implementation );
190                 this.implementationsByClassCache.put( implementation.getName(), i );
191             }
192 
193             return i;
194         }
195     }
196 
197     /**
198      * Gets an implementation for a given name from the list of implementations.
199      * <p>This method queries an internal cache for a result object to return for the given argument values. If no
200      * cached result object is available, this method queries the super-class for a result object to return and caches
201      * the outcome of that query for use on successive calls.</p>
202      * <p><b>Note:</b><br/>Method {@code clear()} must be used to synchronize the state of the internal cache with the
203      * state of the instance, should the state of the instance change.</p>
204      *
205      * @param name The name of the implementation to return.
206      *
207      * @return The first matching implementation or {@code null}, if no such implementation is found.
208      *
209      * @throws NullPointerException if {@code name} is {@code null}.
210      *
211      * @see #getImplementation()
212      * @see Implementation#getName()
213      * @see #clear()
214      */
215     @Override
216     public Implementation getImplementationByName( final String name )
217     {
218         if ( name == null )
219         {
220             throw new NullPointerException( "name" );
221         }
222 
223         synchronized ( this.implementationsByNameCache )
224         {
225             Implementation i = this.implementationsByNameCache.get( name );
226 
227             if ( i == null && !this.implementationsByNameCache.containsKey( name ) )
228             {
229                 i = super.getImplementationByName( name );
230                 this.implementationsByNameCache.put( name, i );
231             }
232 
233             return i;
234         }
235     }
236 
237     /**
238      * Gets an implementation reference for a given identifier from the list of references.
239      * <p>This method queries an internal cache for a result object to return for the given argument values. If no
240      * cached result object is available, this method queries the super-class for a result object to return and caches
241      * the outcome of that query for use on successive calls.</p>
242      * <p><b>Note:</b><br/>Method {@code clear()} must be used to synchronize the state of the internal cache with the
243      * state of the instance, should the state of the instance change.</p>
244      *
245      * @param implementation The identifier of the reference to return.
246      *
247      * @return The first matching implementation reference or {@code null}, if no such reference is found.
248      *
249      * @throws NullPointerException if {@code implementation} is {@code null}.
250      *
251      * @see #getReference()
252      * @see ImplementationReference#getIdentifier()
253      * @see #clear()
254      */
255     @Override
256     public ImplementationReference getReference( final String implementation )
257     {
258         if ( implementation == null )
259         {
260             throw new NullPointerException( "implementation" );
261         }
262 
263         synchronized ( this.referencesByIdentifierCache )
264         {
265             ImplementationReference r = this.referencesByIdentifierCache.get( implementation );
266 
267             if ( r == null && !this.referencesByIdentifierCache.containsKey( implementation ) )
268             {
269                 r = super.getReference( implementation );
270                 this.referencesByIdentifierCache.put( implementation, r );
271             }
272 
273             return r;
274         }
275     }
276 
277     private void copyImplementations()
278     {
279         for ( int i = 0, s0 = this.getImplementation().size(); i < s0; i++ )
280         {
281             final Implementation impl = this.getImplementation().get( i );
282             this.getImplementation().set( i, RuntimeModelObjects.getInstance().copyOf( impl ) );
283         }
284     }
285 
286     private void copyImplementationReferences()
287     {
288         for ( int i = 0, s0 = this.getReference().size(); i < s0; i++ )
289         {
290             final ImplementationReference r = this.getReference().get( i );
291             this.getReference().set( i, RuntimeModelObjects.getInstance().copyOf( r ) );
292         }
293     }
294 
295     // SECTION-END
296     // SECTION-START[RuntimeModelObject]
297     public void gc()
298     {
299         this.gcOrClear( true, false );
300     }
301 
302     public void clear()
303     {
304         synchronized ( this.implementationsByClassCache )
305         {
306             this.implementationsByClassCache.clear();
307         }
308         synchronized ( this.implementationsByIdentifierCache )
309         {
310             this.implementationsByIdentifierCache.clear();
311         }
312         synchronized ( this.implementationsByNameCache )
313         {
314             this.implementationsByNameCache.clear();
315         }
316         synchronized ( this.referencesByIdentifierCache )
317         {
318             this.referencesByIdentifierCache.clear();
319         }
320 
321         this.gcOrClear( false, true );
322     }
323 
324     private void gcOrClear( final boolean gc, final boolean clear )
325     {
326         if ( this.getAuthors() instanceof RuntimeModelObject )
327         {
328             if ( gc )
329             {
330                 ( (RuntimeModelObject) this.getAuthors() ).gc();
331             }
332             if ( clear )
333             {
334                 ( (RuntimeModelObject) this.getAuthors() ).clear();
335             }
336         }
337         if ( this.getDocumentation() instanceof RuntimeModelObject )
338         {
339             if ( gc )
340             {
341                 ( (RuntimeModelObject) this.getDocumentation() ).gc();
342             }
343             if ( clear )
344             {
345                 ( (RuntimeModelObject) this.getDocumentation() ).clear();
346             }
347         }
348 
349         this.gcOrClearImplementationReferences( gc, clear );
350         this.gcOrClearImplementations( gc, clear );
351     }
352 
353     private void gcOrClearImplementations( final boolean gc, final boolean clear )
354     {
355         for ( int i = 0, s0 = this.getImplementation().size(); i < s0; i++ )
356         {
357             final Implementation impl = this.getImplementation().get( i );
358             if ( impl instanceof RuntimeModelObject )
359             {
360                 if ( gc )
361                 {
362                     ( (RuntimeModelObject) impl ).gc();
363                 }
364                 if ( clear )
365                 {
366                     ( (RuntimeModelObject) impl ).clear();
367                 }
368             }
369         }
370     }
371 
372     private void gcOrClearImplementationReferences( final boolean gc, final boolean clear )
373     {
374         for ( int i = 0, s0 = this.getReference().size(); i < s0; i++ )
375         {
376             final ImplementationReference r = this.getReference().get( i );
377             if ( r instanceof RuntimeModelObject )
378             {
379                 if ( gc )
380                 {
381                     ( (RuntimeModelObject) r ).gc();
382                 }
383                 if ( clear )
384                 {
385                     ( (RuntimeModelObject) r ).clear();
386                 }
387             }
388         }
389     }
390 
391     // SECTION-END
392     // SECTION-START[Constructors]
393     // <editor-fold defaultstate="collapsed" desc=" Generated Constructors ">
394     /** Creates a new {@code RuntimeImplementations} instance. */
395     @javax.annotation.Generated( value = "org.jomc.tools.SourceFileProcessor 1.4", comments = "See http://www.jomc.org/jomc/1.4/jomc-tools-1.4" )
396     public RuntimeImplementations()
397     {
398         // SECTION-START[Default Constructor]
399         super();
400         // SECTION-END
401     }
402     // </editor-fold>
403     // SECTION-END
404     // SECTION-START[Dependencies]
405     // SECTION-END
406     // SECTION-START[Properties]
407     // SECTION-END
408     // SECTION-START[Messages]
409     // SECTION-END
410 }