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

jadex.base.test.impl.SharedServiceFactory Maven / Gradle / Ivy

Go to download

Jadex bridge is a base package for kernels and platforms, i.e., it is used by both and provides commonly used interfaces and classes for active components and their management.

There is a newer version: 4.0.267
Show newest version
package jadex.base.test.impl;

import java.lang.reflect.Method;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;

import jadex.bridge.IComponentIdentifier;
import jadex.bridge.service.IInternalService;
import jadex.bridge.service.annotation.OnEnd;
import jadex.bridge.service.annotation.OnStart;
import jadex.bridge.service.component.interceptors.ResolveInterceptor;
import jadex.commons.future.DelegationResultListener;
import jadex.commons.future.Future;
import jadex.commons.future.IFuture;

/**
 *  A factory for creating service instances that delegate to the same shared instance, i.e. it uses the first instance and ignores subsequent ones.
 */
public class SharedServiceFactory	implements Function, T>
{
	//-------- attributes --------
	
	/** The wrapper creation function. */
	protected BiFunction, SharedService>	wrapperfactory;
	
	/** The shared service instance. */
	protected volatile T	instance	=  null;
	
	/** The init future of the shared service. */
	protected volatile IFuture	inited	= null;
	
	/** The usage count to know when the service can be shut down. */
	protected volatile int	cnt	= 0;
	
	//-------- constructors --------
	
	/**
	 *  Create a factory for service sharing.
	 *  @param wrapperfactory	Function to create the individual wrappers for each platform.
	 */
	public SharedServiceFactory(BiFunction, SharedService> wrapperfactory)
	{
		this.wrapperfactory	= wrapperfactory;
	}

	/**
	 *  Create a new wrapper for the first supplied instance.
	 */
	@SuppressWarnings("unchecked")
	@Override
	public T apply(Supplier creator)
	{
		synchronized(this)
		{
			if(instance==null)
			{
				instance	= creator.get();
//				System.out.println("Created shared service instance: "+instance);
			}
		}
		return (T) wrapperfactory.apply(IComponentIdentifier.LOCAL.get(), this);
	}
	
	/**
	 *  Start the original service on first invocation.
	 */
	public IFuture startService()
	{
		Future	init	= null;
		synchronized(this)
		{
			cnt++;
			if(inited==null)
			{
				init	=  new Future();
				inited	= init;
			}
		}
		
		if(init!=null)
		{
//			System.out.println("Starting shared service instance: "+instance);
			if(instance instanceof IInternalService)
			{
				((IInternalService)instance).startService().addResultListener(new DelegationResultListener(init));
			}
			else
			{
				Method	m	= ResolveInterceptor.searchMethod(instance.getClass(), OnStart.class);
				if(m!=null)
				{
					try
					{
						Object	ret	= m.invoke(instance);
						if(ret instanceof IFuture)
						{
							@SuppressWarnings("unchecked")
							IFuture	fut	= (IFuture)ret;
							fut.addResultListener(new DelegationResultListener(init));
						}
						else
						{
							init.setResult(null);
						}
					}
					catch(Exception e)
					{
						init.setException(e);
					}
				}
				else
				{
					init.setResult(null);					
				}
			}
		}
		
		return inited;
	}
	
	/**
	 *  Shutdown the original service on last invocation.
	 */
	public IFuture shutdownService()
	{
		Object	tmp	= null;
		synchronized(this)
		{
			cnt--;
			if(cnt==0)
			{
				tmp	= instance;
				// Clear to allow another platform to be started with new service.
				instance	= null;
				inited	=  null;
			}
		}
		
		if(tmp!=null)
		{
//			System.out.println("Terminating shared service instance: "+tmp);
			if(tmp instanceof IInternalService)
			{
				return ((IInternalService)tmp).shutdownService();
			}
			else
			{
				Method	m	= ResolveInterceptor.searchMethod(tmp.getClass(), OnEnd.class);
				if(m!=null)
				{
					try
					{
						Object	ret	= m.invoke(tmp);
						if(ret instanceof IFuture)
						{
							@SuppressWarnings("unchecked")
							IFuture	fut	= (IFuture)ret;
							return fut;
						}
						else
						{
							return IFuture.DONE;
						}
					}
					catch(Exception e)
					{
						return new Future<>(e);
					}
				}
				else
				{
					return IFuture.DONE;				
				}
			}
		}
		else
		{
			return IFuture.DONE;
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy