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: RuntimeSpecifications.java 5010 2014-11-17 04:00:16Z schulte $
32   *
33   */
34  // </editor-fold>
35  // SECTION-END
36  package org.jomc.ri.model;
37  
38  import java.text.ParseException;
39  import java.util.Map;
40  import javax.xml.bind.annotation.XmlTransient;
41  import org.jomc.model.ModelObjectException;
42  import org.jomc.model.Specification;
43  import org.jomc.model.SpecificationReference;
44  import org.jomc.model.Specifications;
45  import static org.jomc.ri.model.RuntimeModelObjects.createMap;
46  
47  // SECTION-START[Documentation]
48  // <editor-fold defaultstate="collapsed" desc=" Generated Documentation ">
49  /**
50   * Runtime {@code Specifications}.
51   *
52   * <dl>
53   *   <dt><b>Identifier:</b></dt><dd>org.jomc.ri.model.RuntimeSpecifications</dd>
54   *   <dt><b>Name:</b></dt><dd>JOMC ⁑ RI ⁑ RuntimeSpecifications</dd>
55   *   <dt><b>Specifications:</b></dt>
56   *     <dd>org.jomc.ri.model.RuntimeModelObject @ 1.2</dd>
57   *   <dt><b>Abstract:</b></dt><dd>No</dd>
58   *   <dt><b>Final:</b></dt><dd>No</dd>
59   *   <dt><b>Stateless:</b></dt><dd>No</dd>
60   * </dl>
61   *
62   * @author <a href="mailto:cs@schulte.it">Christian Schulte</a> 1.2
63   * @version 1.2
64   */
65  // </editor-fold>
66  // SECTION-END
67  // SECTION-START[Annotations]
68  // <editor-fold defaultstate="collapsed" desc=" Generated Annotations ">
69  @javax.annotation.Generated( value = "org.jomc.tools.SourceFileProcessor 1.8", comments = "See http://www.jomc.org/jomc/1.8/jomc-tools-1.8" )
70  // </editor-fold>
71  // SECTION-END
72  public class RuntimeSpecifications extends Specifications implements RuntimeModelObject
73  {
74      // SECTION-START[RuntimeSpecifications]
75  
76      /** Cache map. */
77      @XmlTransient
78      private transient final Map<String, Specification> specificationsByIdentifierCache = createMap();
79  
80      /** Cache map. */
81      @XmlTransient
82      private transient final Map<String, Specification> specificationsByClassCache = createMap();
83  
84      /** Cache map. */
85      @XmlTransient
86      private transient final Map<String, SpecificationReference> referencesByIdentifierCache = createMap();
87  
88      /**
89       * Creates a new {@code RuntimeSpecifications} instance by deeply copying a given {@code Specifications} instance.
90       *
91       * @param specifications The instance to copy.
92       *
93       * @throws NullPointerException if {@code specifications} is {@code null}.
94       */
95      public RuntimeSpecifications( final Specifications specifications )
96      {
97          super( specifications );
98  
99          if ( this.getAuthors() != null )
100         {
101             this.setAuthors( RuntimeModelObjects.getInstance().copyOf( this.getAuthors() ) );
102         }
103         if ( this.getDocumentation() != null )
104         {
105             this.setDocumentation( RuntimeModelObjects.getInstance().copyOf( this.getDocumentation() ) );
106         }
107 
108         this.copySpecifications();
109         this.copyReferences();
110     }
111 
112     /**
113      * Gets a specification for a given identifier from the list of specifications.
114      * <p>This method queries an internal cache for a result object to return for the given argument values. If no
115      * cached result object is available, this method queries the super-class for a result object to return and caches
116      * the outcome of that query for use on successive calls.</p>
117      * <p><b>Note:</b><br/>Method {@code clear()} must be used to synchronize the state of the internal cache with the
118      * state of the instance, should the state of the instance change.</p>
119      *
120      * @param specification The identifier of the specification to return.
121      *
122      * @return The first matching specification or {@code null}, if no such specification is found.
123      *
124      * @throws NullPointerException if {@code specification} is {@code null}.
125      *
126      * @see #getSpecification()
127      * @see Specification#getIdentifier()
128      * @see #clear()
129      */
130     @Override
131     public Specification getSpecification( final String specification )
132     {
133         if ( specification == null )
134         {
135             throw new NullPointerException( "specification" );
136         }
137 
138         synchronized ( this.specificationsByIdentifierCache )
139         {
140             Specification s = this.specificationsByIdentifierCache.get( specification );
141 
142             if ( s == null && !this.specificationsByIdentifierCache.containsKey( specification ) )
143             {
144                 s = super.getSpecification( specification );
145                 this.specificationsByIdentifierCache.put( specification, s );
146             }
147 
148             return s;
149         }
150     }
151 
152     /**
153      * Gets a specification for a given class from the list of specifications.
154      * <p>This method queries an internal cache for a result object to return for the given argument values. If no
155      * cached result object is available, this method queries the super-class for a result object to return and caches
156      * the outcome of that query for use on successive calls.</p>
157      * <p><b>Note:</b><br/>Method {@code clear()} must be used to synchronize the state of the internal cache with the
158      * state of the instance, should the state of the instance change.</p>
159      *
160      * @param specification The class of the specification to return.
161      *
162      * @return The first matching specification or {@code null}, if no such specification is found.
163      *
164      * @throws NullPointerException if {@code specification} is {@code null}.
165      * @throws ModelObjectException if parsing a name of a referenced type fails.
166      *
167      * @see #getSpecification()
168      * @see Specification#isClassDeclaration()
169      * @see Specification#getClazz()
170      * @see #clear()
171      */
172     @Override
173     public Specification getSpecification( final Class<?> specification ) throws ModelObjectException
174     {
175         if ( specification == null )
176         {
177             throw new NullPointerException( "specification" );
178         }
179 
180         synchronized ( this.specificationsByClassCache )
181         {
182             Specification s = this.specificationsByClassCache.get( specification.getName() );
183 
184             if ( s == null && !this.specificationsByClassCache.containsKey( specification.getName() ) )
185             {
186                 s = super.getSpecification( specification );
187                 this.specificationsByClassCache.put( specification.getName(), s );
188             }
189 
190             return s;
191         }
192     }
193 
194     /**
195      * Gets a specification reference for a given identifier from the list of references.
196      * <p>This method queries an internal cache for a result object to return for the given argument values. If no
197      * cached result object is available, this method queries the super-class for a result object to return and caches
198      * the outcome of that query for use on successive calls.</p>
199      * <p><b>Note:</b><br/>Method {@code clear()} must be used to synchronize the state of the internal cache with the
200      * state of the instance, should the state of the instance change.</p>
201      *
202      * @param specification The identifier of the reference to return.
203      *
204      * @return The first matching specification reference or {@code null}, if no such specification reference is found.
205      *
206      * @throws NullPointerException if {@code specification} is {@code null}.
207      *
208      * @see #getReference()
209      * @see SpecificationReference#getIdentifier()
210      * @see #clear()
211      */
212     @Override
213     public SpecificationReference getReference( final String specification )
214     {
215         if ( specification == null )
216         {
217             throw new NullPointerException( "specification" );
218         }
219 
220         synchronized ( this.referencesByIdentifierCache )
221         {
222             SpecificationReference r = this.referencesByIdentifierCache.get( specification );
223 
224             if ( r == null && !this.referencesByIdentifierCache.containsKey( specification ) )
225             {
226                 r = super.getReference( specification );
227                 this.referencesByIdentifierCache.put( specification, r );
228             }
229 
230             return r;
231         }
232     }
233 
234     private void copySpecifications()
235     {
236         for ( int i = 0, s0 = this.getSpecification().size(); i < s0; i++ )
237         {
238             final Specification s = this.getSpecification().get( i );
239             this.getSpecification().set( i, RuntimeModelObjects.getInstance().copyOf( s ) );
240         }
241     }
242 
243     private void copyReferences()
244     {
245         for ( int i = 0, s0 = this.getReference().size(); i < s0; i++ )
246         {
247             final SpecificationReference r = this.getReference().get( i );
248             this.getReference().set( i, RuntimeModelObjects.getInstance().copyOf( r ) );
249         }
250     }
251 
252     // SECTION-END
253     // SECTION-START[RuntimeModelObject]
254     public void gc()
255     {
256         this.gcOrClear( true, false );
257     }
258 
259     public void clear()
260     {
261         synchronized ( this.specificationsByClassCache )
262         {
263             this.specificationsByClassCache.clear();
264         }
265         synchronized ( this.specificationsByIdentifierCache )
266         {
267             this.specificationsByIdentifierCache.clear();
268         }
269         synchronized ( this.referencesByIdentifierCache )
270         {
271             this.referencesByIdentifierCache.clear();
272         }
273 
274         this.gcOrClear( false, true );
275     }
276 
277     private void gcOrClear( final boolean gc, final boolean clear )
278     {
279         if ( this.getAuthors() instanceof RuntimeModelObject )
280         {
281             if ( gc )
282             {
283                 ( (RuntimeModelObject) this.getAuthors() ).gc();
284             }
285             if ( clear )
286             {
287                 ( (RuntimeModelObject) this.getAuthors() ).clear();
288             }
289         }
290         if ( this.getDocumentation() instanceof RuntimeModelObject )
291         {
292             if ( gc )
293             {
294                 ( (RuntimeModelObject) this.getDocumentation() ).gc();
295             }
296             if ( clear )
297             {
298                 ( (RuntimeModelObject) this.getDocumentation() ).clear();
299             }
300         }
301 
302         this.gcOrClearReferences( gc, clear );
303         this.gcOrClearSpecifications( gc, clear );
304     }
305 
306     private void gcOrClearSpecifications( final boolean gc, final boolean clear )
307     {
308         for ( int i = 0, s0 = this.getSpecification().size(); i < s0; i++ )
309         {
310             final Specification s = this.getSpecification().get( i );
311             if ( s instanceof RuntimeModelObject )
312             {
313                 if ( gc )
314                 {
315                     ( (RuntimeModelObject) s ).gc();
316                 }
317                 if ( clear )
318                 {
319                     ( (RuntimeModelObject) s ).clear();
320                 }
321             }
322         }
323     }
324 
325     private void gcOrClearReferences( final boolean gc, final boolean clear )
326     {
327         for ( int i = 0, s0 = this.getReference().size(); i < s0; i++ )
328         {
329             final SpecificationReference r = this.getReference().get( i );
330             if ( r instanceof RuntimeModelObject )
331             {
332                 if ( gc )
333                 {
334                     ( (RuntimeModelObject) r ).gc();
335                 }
336                 if ( clear )
337                 {
338                     ( (RuntimeModelObject) r ).clear();
339                 }
340             }
341         }
342     }
343     // SECTION-END
344     // SECTION-START[Constructors]
345     // <editor-fold defaultstate="collapsed" desc=" Generated Constructors ">
346     /** Creates a new {@code RuntimeSpecifications} instance. */
347     @javax.annotation.Generated( value = "org.jomc.tools.SourceFileProcessor 1.8", comments = "See http://www.jomc.org/jomc/1.8/jomc-tools-1.8" )
348     public RuntimeSpecifications()
349     {
350         // SECTION-START[Default Constructor]
351         super();
352         // SECTION-END
353     }
354     // </editor-fold>
355     // SECTION-END
356     // SECTION-START[Dependencies]
357     // SECTION-END
358     // SECTION-START[Properties]
359     // SECTION-END
360     // SECTION-START[Messages]
361     // SECTION-END
362 }