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