All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.refcodes.decoupling.Reactor Maven / Gradle / Ivy

Go to download

Artifact for breaking up dependencies between components or modules of a software system (dependency injection and inversion of control).

There is a newer version: 3.3.8
Show newest version
// /////////////////////////////////////////////////////////////////////////////
// REFCODES.ORG
// /////////////////////////////////////////////////////////////////////////////
// This code is copyright (c) by Siegfried Steiner, Munich, Germany and licensed
// under the following (see "http://en.wikipedia.org/wiki/Multi-licensing")
// licenses:
// -----------------------------------------------------------------------------
// GNU General Public License, v3.0 ("http://www.gnu.org/licenses/gpl-3.0.html")
// -----------------------------------------------------------------------------
// Apache License, v2.0 ("http://www.apache.org/licenses/LICENSE-2.0")
// -----------------------------------------------------------------------------
// Please contact the copyright holding author(s) of the software artifacts in
// question for licensing issues not being covered by the above listed licenses,
// also regarding commercial licensing models or regarding the compatibility
// with other open source licenses.
// /////////////////////////////////////////////////////////////////////////////

package org.refcodes.decoupling;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.function.Function;

import org.refcodes.factory.Factory;
import org.refcodes.textual.VerboseTextBuilder;

/**
 * A {@link Reactor}'s instance is used for breaking up dependencies between a
 * Java software system's components or modules, which enables them to be
 * developed and tested independently (dependency injection and inversion of
 * control). The reactor wires components or modules together to form an
 * interacting application. The Reactor uses dependency injection and inversion
 * of control, which are two techniques that help achieve decoupling by allowing
 * components to depend on abstractions instead of concrete implementations.
 */
public class Reactor {

	// /////////////////////////////////////////////////////////////////////////
	// STATICS:
	// /////////////////////////////////////////////////////////////////////////

	// /////////////////////////////////////////////////////////////////////////
	// CONSTANTS:
	// /////////////////////////////////////////////////////////////////////////

	// /////////////////////////////////////////////////////////////////////////
	// VARIABLES:
	// /////////////////////////////////////////////////////////////////////////

	protected List> _dependencies = new ArrayList<>();
	protected List _interceptors = new ArrayList<>();

	// /////////////////////////////////////////////////////////////////////////
	// CONSTRUCTORS:
	// /////////////////////////////////////////////////////////////////////////

	// /////////////////////////////////////////////////////////////////////////
	// INJECTION:
	// /////////////////////////////////////////////////////////////////////////

	// /////////////////////////////////////////////////////////////////////////
	// METHODS:
	// /////////////////////////////////////////////////////////////////////////

	/**
	 * Adds a {@link Dependency} to the {@link Reactor} which's
	 * {@link DependencyBuilder} is returned for fluently configuring your
	 * {@link Dependency}.
	 * 
	 * @param  The type of the {@link Dependency}.
	 * 
	 * @param aType The type of the {@link Dependency}.
	 * 
	 * @return An instance of the {@link DependencyBuilder} class which is used
	 *         to fluently configure your {@link Dependency}.
	 */
	public  DependencyBuilder addDependency( Class aType ) {
		DependencyBuilder theBuilder = new DependencyBuilder<>( aType );
		_dependencies.add( theBuilder );
		return theBuilder;
	}

	/**
	 * Adds a {@link Dependency} to the {@link Reactor} which's
	 * {@link DependencyBuilder} is returned for fluently configuring your
	 * {@link Dependency}.
	 * 
	 * @param  The type of the {@link Dependency}.
	 * 
	 * @param aInstance The instance of the {@link Dependency}.
	 * 
	 * @return An instance of the {@link DependencyBuilder} class which is used
	 *         to fluently configure your {@link Dependency}.
	 */
	public  DependencyBuilder addDependency( T aInstance ) {
		DependencyBuilder theBuilder = new DependencyBuilder<>( aInstance ).withInstanceMetrics( InstanceMode.SINGLETON_IS_MANDATORY );
		_dependencies.add( theBuilder );
		return theBuilder;
	}

	/**
	 * Adds a {@link Dependency} fabricated by a factory.
	 * 
	 * @param  The type of the factory producing the {@link Dependency}.
	 * @param  The type of the {@link Dependency} itself.
	 * @param aType The type of the {@link Dependency} to be fabricated by the
	 *        factory.
	 * @param aFactory The {@link Factory} instance producing the according
	 *        {@link Dependency} declaration(s).
	 * 
	 * @return An instance of the {@link DependencyBuilder} class which is used
	 *         to fluently configure your {@link Dependency}.
	 */
	public , T> DependencyBuilder addDependency( Class aType, F aFactory ) {
		DependencyBuilder theContext = new DependencyBuilder<>( aFactory ).withAlias( UUID.randomUUID().toString() );
		_dependencies.add( theContext );
		DependencyBuilder theFactory = new DependencyBuilder<>( aType ).withFactory( theContext.getType(), ( f ) -> aFactory.create(), theContext.getAlias() );
		_dependencies.add( theFactory );
		return theFactory;
	}

	/**
	 * Adds a {@link Dependency} fabricated by a factory.
	 * 
	 * @param  The type of the factory producing the {@link Dependency}.
	 * @param  The type of the {@link Dependency} itself.
	 * @param aType The type of the {@link Dependency} to be fabricated by the
	 *        factory.
	 * @param aFactory The type of the {@link Factory} producing the according
	 *        {@link Dependency} declaration(s).
	 * 
	 * @return An instance of the {@link DependencyBuilder} class which is used
	 *         to fluently configure your {@link Dependency}.
	 */
	public , T> DependencyBuilder addDependency( Class aType, Class aFactory ) {
		return addDependency( aType, aFactory, ( f ) -> f.create() );
	}

	/**
	 * Adds a {@link Dependency} fabricated from factory's context
	 * ({@link Dependency}).
	 * 
	 * @param  The type of the factory's context ({@link Dependency}).
	 * @param  The type of the {@link Dependency} itself.
	 * @param aType The type of the {@link Dependency} to be fabricated by the
	 *        factory.
	 * @param aDependency The context ({@link Dependency}) used by the factory
	 *        to produce the resulting {@link Dependency}.
	 * @param aFactory The factory {@link Function} using the context to produce
	 *        the according {@link Dependency} declaration(s).
	 * 
	 * @return An instance of the {@link DependencyBuilder} class which is used
	 *         to fluently configure your {@link Dependency}.
	 */
	public  DependencyBuilder addDependency( Class aType, Class aDependency, Function aFactory ) {
		DependencyBuilder theContext = new DependencyBuilder<>( aDependency ).withAlias( UUID.randomUUID().toString() );
		_dependencies.add( theContext );
		DependencyBuilder theFactory = new DependencyBuilderFactory<>( aType, theContext ).withFactory( theContext.getType(), ( f ) -> aFactory.apply( f ), theContext.getAlias() );
		_dependencies.add( theFactory );
		return theFactory;
	}

	/**
	 * Tests whether the given {@link DependencyInterceptor} instance has been
	 * added.
	 * 
	 * @param aInterceptor The {@link DependencyInterceptor} instance for which
	 *        to test if it has been added.
	 * 
	 * @return True if the given {@link DependencyInterceptor} instance has been
	 *         added already.
	 */
	public boolean hasInterceptor( DependencyInterceptor aInterceptor ) {
		return _interceptors.contains( aInterceptor );
	}

	/**
	 * Adds the given {@link DependencyInterceptor} instance. The
	 * {@link DependencyInterceptor} instance itself acts as the handle which is
	 * used when removing the given {@link DependencyInterceptor} instance
	 * later.
	 * 
	 * @param aInterceptor The {@link DependencyInterceptor} instance which is
	 *        to be added.
	 * 
	 * @return True if the {@link DependencyInterceptor} instance has been added
	 *         successfully. If the {@link DependencyInterceptor} instance has
	 *         already been added, false is returned.
	 */
	public boolean addInterceptor( DependencyInterceptor aInterceptor ) {
		if ( !_interceptors.contains( aInterceptor ) ) {
			return _interceptors.add( aInterceptor );
		}
		return false;
	}

	/**
	 * Removes the {@link DependencyInterceptor} instance. In case the
	 * {@link DependencyInterceptor} instance has not been added before, then
	 * false is returned.
	 * 
	 * @param aInterceptor The {@link DependencyInterceptor} instance which is
	 *        to be removed.
	 * 
	 * @return True if the {@link DependencyInterceptor} instance has been
	 *         removed successfully. If there was none such
	 *         {@link DependencyInterceptor} instance or if the
	 *         {@link DependencyInterceptor} instance has already been removed,
	 *         then false is returned.
	 */
	public boolean removeInterceptor( DependencyInterceptor aInterceptor ) {
		return _interceptors.remove( aInterceptor );
	}

	/**
	 * Creates a {@link Context} which describes the components and modules
	 * wired together by this {@link Reactor}.
	 *
	 * @return The accordingly wired {@link Context} instance.
	 * 
	 * @throws AmbigousDependencyException thrown in case for a required
	 *         {@link Dependency} there are more than one matching
	 *         {@link Dependency} candidates in the {@link Reactor}.
	 * @throws UnsatisfiedDependencyException thrown in case for a required
	 *         {@link Dependency} none matching {@link Dependency} candidates in
	 *         the {@link Reactor} have been found (taking the profiles applied
	 *         into account) for the constructors of the given
	 *         {@link Dependency}.
	 * @throws CircularDependencyException thrown in case there is some
	 *         (transitive) circular dependency between two {@link Dependency}
	 *         instances.
	 * @throws DuplicateDependencyException is thrown in case there are multiple
	 *         identical dependencies applicable by the {@link Reactor}.
	 * @throws DuplicateClaimException is thrown in case there are multiple
	 *         identical claims declared by a {@link Dependency}.
	 * @throws UnsatisfiedClaimException is thrown in case a {@link Claim}
	 *         instance cannot be satisfied by any known {@link Dependency}
	 *         instance.
	 * @throws AmbigousClaimException is thrown in case one {@link Claim} can be
	 *         matched by multiple dependencies.
	 * @throws AmbigousInitializerException is thrown in case one
	 *         {@link InitializerClaim} instance can be matched by multiple
	 *         dependencies.
	 * @throws UnsatisfiedInitializerException is thrown in case a
	 *         {@link InitializerClaim} instance cannot be satisfied by any
	 *         known {@link Dependency} declaration.
	 * @throws AmbigousFactoryException is thrown in case one
	 *         {@link FactoryClaim} instance can be matched by multiple
	 *         dependencies.
	 * @throws UnsatisfiedFactoryException is thrown in case a
	 *         {@link FactoryClaim} instance cannot be satisfied by any known
	 *         {@link Dependency} declaration.
	 * @throws InstallDependencyException is thrown when trying to install a
	 *         {@link Dependency} into the {@link Context}, though installing
	 *         failed die to the dependency throwing an exception during the
	 *         process of installing (e.g. instantiation).
	 */
	public Context createContext() throws AmbigousDependencyException, UnsatisfiedDependencyException, CircularDependencyException, DuplicateDependencyException, DuplicateClaimException, UnsatisfiedClaimException, AmbigousClaimException, AmbigousInitializerException, UnsatisfiedInitializerException, AmbigousFactoryException, UnsatisfiedFactoryException, InstallDependencyException {
		return createContext( new Object[] {} );
	}

	/**
	 * Creates a {@link Context}, regarding the provided profiles, which
	 * describes the components and modules wired together by this
	 * {@link Reactor}.
	 *
	 * @param aProfiles The profiles to take into account when creating the
	 *        {@link Context} instance.
	 * 
	 * @return The accordingly wired {@link Context} instance, as of the
	 *         provided profiles.
	 * 
	 * @throws AmbigousDependencyException thrown in case for a required
	 *         {@link Dependency} there are more than one matching
	 *         {@link Dependency} candidates in the {@link Reactor}.
	 * @throws UnsatisfiedDependencyException thrown in case for a required
	 *         {@link Dependency} none matching {@link Dependency} candidates in
	 *         the {@link Reactor} have been found (taking the profiles applied
	 *         into account) for the constructors of the given
	 *         {@link Dependency}.
	 * @throws CircularDependencyException thrown in case there is some
	 *         (transitive) circular dependency between two {@link Dependency}
	 *         instances.
	 * @throws DuplicateDependencyException is thrown in case there are multiple
	 *         identical dependencies applicable by the {@link Reactor}.
	 * @throws DuplicateClaimException is thrown in case there are multiple
	 *         identical claims declared by a {@link Dependency}.
	 * @throws UnsatisfiedClaimException is thrown in case a {@link Claim}
	 *         instance cannot be satisfied by any known {@link Dependency}
	 *         instance.
	 * @throws AmbigousClaimException is thrown in case one {@link Claim} can be
	 *         matched by multiple dependencies.
	 * @throws AmbigousInitializerException is thrown in case one
	 *         {@link InitializerClaim} instance can be matched by multiple
	 *         dependencies.
	 * @throws UnsatisfiedInitializerException is thrown in case a
	 *         {@link InitializerClaim} instance cannot be satisfied by any
	 *         known {@link Dependency} declaration.
	 * @throws AmbigousFactoryException is thrown in case one
	 *         {@link FactoryClaim} instance can be matched by multiple
	 *         dependencies.
	 * @throws UnsatisfiedFactoryException is thrown in case a
	 *         {@link FactoryClaim} instance cannot be satisfied by any known
	 *         {@link Dependency} declaration.
	 * @throws InstallDependencyException is thrown when trying to install a
	 *         {@link Dependency} into the {@link Context}, though installing
	 *         failed die to the dependency throwing an exception during the
	 *         process of installing (e.g. instantiation).
	 */
	public Context createContext( String... aProfiles ) throws AmbigousDependencyException, UnsatisfiedDependencyException, CircularDependencyException, DuplicateDependencyException, DuplicateClaimException, UnsatisfiedClaimException, AmbigousClaimException, AmbigousInitializerException, UnsatisfiedInitializerException, AmbigousFactoryException, UnsatisfiedFactoryException, InstallDependencyException {
		return createContext( (Object[]) aProfiles );
	}

	/**
	 * Creates a {@link Context}, regarding the provided profiles, which
	 * describes the components and modules wired together by this
	 * {@link Reactor}.
	 *
	 * @param aProfiles The profiles to take into account when creating the
	 *        {@link Context} instance.
	 * 
	 * @return The accordingly wired {@link Context} instance, as of the
	 *         provided profiles.
	 * 
	 * @throws AmbigousDependencyException thrown in case for a required
	 *         {@link Dependency} there are more than one matching
	 *         {@link Dependency} candidates in the {@link Reactor}.
	 * @throws UnsatisfiedDependencyException thrown in case for a required
	 *         {@link Dependency} none matching {@link Dependency} candidates in
	 *         the {@link Reactor} have been found (taking the profiles applied
	 *         into account) for the constructors of the given
	 *         {@link Dependency}.
	 * @throws CircularDependencyException thrown in case there is some
	 *         (transitive) circular dependency between two {@link Dependency}
	 *         instances.
	 * @throws DuplicateDependencyException is thrown in case there are multiple
	 *         identical dependencies applicable by the {@link Reactor}.
	 * @throws DuplicateClaimException is thrown in case there are multiple
	 *         identical claims declared by a {@link Dependency}.
	 * @throws UnsatisfiedClaimException is thrown in case a {@link Claim}
	 *         instance cannot be satisfied by any known {@link Dependency}
	 *         instance.
	 * @throws AmbigousClaimException is thrown in case one {@link Claim} can be
	 *         matched by multiple dependencies.
	 * @throws AmbigousInitializerException is thrown in case one
	 *         {@link InitializerClaim} instance can be matched by multiple
	 *         dependencies.
	 * @throws UnsatisfiedInitializerException is thrown in case a
	 *         {@link InitializerClaim} instance cannot be satisfied by any
	 *         known {@link Dependency} declaration.
	 * @throws AmbigousFactoryException is thrown in case one
	 *         {@link FactoryClaim} instance can be matched by multiple
	 *         dependencies.
	 * @throws UnsatisfiedFactoryException is thrown in case a
	 *         {@link FactoryClaim} instance cannot be satisfied by any known
	 *         {@link Dependency} declaration.
	 * @throws InstallDependencyException is thrown when trying to install a
	 *         {@link Dependency} into the {@link Context}, though installing
	 *         failed die to the dependency throwing an exception during the
	 *         process of installing (e.g. instantiation).
	 */
	public Context createContext( Object... aProfiles ) throws AmbigousDependencyException, UnsatisfiedDependencyException, CircularDependencyException, DuplicateDependencyException, DuplicateClaimException, UnsatisfiedClaimException, AmbigousClaimException, AmbigousInitializerException, UnsatisfiedInitializerException, AmbigousFactoryException, UnsatisfiedFactoryException, InstallDependencyException {
		Context theCtx = toContext( aProfiles );
		Dependency[] theDependencies = toDependencies( aProfiles );
		toDependencies( theDependencies );
		for ( Dependency eDependency : theDependencies ) {
			try {
				if ( eDependency.getInstanceMetrics().isMandatory() ) {
					eDependency.toInstance( theDependencies, aProfiles );
				}
			}
			catch ( AmbigousDependencyException e ) {
				throw new AmbigousDependencyException( e.getDependency(), e.getDependencies(), "Cannot create context as of an ambigous dependency!", e );
			}
			catch ( UnsatisfiedDependencyException e ) {
				throw new UnsatisfiedDependencyException( e.getDependency(), e.getDependencies(), "Cannot create context as of an unsatisified dependency!", e );
			}
		}
		theCtx.initialize( theDependencies );
		return theCtx;
	}

	// /////////////////////////////////////////////////////////////////////////
	// HOOKS:
	// /////////////////////////////////////////////////////////////////////////
	
	/**
	 * Hook method to create (and prepare) an empty {@link Context} (sub-class).
	 * 
	 * @param aProfiles The profiles being applied when creating the
	 *        {@link Context}.
	 * 
	 * @return The according {@link Context} (sub-class) instance.
	 */
	protected Context toContext( Object[] aProfiles ) {
		return new Context( aProfiles );
	}
	
	/**
	 * Invokes all registered {@link DependencyInterceptor} instances for the
	 * given {@link Dependency} declaration's instance for intercepting
	 * purposes.
	 * 
	 * @param  The type of the {@link Dependency}
	 * @param aInstance The instance created for the provided {@link Dependency}
	 *        declaration.
	 * @param aDependency The {@link Dependency} declaration.
	 * 
	 * @return The intercepted instance.
	 */
	@SuppressWarnings("unchecked")
	protected  T intercept( T aInstance, Dependency aDependency ) {
		if ( aInstance == null ) throw new NullPointerException( "The provided instance must not be !" );
		for ( DependencyInterceptor eInterceptor : _interceptors ) {
			aInstance = (T) eInterceptor.intercept( aInstance, aDependency );
			if ( aInstance == null ) throw new NullPointerException( "The intercepted work piece must not be !" );
		}
		return aInstance;
	}

	// /////////////////////////////////////////////////////////////////////////
	// TEST HOOKS:
	// /////////////////////////////////////////////////////////////////////////

	/**
	 * Returns a list of {@link Dependency} declarations matching the provided
	 * profiles.
	 * 
	 * @param aProfiles The profiles with which to match.
	 * 
	 * @return The according list of {@link Dependency} declarations.
	 */
	Dependency[] toDependencies( Object... aProfiles ) {
		List> theDependencies = new ArrayList<>();
		for ( DependencyBuilder eDependency : _dependencies ) {
			if ( eDependency.hasProfile( aProfiles ) ) {
				theDependencies.add( new Dependency<>( eDependency, this ) );
			}
		}
		return theDependencies.toArray( new Dependency[theDependencies.size()] );
	}

	// /////////////////////////////////////////////////////////////////////////
	// HELPER:
	// /////////////////////////////////////////////////////////////////////////

	private void toDependencies( Dependency[] theDependencies ) throws DuplicateClaimException, UnsatisfiedInitializerException, UnsatisfiedFactoryException, UnsatisfiedClaimException, DuplicateDependencyException {
		Claim[] eClaims;
		for ( int i = 0; i < theDependencies.length; i++ ) {
			// Duplicate claims:
			eClaims = theDependencies[i].getClaims();
			if ( theDependencies[i].getSetup() != null ) {
				eClaims = Arrays.copyOf( eClaims, eClaims.length + 1 );
				eClaims[eClaims.length - 1] = theDependencies[i].getSetup();
			}
			if ( theDependencies[i].getFactory() != null ) {
				eClaims = Arrays.copyOf( eClaims, eClaims.length + 1 );
				eClaims[eClaims.length - 1] = theDependencies[i].getFactory();
			}
			for ( int a = 0; a < eClaims.length; a++ ) {
				for ( int b = a + 1; b < eClaims.length; b++ ) {
					if ( b != a && eClaims[b].equals( eClaims[a] ) ) {
						throw new DuplicateClaimException( theDependencies[i], eClaims[a], eClaims, "An identical claim for type <" + eClaims[a].getType().getSimpleName() + "> in dependency <" + theDependencies[i] + "> already exists (" + eClaims[a] + ")!" );
					}
				}
				// Unsatisfied claims:
				out: {
					for ( Dependency eDependency : theDependencies ) {
						if ( eDependency != theDependencies[i] ) {
							if ( eClaims[a].isClaim( eDependency ) ) {
								break out;
							}
						}
					}
					if ( eClaims[a] instanceof InitializerClaim ) {
						throw new UnsatisfiedInitializerException( theDependencies[i], (InitializerClaim) eClaims[a], theDependencies, "The initializer <" + eClaims[a] + "> for dependency <" + theDependencies[i] + "> cannot be satisfied by any of the provided dependencies: " + VerboseTextBuilder.asString( theDependencies ) );
					}
					if ( eClaims[a] instanceof FactoryClaim ) {
						throw new UnsatisfiedFactoryException( theDependencies[i], (FactoryClaim) eClaims[a], theDependencies, "The factory <" + eClaims[a] + "> for dependency <" + theDependencies[i] + "> cannot be satisfied by any of the provided dependencies: " + VerboseTextBuilder.asString( theDependencies ) );
					}
					throw new UnsatisfiedClaimException( theDependencies[i], eClaims[a], theDependencies, "The claim <" + eClaims[a] + "> for dependency <" + theDependencies[i] + "> cannot be satisfied by any of the provided dependencies: " + VerboseTextBuilder.asString( theDependencies ) );
				}
			}
			// Duplicate dependencies:
			for ( int j = i + 1; j < theDependencies.length; j++ ) {
				if ( theDependencies[j].equals( theDependencies[i] ) ) {
					throw new DuplicateDependencyException( theDependencies[i], theDependencies, "An identical dependency for type <" + theDependencies[i].getType().getSimpleName() + "> and alias <" + theDependencies[i].getAlias() + "> already exists (" + theDependencies[j] + ")!" );
				}
				// if ( theDependencies[j].getAlias() != null && theDependencies[i].getAlias() != null && theDependencies[j].getAlias().equalsIgnoreCase( theDependencies[i].getAlias() ) ) {
				//	throw new AmbigousAliasException( theDependencies[i], theDependencies[j].getAlias(), theDependencies, "An identical dependency with alias <" + theDependencies[i].getAlias() + "> already exists (" + theDependencies[j] + ")!" );
				// }
			}
		}
	}

	// /////////////////////////////////////////////////////////////////////////
	// INNER CLASSES:
	// /////////////////////////////////////////////////////////////////////////

	private static class DependencyBuilderFactory extends DependencyBuilder {

		private DependencyBuilder _dependencyBuilder;

		DependencyBuilderFactory( Class aType, DependencyBuilder aDependencyBuilder ) {
			super( aType );
			_dependencyBuilder = aDependencyBuilder;
		}

		@Override
		public void setInstanceMetrics( InstanceMetrics aInstanceMetrics ) {
			_dependencyBuilder.setInstanceMetrics( toInstanceMetrics( aInstanceMetrics ) );
			super.setInstanceMetrics( aInstanceMetrics );
		};

		@Override
		public void setInstanceMetrics( InstanceMode aInstanceMode ) {
			_dependencyBuilder.setInstanceMetrics( toInstanceMetrics( aInstanceMode ) );
			super.setInstanceMetrics( aInstanceMode );
		};

		@Override
		public DependencyBuilder withInstanceMetrics( InstanceMetrics aInstanceMetrics ) {
			_dependencyBuilder.setInstanceMetrics( toInstanceMetrics( aInstanceMetrics ) );
			return super.withInstanceMetrics( aInstanceMetrics );
		};

		@Override
		public DependencyBuilder withInstanceMetrics( InstanceMode aInstanceMode ) {
			_dependencyBuilder.setInstanceMetrics( toInstanceMetrics( aInstanceMode ) );
			return super.withInstanceMetrics( aInstanceMode );
		}

		private InstanceMetrics toInstanceMetrics( InstanceMetrics aInstanceMode ) {
			return aInstanceMode.isSingleton() ? aInstanceMode : new InstanceMetrics() {

				@Override
				public boolean isSingleton() {
					return aInstanceMode.isSingleton();
				}

				@Override
				public boolean isMandatory() {
					return false;
				}
			};
		};
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy