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: RuntimeModules.java 4381 2012-03-04 19:29:29Z schulte2005 $
32   *
33   */
34  // </editor-fold>
35  // SECTION-END
36  package org.jomc.ri.model;
37  
38  import java.util.List;
39  import java.util.Map;
40  import javax.xml.bind.annotation.XmlTransient;
41  import org.jomc.model.Dependencies;
42  import org.jomc.model.Dependency;
43  import org.jomc.model.Implementation;
44  import org.jomc.model.Implementations;
45  import org.jomc.model.Instance;
46  import org.jomc.model.Message;
47  import org.jomc.model.Messages;
48  import org.jomc.model.Module;
49  import org.jomc.model.Modules;
50  import org.jomc.model.Properties;
51  import org.jomc.model.Property;
52  import org.jomc.model.Specification;
53  import org.jomc.model.Specifications;
54  import static org.jomc.ri.model.RuntimeModelObjects.createMap;
55  
56  // SECTION-START[Documentation]
57  // <editor-fold defaultstate="collapsed" desc=" Generated Documentation ">
58  /**
59   * Runtime {@code Modules}.
60   *
61   * <dl>
62   *   <dt><b>Identifier:</b></dt><dd>org.jomc.ri.model.RuntimeModules</dd>
63   *   <dt><b>Name:</b></dt><dd>JOMC RI RuntimeModules</dd>
64   *   <dt><b>Specifications:</b></dt>
65   *     <dd>org.jomc.ri.model.RuntimeModelObject @ 1.2</dd>
66   *   <dt><b>Abstract:</b></dt><dd>No</dd>
67   *   <dt><b>Final:</b></dt><dd>No</dd>
68   *   <dt><b>Stateless:</b></dt><dd>No</dd>
69   * </dl>
70   *
71   * @author <a href="mailto:schulte2005@users.sourceforge.net">Christian Schulte</a> 1.2
72   * @version 1.2
73   */
74  // </editor-fold>
75  // SECTION-END
76  // SECTION-START[Annotations]
77  // <editor-fold defaultstate="collapsed" desc=" Generated Annotations ">
78  @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" )
79  // </editor-fold>
80  // SECTION-END
81  public class RuntimeModules extends Modules implements RuntimeModelObject
82  {
83      // SECTION-START[RuntimeModules]
84  
85      /** Cache map. */
86      @XmlTransient
87      private transient final Map<String, Module> modulesByNameCache = createMap();
88  
89      /** Cache map. */
90      @XmlTransient
91      private transient final Map<String, Specifications> specificationsCache = createMap();
92  
93      /** Cache map. */
94      @XmlTransient
95      private transient final Map<String, Implementations> implementationsCache = createMap();
96  
97      /** Cache map. */
98      @XmlTransient
99      private transient final Map<String, Module> moduleBySpecificationIdentifierCache = createMap();
100 
101     /** Cache map. */
102     @XmlTransient
103     private transient final Map<String, Module> moduleByImplementationIdentifierCache = createMap();
104 
105     /** Cache map. */
106     @XmlTransient
107     private transient final Map<String, Specification> specificationByIdentifierCache = createMap();
108 
109     /** Cache map. */
110     @XmlTransient
111     private transient final Map<String, Specification> specificationByClassNameCache = createMap();
112 
113     /** Cache map. */
114     @XmlTransient
115     private transient final Map<String, Specifications> specificationsByImplemenationIdentifierCache = createMap();
116 
117     /** Cache map. */
118     @XmlTransient
119     private transient final Map<String, Implementation> implementationByIdentifierCache = createMap();
120 
121     /** Cache map. */
122     @XmlTransient
123     private transient final Map<String, Implementation> implementationByClassNameCache = createMap();
124 
125     /** Cache map. */
126     @XmlTransient
127     private transient final Map<String, Implementation> implementationByObjectClassNameCache = createMap();
128 
129     /** Cache map. */
130     @XmlTransient
131     private transient final Map<String, Implementation> implementationBySpecificationAndNameCache = createMap();
132 
133     /** Cache map. */
134     @XmlTransient
135     private transient final Map<String, Dependencies> dependenciesByImplementationIdentifierCache = createMap();
136 
137     /** Cache map. */
138     @XmlTransient
139     private transient final Map<String, Properties> propertiesByImplementationIdentifierCache = createMap();
140 
141     /** Cache map. */
142     @XmlTransient
143     private transient final Map<String, Properties> specifiedPropertiesByImplementationIdentifierCache = createMap();
144 
145     /** Cache map. */
146     @XmlTransient
147     private transient final Map<String, Messages> messagesByImplementationIdentifierCache = createMap();
148 
149     /** Cache map. */
150     @XmlTransient
151     private transient final Map<String, Implementations> implementationsBySpecificationIdentifierCache = createMap();
152 
153     /** Cache map. */
154     @XmlTransient
155     private transient final Map<String, List<Object>> anyObjectsByImplemenationIdentifierCache = createMap();
156 
157     /**
158      * Creates a new {@code RuntimeModules} instance by deeply copying a given {@code Modules} instance.
159      *
160      * @param modules The instance to copy.
161      *
162      * @throws NullPointerException if {@code modules} is {@code null}.
163      */
164     public RuntimeModules( final Modules modules )
165     {
166         super( modules );
167 
168         if ( this.getAuthors() != null )
169         {
170             this.setAuthors( RuntimeModelObjects.getInstance().copyOf( this.getAuthors() ) );
171         }
172         if ( this.getDocumentation() != null )
173         {
174             this.setDocumentation( RuntimeModelObjects.getInstance().copyOf( this.getDocumentation() ) );
175         }
176 
177         this.copyModules();
178     }
179 
180     /**
181      * Creates a new {@code DefaultModules} instance by deeply copying a given {@code Modules} instance taking a map
182      * backing the instance.
183      *
184      * @param modules The instance to copy.
185      * @param objects The map backing the instance.
186      *
187      * @throws NullPointerException if {@code modules} or {@code objects} is {@code null}.
188      */
189     public RuntimeModules( final Modules modules, final Map<Object, Instance> objects )
190     {
191         super( modules, objects );
192 
193         if ( this.getAuthors() != null )
194         {
195             this.setAuthors( RuntimeModelObjects.getInstance().copyOf( this.getAuthors() ) );
196         }
197         if ( this.getDocumentation() != null )
198         {
199             this.setDocumentation( RuntimeModelObjects.getInstance().copyOf( this.getDocumentation() ) );
200         }
201 
202         this.copyModules();
203     }
204 
205     /**
206      * Gets a module for a given name from the list of modules.
207      * <p>This method queries an internal cache for a result object to return for the given argument values. If no
208      * cached result object is available, this method queries the super-class for a result object to return and caches
209      * the outcome of that query for use on successive calls.</p>
210      * <p><b>Note:</b><br/>Method {@code clear()} must be used to synchronize the state of the internal cache with the
211      * state of the instance, should the state of the instance change.</p>
212      *
213      * @param name The name of the module to return.
214      *
215      * @return The first matching module or {@code null}, if no such module is found.
216      *
217      * @throws NullPointerException if {@code name} is {@code null}.
218      *
219      * @see #getModule()
220      * @see Module#getName()
221      * @see #clear()
222      */
223     @Override
224     public Module getModule( final String name )
225     {
226         if ( name == null )
227         {
228             throw new NullPointerException( "name" );
229         }
230 
231         synchronized ( this.modulesByNameCache )
232         {
233             Module m = this.modulesByNameCache.get( name );
234 
235             if ( m == null && !this.modulesByNameCache.containsKey( name ) )
236             {
237                 m = super.getModule( name );
238                 this.modulesByNameCache.put( name, m );
239             }
240 
241             return m;
242         }
243     }
244 
245     /**
246      * Gets all specifications of the list of modules.
247      * <p>This method queries an internal cache for a result object to return. If no cached result object is available,
248      * this method queries the super-class for a result object to return and caches the outcome of that query for use on
249      * successive calls.</p>
250      * <p><b>Note:</b><br/>Method {@code clear()} must be used to synchronize the state of the internal cache with the
251      * state of the instance, should the state of the instance change.</p>
252      *
253      * @return All specifications or {@code null}, if no specifications are found.
254      *
255      * @see #getModule()
256      * @see #clear()
257      */
258     @Override
259     public Specifications getSpecifications()
260     {
261         synchronized ( this.specificationsCache )
262         {
263             Specifications s = this.specificationsCache.get( RuntimeModules.class.getName() );
264 
265             if ( s == null && !this.specificationsCache.containsKey( RuntimeModules.class.getName() ) )
266             {
267                 s = super.getSpecifications();
268 
269                 if ( s != null )
270                 {
271                     s = RuntimeModelObjects.getInstance().copyOf( s );
272                 }
273 
274                 this.specificationsCache.put( RuntimeModules.class.getName(), s );
275             }
276 
277             return s;
278         }
279     }
280 
281     /**
282      * Gets all specifications of the list of modules.
283      * <p>This method queries an internal cache for a result object to return. If no cached result object is available,
284      * this method queries the super-class for a result object to return and caches the outcome of that query for use on
285      * successive calls.</p>
286      * <p><b>Note:</b><br/>Method {@code clear()} must be used to synchronize the state of the internal cache with the
287      * state of the instance, should the state of the instance change.</p>
288      *
289      * @return All specifications or {@code null}, if no specifications are found.
290      *
291      * @see #getModule()
292      * @see #clear()
293      */
294     @Override
295     public Implementations getImplementations()
296     {
297         synchronized ( this.implementationsCache )
298         {
299             Implementations i = this.implementationsCache.get( RuntimeModules.class.getName() );
300 
301             if ( i == null && !this.implementationsCache.containsKey( RuntimeModules.class.getName() ) )
302             {
303                 i = super.getImplementations();
304 
305                 if ( i != null )
306                 {
307                     i = RuntimeModelObjects.getInstance().copyOf( i );
308                 }
309 
310                 this.implementationsCache.put( RuntimeModules.class.getName(), i );
311             }
312 
313             return i;
314         }
315     }
316 
317     /**
318      * Gets the module declaring a given specification from the list of modules.
319      * <p>This method queries an internal cache for a result object to return for the given argument values. If no
320      * cached result object is available, this method queries the super-class for a result object to return and caches
321      * the outcome of that query for use on successive calls.</p>
322      * <p><b>Note:</b><br/>Method {@code clear()} must be used to synchronize the state of the internal cache with the
323      * state of the instance, should the state of the instance change.</p>
324      *
325      * @param specification The identifier of the specification whose declaring module to return.
326      *
327      * @return The first matching module or {@code null}, if no such module is found.
328      *
329      * @throws NullPointerException if {@code specification} is {@code null}.
330      *
331      * @see #getModule()
332      * @see Module#getSpecifications()
333      * @see Specifications#getSpecification( java.lang.String )
334      * @see #clear()
335      */
336     @Override
337     public Module getModuleOfSpecification( final String specification )
338     {
339         if ( specification == null )
340         {
341             throw new NullPointerException( "specification" );
342         }
343 
344         synchronized ( this.moduleBySpecificationIdentifierCache )
345         {
346             Module m = this.moduleBySpecificationIdentifierCache.get( specification );
347 
348             if ( m == null && !this.moduleBySpecificationIdentifierCache.containsKey( specification ) )
349             {
350                 m = super.getModuleOfSpecification( specification );
351                 this.moduleBySpecificationIdentifierCache.put( specification, m );
352             }
353 
354             return m;
355         }
356     }
357 
358     /**
359      * Gets the module declaring a given implementation from the list of modules.
360      * <p>This method queries an internal cache for a result object to return for the given argument values. If no
361      * cached result object is available, this method queries the super-class for a result object to return and caches
362      * the outcome of that query for use on successive calls.</p>
363      * <p><b>Note:</b><br/>Method {@code clear()} must be used to synchronize the state of the internal cache with the
364      * state of the instance, should the state of the instance change.</p>
365      *
366      * @param implementation The identifier of the implementation whose declaring module to return.
367      *
368      * @return The first matching module or {@code null}, if no such module is found.
369      *
370      * @throws NullPointerException if {@code implementation} is {@code null}.
371      *
372      * @see #getModule()
373      * @see Module#getImplementations()
374      * @see Implementations#getImplementation( java.lang.String )
375      * @see #clear()
376      */
377     @Override
378     public Module getModuleOfImplementation( final String implementation )
379     {
380         if ( implementation == null )
381         {
382             throw new NullPointerException( "implementation" );
383         }
384 
385         synchronized ( this.moduleByImplementationIdentifierCache )
386         {
387             Module m = this.moduleByImplementationIdentifierCache.get( implementation );
388 
389             if ( m == null && !this.moduleByImplementationIdentifierCache.containsKey( implementation ) )
390             {
391                 m = super.getModuleOfImplementation( implementation );
392                 this.moduleByImplementationIdentifierCache.put( implementation, m );
393             }
394 
395             return m;
396         }
397     }
398 
399     /**
400      * Gets a specification for a given identifier from the list of modules.
401      * <p>This method queries an internal cache for a result object to return for the given argument values. If no
402      * cached result object is available, this method queries the super-class for a result object to return and caches
403      * the outcome of that query for use on successive calls.</p>
404      * <p><b>Note:</b><br/>Method {@code clear()} must be used to synchronize the state of the internal cache with the
405      * state of the instance, should the state of the instance change.</p>
406      *
407      * @param specification The identifier of the specification to return.
408      *
409      * @return The first matching specification or {@code null}, if no such specification is found.
410      *
411      * @throws NullPointerException if {@code specification} is {@code null}.
412      *
413      * @see #getModule()
414      * @see Module#getSpecifications()
415      * @see Specifications#getSpecification( java.lang.String )
416      * @see #clear()
417      */
418     @Override
419     public Specification getSpecification( final String specification )
420     {
421         if ( specification == null )
422         {
423             throw new NullPointerException( "specification" );
424         }
425 
426         synchronized ( this.specificationByIdentifierCache )
427         {
428             Specification s = this.specificationByIdentifierCache.get( specification );
429 
430             if ( s == null && !this.specificationByIdentifierCache.containsKey( specification ) )
431             {
432                 s = super.getSpecification( specification );
433                 this.specificationByIdentifierCache.put( specification, s );
434             }
435 
436             return s;
437         }
438     }
439 
440     /**
441      * Gets a specification for a given class from the list of modules.
442      * <p>This method queries an internal cache for a result object to return for the given argument values. If no
443      * cached result object is available, this method queries the super-class for a result object to return and caches
444      * the outcome of that query for use on successive calls.</p>
445      * <p><b>Note:</b><br/>Method {@code clear()} must be used to synchronize the state of the internal cache with the
446      * state of the instance, should the state of the instance change.</p>
447      *
448      * @param specification The class of the specification to return.
449      *
450      * @return The first matching specification or {@code null}, if no such specification is found.
451      *
452      * @throws NullPointerException if {@code specification} is {@code null}.
453      *
454      * @see #getModule()
455      * @see Module#getSpecifications()
456      * @see Specifications#getSpecification( java.lang.Class )
457      * @see #clear()
458      */
459     @Override
460     public Specification getSpecification( final Class<?> specification )
461     {
462         if ( specification == null )
463         {
464             throw new NullPointerException( "specification" );
465         }
466 
467         synchronized ( this.specificationByClassNameCache )
468         {
469             Specification s = this.specificationByClassNameCache.get( specification.getName() );
470 
471             if ( s == null && !this.specificationByClassNameCache.containsKey( specification.getName() ) )
472             {
473                 s = super.getSpecification( specification );
474                 this.specificationByClassNameCache.put( specification.getName(), s );
475             }
476 
477             return s;
478         }
479     }
480 
481     /**
482      * Gets all specifications an implementation implements from the list of modules.
483      * <p>This method queries an internal cache for a result object to return for the given argument values. If no
484      * cached result object is available, this method queries the super-class for a result object to return and caches
485      * the outcome of that query for use on successive calls.</p>
486      * <p><b>Note:</b><br/>Method {@code clear()} must be used to synchronize the state of the internal cache with the
487      * state of the instance, should the state of the instance change.</p>
488      *
489      * @param implementation The identifier of the implementation to get all implemented specifications of.
490      *
491      * @return All specifications implemented by the first matching implementation or {@code null}, if no such
492      * implementation is found or if the first matching implementation does not implement any specification.
493      *
494      * @throws NullPointerException if {@code implementation} is {@code null}.
495      *
496      * @see #getModule()
497      * @see #getImplementation( java.lang.String )
498      * @see Implementation#getImplementations()
499      * @see Implementations#getReference()
500      * @see #clear()
501      */
502     @Override
503     public Specifications getSpecifications( final String implementation )
504     {
505         if ( implementation == null )
506         {
507             throw new NullPointerException( "implementation" );
508         }
509 
510         synchronized ( this.specificationsByImplemenationIdentifierCache )
511         {
512             Specifications s = this.specificationsByImplemenationIdentifierCache.get( implementation );
513 
514             if ( s == null && !this.specificationsByImplemenationIdentifierCache.containsKey( implementation ) )
515             {
516                 s = super.getSpecifications( implementation );
517 
518                 if ( s != null )
519                 {
520                     s = RuntimeModelObjects.getInstance().copyOf( s );
521                 }
522 
523                 this.specificationsByImplemenationIdentifierCache.put( implementation, s );
524             }
525 
526             return s;
527         }
528     }
529 
530     /**
531      * Gets an implementation for a given identifier from the list of modules.
532      * <p>This method queries an internal cache for a result object to return for the given argument values. If no
533      * cached result object is available, this method queries the super-class for a result object to return and caches
534      * the outcome of that query for use on successive calls.</p>
535      * <p><b>Note:</b><br/>Method {@code clear()} must be used to synchronize the state of the internal cache with the
536      * state of the instance, should the state of the instance change.</p>
537      *
538      * @param implementation The identifier of the implementation to return.
539      *
540      * @return The first matching implementation or {@code null}, if no such implementation is found.
541      *
542      * @throws NullPointerException if {@code implementation} is {@code null}.
543      *
544      * @see #getModule()
545      * @see Module#getImplementations()
546      * @see Implementations#getImplementation( java.lang.String )
547      * @see #clear()
548      */
549     @Override
550     public Implementation getImplementation( final String implementation )
551     {
552         if ( implementation == null )
553         {
554             throw new NullPointerException( "implementation" );
555         }
556 
557         synchronized ( this.implementationByIdentifierCache )
558         {
559             Implementation i = this.implementationByIdentifierCache.get( implementation );
560 
561             if ( i == null && !this.implementationByIdentifierCache.containsKey( implementation ) )
562             {
563                 i = super.getImplementation( implementation );
564                 this.implementationByIdentifierCache.put( implementation, i );
565             }
566 
567             return i;
568         }
569     }
570 
571     /**
572      * Gets an implementation for a given class from the list of modules.
573      * <p>This method queries an internal cache for a result object to return for the given argument values. If no
574      * cached result object is available, this method queries the super-class for a result object to return and caches
575      * the outcome of that query for use on successive calls.</p>
576      * <p><b>Note:</b><br/>Method {@code clear()} must be used to synchronize the state of the internal cache with the
577      * state of the instance, should the state of the instance change.</p>
578      *
579      * @param implementation The class of the implementation to return.
580      *
581      * @return The first matching implementation or {@code null}, if no such implementation is found.
582      *
583      * @throws NullPointerException if {@code implementation} is {@code null}.
584      *
585      * @see #getModule()
586      * @see Module#getImplementations()
587      * @see Implementations#getImplementation( java.lang.Class )
588      * @see #clear()
589      */
590     @Override
591     public Implementation getImplementation( final Class<?> implementation )
592     {
593         if ( implementation == null )
594         {
595             throw new NullPointerException( "implementation" );
596         }
597 
598         synchronized ( this.implementationByClassNameCache )
599         {
600             Implementation i = this.implementationByClassNameCache.get( implementation.getName() );
601 
602             if ( i == null && !this.implementationByClassNameCache.containsKey( implementation.getName() ) )
603             {
604                 i = super.getImplementation( implementation );
605                 this.implementationByClassNameCache.put( implementation.getName(), i );
606             }
607 
608             return i;
609         }
610     }
611 
612     /**
613      * Gets an implementation for a given object from the list of modules.
614      * <p>This method queries an internal cache for a result object to return for the given argument values. If no
615      * cached result object is available, this method queries the super-class for a result object to return and caches
616      * the outcome of that query for use on successive calls.</p>
617      * <p><b>Note:</b><br/>Method {@code clear()} must be used to synchronize the state of the internal cache with the
618      * state of the instance, should the state of the instance change.</p>
619      *
620      * @param object The object of the implementation to return.
621      *
622      * @return The first matching implementation or {@code null}, if no such implementation is found.
623      *
624      * @throws NullPointerException if {@code object} is {@code null}.
625      *
626      * @see #getModule()
627      * @see #getImplementation( java.lang.Class )
628      * @see #clear()
629      */
630     @Override
631     public Implementation getImplementation( final Object object )
632     {
633         if ( object == null )
634         {
635             throw new NullPointerException( "object" );
636         }
637 
638         synchronized ( this.implementationByObjectClassNameCache )
639         {
640             Implementation i = this.implementationByObjectClassNameCache.get( object.getClass().getName() );
641 
642             if ( i == null && !this.implementationByObjectClassNameCache.containsKey( object.getClass().getName() ) )
643             {
644                 i = super.getImplementation( object );
645                 this.implementationByObjectClassNameCache.put( object.getClass().getName(), i );
646             }
647 
648             return i;
649         }
650     }
651 
652     /**
653      * Gets an implementation for a given name implementing a given specification from the list of modules.
654      * <p>This method queries an internal cache for a result object to return for the given argument values. If no
655      * cached result object is available, this method queries the super-class for a result object to return and caches
656      * the outcome of that query for use on successive calls.</p>
657      * <p><b>Note:</b><br/>Method {@code clear()} must be used to synchronize the state of the internal cache with the
658      * state of the instance, should the state of the instance change.</p>
659      *
660      * @param specification The identifier of the specification to return an implementation of.
661      * @param name The name of the implementation to return.
662      *
663      * @return The first matching implementation or {@code null}, if no such implementation is found.
664      *
665      * @throws NullPointerException if {@code specification} or {@code name} is {@code null}.
666      *
667      * @see #getModule()
668      * @see #getImplementations( java.lang.String )
669      * @see Implementations#getImplementationByName( java.lang.String )
670      * @see #clear()
671      */
672     @Override
673     public Implementation getImplementation( final String specification, final String name )
674     {
675         if ( specification == null )
676         {
677             throw new NullPointerException( "specification" );
678         }
679         if ( name == null )
680         {
681             throw new NullPointerException( "name" );
682         }
683 
684         synchronized ( this.implementationBySpecificationAndNameCache )
685         {
686             final String key = specification + "|" + name;
687             Implementation i = this.implementationBySpecificationAndNameCache.get( key );
688 
689             if ( i == null && !this.implementationBySpecificationAndNameCache.containsKey( key ) )
690             {
691                 i = super.getImplementation( specification, name );
692                 this.implementationBySpecificationAndNameCache.put( key, i );
693             }
694 
695             return i;
696         }
697     }
698 
699     /**
700      * Gets all dependencies of an implementation from the list of modules.
701      * <p>This method queries an internal cache for a result object to return for the given argument values. If no
702      * cached result object is available, this method queries the super-class for a result object to return and caches
703      * the outcome of that query for use on successive calls.</p>
704      * <p><b>Note:</b><br/>Method {@code clear()} must be used to synchronize the state of the internal cache with the
705      * state of the instance, should the state of the instance change.</p>
706      *
707      * @param implementation The identifier of the implementation to get all dependencies of.
708      *
709      * @return All dependencies of the first matching implementation or {@code null}, if no such implementation is
710      * found or if the first matching implementation does not have any dependencies.
711      *
712      * @throws NullPointerException if {@code implementation} is {@code null}.
713      *
714      * @see #getModule()
715      * @see #getImplementation( java.lang.String )
716      * @see Implementation#getImplementations()
717      * @see Implementations#getReference()
718      * @see #clear()
719      */
720     @Override
721     public Dependencies getDependencies( final String implementation )
722     {
723         if ( implementation == null )
724         {
725             throw new NullPointerException( "implementation" );
726         }
727 
728         synchronized ( this.dependenciesByImplementationIdentifierCache )
729         {
730             Dependencies d = this.dependenciesByImplementationIdentifierCache.get( implementation );
731 
732             if ( d == null && !this.dependenciesByImplementationIdentifierCache.containsKey( implementation ) )
733             {
734                 d = super.getDependencies( implementation );
735 
736                 if ( d != null )
737                 {
738                     d = RuntimeModelObjects.getInstance().copyOf( d );
739                 }
740 
741                 this.dependenciesByImplementationIdentifierCache.put( implementation, d );
742             }
743 
744             return d;
745         }
746     }
747 
748     /**
749      * Gets all properties of an implementation from the list of modules.
750      * <p>This method queries an internal cache for a result object to return for the given argument values. If no
751      * cached result object is available, this method queries the super-class for a result object to return and caches
752      * the outcome of that query for use on successive calls.</p>
753      * <p><b>Note:</b><br/>Method {@code clear()} must be used to synchronize the state of the internal cache with the
754      * state of the instance, should the state of the instance change.</p>
755      *
756      * @param implementation The identifier of the implementation to get all properties of.
757      *
758      * @return All properties of the first matching implementation or {@code null}, if no such implementation is found
759      * or if the first matching implementation does not have any properties.
760      *
761      * @throws NullPointerException if {@code implementation} is {@code null}.
762      *
763      * @see #getModule()
764      * @see #getImplementation( java.lang.String )
765      * @see Implementation#getImplementations()
766      * @see Implementations#getReference()
767      * @see #clear()
768      */
769     @Override
770     public Properties getProperties( final String implementation )
771     {
772         if ( implementation == null )
773         {
774             throw new NullPointerException( "implementation" );
775         }
776 
777         synchronized ( this.propertiesByImplementationIdentifierCache )
778         {
779             Properties p = this.propertiesByImplementationIdentifierCache.get( implementation );
780 
781             if ( p == null && !this.propertiesByImplementationIdentifierCache.containsKey( implementation ) )
782             {
783                 p = super.getProperties( implementation );
784 
785                 if ( p != null )
786                 {
787                     p = RuntimeModelObjects.getInstance().copyOf( p );
788                 }
789 
790                 this.propertiesByImplementationIdentifierCache.put( implementation, p );
791             }
792 
793             return p;
794         }
795     }
796 
797     /**
798      * Gets all properties specified for an implementation from the list of modules.
799      * <p>This method queries an internal cache for a result object to return for the given argument values. If no
800      * cached result object is available, this method queries the super-class for a result object to return and caches
801      * the outcome of that query for use on successive calls.</p>
802      * <p><b>Note:</b><br/>Method {@code clear()} must be used to synchronize the state of the internal cache with the
803      * state of the instance, should the state of the instance change.</p>
804      *
805      * @param implementation The identifier of the implementation to return specified properties of.
806      *
807      * @return All properties specified for the first matching implementation or {@code null}, if no such implementation
808      * is found or if the first matching implementation does not have any specified properties.
809      *
810      * @throws NullPointerException if {@code implementation} is {@code null}.
811      *
812      * @see #getModule()
813      * @see #getSpecifications( java.lang.String )
814      * @see Specification#getProperties()
815      * @see #clear()
816      */
817     @Override
818     public Properties getSpecifiedProperties( final String implementation )
819     {
820         if ( implementation == null )
821         {
822             throw new NullPointerException( "implementation" );
823         }
824 
825         synchronized ( this.specifiedPropertiesByImplementationIdentifierCache )
826         {
827             Properties p = this.specifiedPropertiesByImplementationIdentifierCache.get( implementation );
828 
829             if ( p == null && !this.specifiedPropertiesByImplementationIdentifierCache.containsKey( implementation ) )
830             {
831                 p = super.getSpecifiedProperties( implementation );
832 
833                 if ( p != null )
834                 {
835                     p = RuntimeModelObjects.getInstance().copyOf( p );
836                 }
837 
838                 this.specifiedPropertiesByImplementationIdentifierCache.put( implementation, p );
839             }
840 
841             return p;
842         }
843     }
844 
845     /**
846      * Gets all messages of an implementation from the list of modules.
847      * <p>This method queries an internal cache for a result object to return for the given argument values. If no
848      * cached result object is available, this method queries the super-class for a result object to return and caches
849      * the outcome of that query for use on successive calls.</p>
850      * <p><b>Note:</b><br/>Method {@code clear()} must be used to synchronize the state of the internal cache with the
851      * state of the instance, should the state of the instance change.</p>
852      *
853      * @param implementation The identifier of the implementation to get all messages of.
854      *
855      * @return All messages of the first matching implementation or {@code null}, if no such implementation is found
856      * or if the first matching implementation does not have any messages.
857      *
858      * @throws NullPointerException if {@code implementation} is {@code null}.
859      *
860      * @see #getModule()
861      * @see #getImplementation( java.lang.String )
862      * @see Implementation#getImplementations()
863      * @see Implementations#getReference()
864      * @see #clear()
865      */
866     @Override
867     public Messages getMessages( final String implementation )
868     {
869         if ( implementation == null )
870         {
871             throw new NullPointerException( "implementation" );
872         }
873 
874         synchronized ( this.messagesByImplementationIdentifierCache )
875         {
876             Messages m = this.messagesByImplementationIdentifierCache.get( implementation );
877 
878             if ( m == null && !this.messagesByImplementationIdentifierCache.containsKey( implementation ) )
879             {
880                 m = super.getMessages( implementation );
881 
882                 if ( m != null )
883                 {
884                     m = RuntimeModelObjects.getInstance().copyOf( m );
885                 }
886 
887                 this.messagesByImplementationIdentifierCache.put( implementation, m );
888             }
889 
890             return m;
891         }
892     }
893 
894     /**
895      * Gets all implementations implementing a given specification from the list of modules.
896      * <p>This method queries an internal cache for a result object to return for the given argument values. If no
897      * cached result object is available, this method queries the super-class for a result object to return and caches
898      * the outcome of that query for use on successive calls.</p>
899      * <p><b>Note:</b><br/>Method {@code clear()} must be used to synchronize the state of the internal cache with the
900      * state of the instance, should the state of the instance change.</p>
901      *
902      * @param specification The identifier of the specification to return all implementations of.
903      *
904      * @return All implementations implementing the first matching specification or {@code null}, if no such
905      * specification is found or if the first matching specification does not have any implementations.
906      *
907      * @throws NullPointerException if {@code specification} is {@code null}.
908      *
909      * @see #getModule()
910      * @see #getSpecifications( java.lang.String )
911      * @see #clear()
912      */
913     @Override
914     public Implementations getImplementations( final String specification )
915     {
916         if ( specification == null )
917         {
918             throw new NullPointerException( "specification" );
919         }
920 
921         synchronized ( this.implementationsBySpecificationIdentifierCache )
922         {
923             Implementations i = this.implementationsBySpecificationIdentifierCache.get( specification );
924 
925             if ( i == null && !this.implementationsBySpecificationIdentifierCache.containsKey( specification ) )
926             {
927                 i = super.getImplementations( specification );
928 
929                 if ( i != null )
930                 {
931                     i = RuntimeModelObjects.getInstance().copyOf( i );
932                 }
933 
934                 this.implementationsBySpecificationIdentifierCache.put( specification, i );
935             }
936 
937             return i;
938         }
939     }
940 
941     /**
942      * Gets any objects of an implementation from the list of modules.
943      * <p>This method queries an internal cache for a result object to return for the given argument values. If no
944      * cached result object is available, this method queries the super-class for a result object to return and caches
945      * the outcome of that query for use on successive calls.</p>
946      * <p><b>Note:</b><br/>Method {@code clear()} must be used to synchronize the state of the internal cache with the
947      * state of the instance, should the state of the instance change.</p>
948      *
949      * @param implementation The identifier of the implementation to get any objects of.
950      *
951      * @return Any objects of the first matching implementation or {@code null}, if no such implementation is found.
952      *
953      * @throws NullPointerException if {@code implementation} is {@code null}.
954      *
955      * @see #getModule()
956      * @see #getImplementation( java.lang.String )
957      * @see Implementation#getImplementations()
958      * @see Implementations#getReference()
959      * @see #clear()
960      */
961     @Override
962     public List<Object> getAnyObjects( final String implementation )
963     {
964         if ( implementation == null )
965         {
966             throw new NullPointerException( "implementation" );
967         }
968 
969         synchronized ( this.anyObjectsByImplemenationIdentifierCache )
970         {
971             List<Object> any = this.anyObjectsByImplemenationIdentifierCache.get( implementation );
972 
973             if ( any == null && !this.anyObjectsByImplemenationIdentifierCache.containsKey( implementation ) )
974             {
975                 any = super.getAnyObjects( implementation );
976                 this.anyObjectsByImplemenationIdentifierCache.put( implementation, any );
977             }
978 
979             return any;
980         }
981     }
982 
983     /**
984      * Gets an instance for an implementation from the list of modules.
985      *
986      * @param implementation The identifier of the implementation to get an instance for.
987      *
988      * @return A new instance for the first matching implementation or {@code null}, if no such implementation is found.
989      *
990      * @throws NullPointerException if {@code implementation} is {@code null}.
991      *
992      * @see #getModule()
993      * @see #getImplementation( java.lang.String )
994      * @see #getDependencies(java.lang.String)
995      * @see #getProperties(java.lang.String)
996      * @see #getMessages(java.lang.String)
997      * @see #getSpecifications(java.lang.String)
998      * @see #getAnyObjects(java.lang.String)
999      */
1000     @Override
1001     public Instance getInstance( final String implementation )
1002     {
1003         if ( implementation == null )
1004         {
1005             throw new NullPointerException( "implementation" );
1006         }
1007 
1008         final Implementation i = this.getImplementation( implementation );
1009 
1010         if ( i != null && i.getClazz() != null )
1011         {
1012             final Instance instance = new RuntimeInstance();
1013             instance.setIdentifier( i.getIdentifier() );
1014             instance.setName( i.getName() );
1015             instance.setClazz( i.getClazz() );
1016             instance.setStateless( i.isStateless() );
1017             instance.setDependencies( this.getDependencies( implementation ) );
1018             instance.setProperties( this.getProperties( implementation ) );
1019             instance.setMessages( this.getMessages( implementation ) );
1020             instance.setSpecifications( this.getSpecifications( implementation ) );
1021             instance.getAny().addAll( this.getAnyObjects( implementation ) );
1022             return instance;
1023         }
1024 
1025         return null;
1026     }
1027 
1028     /**
1029      * Gets an instance for an implementation from the list of modules overridden with a given dependency.
1030      *
1031      * @param implementation The identifier of the implementation to get an instance for.
1032      * @param dependency The dependency to use for overriding model objects of the instance.
1033      *
1034      * @return An instance for the first matching implementation with any model objects overridden using
1035      * {@code dependency} or {@code null}, if no such implementation is found.
1036      *
1037      * @throws NullPointerException if {@code implementation} or {@code dependency} is {@code null}.
1038      *
1039      * @see #getModule()
1040      * @see #getInstance( java.lang.String )
1041      */
1042     @Override
1043     public Instance getInstance( final String implementation, final Dependency dependency )
1044     {
1045         if ( implementation == null )
1046         {
1047             throw new NullPointerException( "implementation" );
1048         }
1049         if ( dependency == null )
1050         {
1051             throw new NullPointerException( "dependency" );
1052         }
1053 
1054         Instance instance = this.getInstance( implementation );
1055 
1056         if ( instance != null )
1057         {
1058             final Specification dependencySpecification = this.getSpecification( dependency.getIdentifier() );
1059 
1060             if ( dependencySpecification != null && dependencySpecification.getScope() == null )
1061             {
1062                 if ( dependency.getDependencies() != null && !dependency.getDependencies().getDependency().isEmpty() )
1063                 {
1064                     final Dependencies dependencies =
1065                         RuntimeModelObjects.getInstance().copyOf( dependency.getDependencies() );
1066 
1067                     if ( instance.getDependencies() != null )
1068                     {
1069                         for ( int i = 0, s0 = instance.getDependencies().getDependency().size(); i < s0; i++ )
1070                         {
1071                             final Dependency d = instance.getDependencies().getDependency().get( i );
1072                             final Dependency td = dependencies.getDependency( d.getName() );
1073 
1074                             if ( td == null )
1075                             {
1076                                 dependencies.getDependency().add( d );
1077 
1078                                 if ( dependencies instanceof RuntimeModelObject )
1079                                 {
1080                                     ( (RuntimeModelObject) dependencies ).clear();
1081                                 }
1082                             }
1083                             else
1084                             {
1085                                 this.collectDependencies( d, td );
1086                             }
1087                         }
1088                     }
1089 
1090                     instance.setDependencies( dependencies );
1091                 }
1092 
1093                 if ( dependency.getMessages() != null && !dependency.getMessages().getMessage().isEmpty() )
1094                 {
1095                     final Messages messages =
1096                         RuntimeModelObjects.getInstance().copyOf( dependency.getMessages() );
1097 
1098                     if ( instance.getMessages() != null )
1099                     {
1100                         for ( int i = 0, s0 = instance.getMessages().getMessage().size(); i < s0; i++ )
1101                         {
1102                             final Message m = instance.getMessages().getMessage().get( i );
1103 
1104                             if ( messages.getMessage( m.getName() ) == null )
1105                             {
1106                                 messages.getMessage().add( m );
1107 
1108                                 if ( messages instanceof RuntimeModelObject )
1109                                 {
1110                                     ( (RuntimeModelObject) messages ).clear();
1111                                 }
1112                             }
1113                         }
1114                     }
1115 
1116                     instance.setMessages( messages );
1117                 }
1118 
1119                 if ( dependency.getProperties() != null && !dependency.getProperties().getProperty().isEmpty() )
1120                 {
1121                     final Properties properties =
1122                         RuntimeModelObjects.getInstance().copyOf( dependency.getProperties() );
1123 
1124                     if ( instance.getProperties() != null )
1125                     {
1126                         for ( int i = 0, s0 = instance.getProperties().getProperty().size(); i < s0; i++ )
1127                         {
1128                             final Property p = instance.getProperties().getProperty().get( i );
1129 
1130                             if ( properties.getProperty( p.getName() ) == null )
1131                             {
1132                                 properties.getProperty().add( p );
1133 
1134                                 if ( properties instanceof RuntimeModelObject )
1135                                 {
1136                                     ( (RuntimeModelObject) properties ).clear();
1137                                 }
1138                             }
1139                         }
1140                     }
1141 
1142                     instance.setProperties( properties );
1143                 }
1144             }
1145         }
1146 
1147         return instance;
1148     }
1149 
1150     private void collectDependencies( final Dependency source, final Dependency target )
1151     {
1152         if ( source.getMessages() != null )
1153         {
1154             if ( target.getMessages() == null )
1155             {
1156                 target.setMessages( new RuntimeMessages() );
1157             }
1158 
1159             for ( int i = 0, s0 = source.getMessages().getMessage().size(); i < s0; i++ )
1160             {
1161                 final Message m = source.getMessages().getMessage().get( i );
1162 
1163                 if ( target.getMessages().getMessage( m.getName() ) == null )
1164                 {
1165                     target.getMessages().getMessage().add( m );
1166 
1167                     if ( target.getMessages() instanceof RuntimeModelObject )
1168                     {
1169                         ( (RuntimeModelObject) target.getMessages() ).clear();
1170                     }
1171                 }
1172             }
1173         }
1174 
1175         if ( source.getProperties() != null )
1176         {
1177             if ( target.getProperties() == null )
1178             {
1179                 target.setProperties( new RuntimeProperties() );
1180             }
1181 
1182             for ( int i = 0, s0 = source.getProperties().getProperty().size(); i < s0; i++ )
1183             {
1184                 final Property p = source.getProperties().getProperty().get( i );
1185 
1186                 if ( target.getProperties().getProperty( p.getName() ) == null )
1187                 {
1188                     target.getProperties().getProperty().add( p );
1189 
1190                     if ( target.getProperties() instanceof RuntimeModelObject )
1191                     {
1192                         ( (RuntimeModelObject) target.getProperties() ).clear();
1193                     }
1194                 }
1195             }
1196         }
1197 
1198         if ( source.getDependencies() != null )
1199         {
1200             if ( target.getDependencies() == null )
1201             {
1202                 target.setDependencies( new RuntimeDependencies() );
1203             }
1204 
1205             for ( int i = 0, s0 = source.getDependencies().getDependency().size(); i < s0; i++ )
1206             {
1207                 final Dependency sd = source.getDependencies().getDependency().get( i );
1208                 final Dependency td = target.getDependencies().getDependency( sd.getName() );
1209 
1210                 if ( td == null )
1211                 {
1212                     target.getDependencies().getDependency().add( sd );
1213 
1214                     if ( target.getDependencies() instanceof RuntimeModelObject )
1215                     {
1216                         ( (RuntimeModelObject) target.getDependencies() ).clear();
1217                     }
1218                 }
1219                 else
1220                 {
1221                     this.collectDependencies( sd, td );
1222                 }
1223             }
1224         }
1225     }
1226 
1227     private void copyModules()
1228     {
1229         for ( int i = 0, s0 = this.getModule().size(); i < s0; i++ )
1230         {
1231             final Module m = this.getModule().get( i );
1232             this.getModule().set( i, RuntimeModelObjects.getInstance().copyOf( m ) );
1233         }
1234     }
1235 
1236     // SECTION-END
1237     // SECTION-START[RuntimeModelObject]
1238     public void gc()
1239     {
1240         gcMap( this.specificationsCache );
1241         gcMap( this.implementationsCache );
1242         gcMap( this.specificationsByImplemenationIdentifierCache );
1243         gcMap( this.dependenciesByImplementationIdentifierCache );
1244         gcMap( this.propertiesByImplementationIdentifierCache );
1245         gcMap( this.specifiedPropertiesByImplementationIdentifierCache );
1246         gcMap( this.messagesByImplementationIdentifierCache );
1247         gcMap( this.implementationsBySpecificationIdentifierCache );
1248         this.gcOrClear( true, false );
1249     }
1250 
1251     public void clear()
1252     {
1253         synchronized ( this.anyObjectsByImplemenationIdentifierCache )
1254         {
1255             this.anyObjectsByImplemenationIdentifierCache.clear();
1256         }
1257         synchronized ( this.dependenciesByImplementationIdentifierCache )
1258         {
1259             this.dependenciesByImplementationIdentifierCache.clear();
1260         }
1261         synchronized ( this.implementationByClassNameCache )
1262         {
1263             this.implementationByClassNameCache.clear();
1264         }
1265         synchronized ( this.implementationByIdentifierCache )
1266         {
1267             this.implementationByIdentifierCache.clear();
1268         }
1269         synchronized ( this.implementationByObjectClassNameCache )
1270         {
1271             this.implementationByObjectClassNameCache.clear();
1272         }
1273         synchronized ( this.implementationBySpecificationAndNameCache )
1274         {
1275             this.implementationBySpecificationAndNameCache.clear();
1276         }
1277         synchronized ( this.implementationsBySpecificationIdentifierCache )
1278         {
1279             this.implementationsBySpecificationIdentifierCache.clear();
1280         }
1281         synchronized ( this.implementationsCache )
1282         {
1283             this.implementationsCache.clear();
1284         }
1285         synchronized ( this.messagesByImplementationIdentifierCache )
1286         {
1287             this.messagesByImplementationIdentifierCache.clear();
1288         }
1289         synchronized ( this.moduleByImplementationIdentifierCache )
1290         {
1291             this.moduleByImplementationIdentifierCache.clear();
1292         }
1293         synchronized ( this.moduleBySpecificationIdentifierCache )
1294         {
1295             this.moduleBySpecificationIdentifierCache.clear();
1296         }
1297         synchronized ( this.modulesByNameCache )
1298         {
1299             this.modulesByNameCache.clear();
1300         }
1301         synchronized ( this.propertiesByImplementationIdentifierCache )
1302         {
1303             this.propertiesByImplementationIdentifierCache.clear();
1304         }
1305         synchronized ( this.specificationByClassNameCache )
1306         {
1307             this.specificationByClassNameCache.clear();
1308         }
1309         synchronized ( this.specificationByIdentifierCache )
1310         {
1311             this.specificationByIdentifierCache.clear();
1312         }
1313         synchronized ( this.specificationsByImplemenationIdentifierCache )
1314         {
1315             this.specificationsByImplemenationIdentifierCache.clear();
1316         }
1317         synchronized ( this.specificationsCache )
1318         {
1319             this.specificationsCache.clear();
1320         }
1321         synchronized ( this.specifiedPropertiesByImplementationIdentifierCache )
1322         {
1323             this.specifiedPropertiesByImplementationIdentifierCache.clear();
1324         }
1325 
1326         this.gcOrClear( false, true );
1327     }
1328 
1329     private void gcOrClear( final boolean gc, final boolean clear )
1330     {
1331         if ( this.getAuthors() instanceof RuntimeModelObject )
1332         {
1333             if ( gc )
1334             {
1335                 ( (RuntimeModelObject) this.getAuthors() ).gc();
1336             }
1337             if ( clear )
1338             {
1339                 ( (RuntimeModelObject) this.getAuthors() ).clear();
1340             }
1341         }
1342         if ( this.getDocumentation() instanceof RuntimeModelObject )
1343         {
1344             if ( gc )
1345             {
1346                 ( (RuntimeModelObject) this.getDocumentation() ).gc();
1347             }
1348             if ( clear )
1349             {
1350                 ( (RuntimeModelObject) this.getDocumentation() ).clear();
1351             }
1352         }
1353 
1354         this.gcOrClearModules( gc, clear );
1355     }
1356 
1357     private void gcOrClearModules( final boolean gc, final boolean clear )
1358     {
1359 
1360         for ( int i = 0, s0 = this.getModule().size(); i < s0; i++ )
1361         {
1362             final Module m = this.getModule().get( i );
1363             if ( m instanceof RuntimeModelObject )
1364             {
1365                 if ( gc )
1366                 {
1367                     ( (RuntimeModelObject) m ).gc();
1368                 }
1369                 if ( clear )
1370                 {
1371                     ( (RuntimeModelObject) m ).clear();
1372                 }
1373             }
1374         }
1375     }
1376 
1377     private static void gcMap( final Map<?, ?> map )
1378     {
1379         synchronized ( map )
1380         {
1381             for ( Map.Entry<?, ?> e : map.entrySet() )
1382             {
1383                 if ( e.getValue() instanceof RuntimeModelObject )
1384                 {
1385                     ( (RuntimeModelObject) e.getValue() ).gc();
1386                 }
1387             }
1388         }
1389     }
1390 
1391     // SECTION-END
1392     // SECTION-START[Constructors]
1393     // <editor-fold defaultstate="collapsed" desc=" Generated Constructors ">
1394     /** Creates a new {@code RuntimeModules} instance. */
1395     @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" )
1396     public RuntimeModules()
1397     {
1398         // SECTION-START[Default Constructor]
1399         super();
1400         // SECTION-END
1401     }
1402     // </editor-fold>
1403     // SECTION-END
1404     // SECTION-START[Dependencies]
1405     // SECTION-END
1406     // SECTION-START[Properties]
1407     // SECTION-END
1408     // SECTION-START[Messages]
1409     // SECTION-END
1410 }