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

com.github.nill14.utils.init.impl.LazyPojo Maven / Gradle / Ivy

There is a newer version: 0.4.0
Show newest version
package com.github.nill14.utils.init.impl;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;

import javax.inject.Provider;

import com.github.nill14.utils.init.api.ILazyPojo;
import com.github.nill14.utils.init.api.IPojoFactory;
import com.github.nill14.utils.init.api.IPojoInitializer;

public class LazyPojo implements ILazyPojo, Provider {

	/**
	 * 
	 */
	private static final long serialVersionUID = 5927142279116185259L;

	public static  ILazyPojo forClass(Class beanClass) {
		return forClass(beanClass, IPojoInitializer.empty());
	}

	public static > ILazyPojo forFactory(Class beanClass, Class factoryClass) {
		return forFactory(beanClass, factoryClass, IPojoInitializer.empty());
	}
	
	public static  ILazyPojo forClass(Class beanClass, IPojoInitializer initializer) {
		IPojoFactory factory = PojoFactory.create(beanClass);
		return new LazyPojo<>(factory, initializer);
	}

	public static > ILazyPojo forFactory(Class beanClass, Class factoryClass, IPojoInitializer factoryInitializer) {
		FactoryAdapter factoryAdapter = new FactoryAdapter<>(beanClass, factoryClass, factoryInitializer);
		return new LazyPojo<>(factoryAdapter, factoryAdapter);
	}
	
	private final IPojoFactory factory;
	private final IPojoInitializer initializer;
	private volatile transient T instance;

	public LazyPojo(IPojoFactory factory, IPojoInitializer initializer) {
		this.factory = factory;
		this.initializer = initializer;
	}
	
	@Override
	public Class getInstanceType() {
		return factory.getType();
	}
	
	@Override
	public T get() {
		return getInstance();
	}
	
	@Override
	public T getInstance() {
		T instance = this.instance;
		if (instance == null) {
			
			synchronized (this) {
				instance = this.instance;
				if (instance == null) {
					
					instance = factory.newInstance();
					initializer.init(instance);
					this.instance = instance;
				}
			}
		}
		return instance;
	}

	@Override
	public boolean freeInstance() {
		boolean released = false;
		T instance = this.instance;
		if (instance != null) {
			
			synchronized (this) {
				instance = this.instance;
				if (instance != null) {
					
					this.instance = null;
					initializer.destroy(instance);
					released = true;
				}
			}
		}
		
		return released;
	}

	@Override
	public Future init(ExecutorService executor) {
		return executor.submit(new Callable() {

			@Override
			public T call() throws Exception {
				return getInstance();
			}
		});
	}

	@Override
	public Future destroy(ExecutorService executor) {
		return executor.submit(new Callable() {

			@Override
			public Boolean call() throws Exception {
				return freeInstance();
			}
		});
	}
	
	private void writeObject(ObjectOutputStream stream) throws IOException {
		stream.defaultWriteObject();
		synchronized (this) {
			if (instance instanceof Serializable) {
				stream.writeObject(instance);
			} else {
				stream.writeObject(null);
			}
		}
	}

	private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
		stream.defaultReadObject();
		Object obj = stream.readObject();
		synchronized (this) {
			if (obj != null) {
				this.instance = getInstanceType().cast(obj);
			}
		}
	}
	
	
	private static class FactoryAdapter> implements IPojoFactory, IPojoInitializer {
		/**
		 * 
		 */
		private static final long serialVersionUID = -3988519477717092909L;
		
		private final ILazyPojo lazyFactory;
		private final Class beanClass;

		public FactoryAdapter(Class beanClass, Class factoryClass, IPojoInitializer factoryInitializer) {
			IPojoFactory factoryFactory = PojoFactory.create(factoryClass);
			this.lazyFactory = new LazyPojo<>(factoryFactory, factoryInitializer);
			this.beanClass = beanClass;
		}


		@Override
		public T newInstance() {
			return lazyFactory.getInstance().newInstance();
		}

		@Override
		public Class getType() {
			return beanClass;
		}


		@Override
		public void init(T instance) {
			//nothing to do, here is already late
		}
		
		@Override
		public void destroy(T instance) {
			//destroying of bean is being handled by the factory
			//the factory is not re-used but re-created for each object
			lazyFactory.freeInstance();
		}

	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy