001// SECTION-START[License Header] 002// <editor-fold defaultstate="collapsed" desc=" Generated License "> 003/* 004 * Java Object Management and Configuration 005 * Copyright (C) Christian Schulte, 2011-313 006 * All rights reserved. 007 * 008 * Redistribution and use in source and binary forms, with or without 009 * modification, are permitted provided that the following conditions 010 * are met: 011 * 012 * o Redistributions of source code must retain the above copyright 013 * notice, this list of conditions and the following disclaimer. 014 * 015 * o Redistributions in binary form must reproduce the above copyright 016 * notice, this list of conditions and the following disclaimer in 017 * the documentation and/or other materials provided with the 018 * distribution. 019 * 020 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 021 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 022 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 023 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, 024 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 025 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 026 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 027 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 028 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 029 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 030 * 031 * $JOMC: RuntimeImplementations.java 4795 2013-04-21 09:09:02Z schulte $ 032 * 033 */ 034// </editor-fold> 035// SECTION-END 036package org.jomc.ri.model; 037 038import java.util.Map; 039import javax.xml.bind.annotation.XmlTransient; 040import org.jomc.model.Implementation; 041import org.jomc.model.ImplementationReference; 042import org.jomc.model.Implementations; 043import org.jomc.model.ModelObjectException; 044import static org.jomc.ri.model.RuntimeModelObjects.createMap; 045 046// SECTION-START[Documentation] 047// <editor-fold defaultstate="collapsed" desc=" Generated Documentation "> 048/** 049 * Runtime {@code Implementations}. 050 * 051 * <dl> 052 * <dt><b>Identifier:</b></dt><dd>org.jomc.ri.model.RuntimeImplementations</dd> 053 * <dt><b>Name:</b></dt><dd>JOMC ⁑ RI ⁑ RuntimeImplementations</dd> 054 * <dt><b>Specifications:</b></dt> 055 * <dd>org.jomc.ri.model.RuntimeModelObject @ 1.2</dd> 056 * <dt><b>Abstract:</b></dt><dd>No</dd> 057 * <dt><b>Final:</b></dt><dd>No</dd> 058 * <dt><b>Stateless:</b></dt><dd>No</dd> 059 * </dl> 060 * 061 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a> 1.2 062 * @version 1.2 063 */ 064// </editor-fold> 065// SECTION-END 066// SECTION-START[Annotations] 067// <editor-fold defaultstate="collapsed" desc=" Generated Annotations "> 068@javax.annotation.Generated( value = "org.jomc.tools.SourceFileProcessor 1.5", comments = "See http://www.jomc.org/jomc/1.5/jomc-tools-1.5" ) 069// </editor-fold> 070// SECTION-END 071public class RuntimeImplementations extends Implementations implements RuntimeModelObject 072{ 073 // SECTION-START[RuntimeImplementations] 074 075 /** Cache map. */ 076 @XmlTransient 077 private transient final Map<String, Implementation> implementationsByIdentifierCache = createMap(); 078 079 /** Cache map. */ 080 @XmlTransient 081 private transient final Map<String, Implementation> implementationsByClassCache = createMap(); 082 083 /** Cache map. */ 084 @XmlTransient 085 private transient final Map<String, Implementation> implementationsByNameCache = createMap(); 086 087 /** Cache map. */ 088 @XmlTransient 089 private transient final Map<String, ImplementationReference> referencesByIdentifierCache = createMap(); 090 091 /** 092 * Creates a new {@code RuntimeImplementations} instance by deeply copying a given {@code Implementations} instance. 093 * 094 * @param implementations The instance to copy. 095 * 096 * @throws NullPointerException if {@code implementations} is {@code null}. 097 */ 098 public RuntimeImplementations( final Implementations implementations ) 099 { 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.5", comments = "See http://www.jomc.org/jomc/1.5/jomc-tools-1.5" ) 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}