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

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

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;
import com.github.nill14.utils.init.api.IPropertyResolver;
import com.github.nill14.utils.init.inject.ReflectionUtils;
import com.google.common.reflect.TypeToken;

@SuppressWarnings("serial")
public final class LazyPojo implements ILazyPojo, Provider {

	
	public static  ILazyPojo forSingleton(T singleton) {
		return forSingleton(singleton, IPropertyResolver.empty());
	}
	
	public static  ILazyPojo forSingleton(T singleton, IPropertyResolver resolver) {
		IPojoFactory pojoFactory = PojoProviderFactory.singleton(singleton, resolver);
		return new LazyPojo(pojoFactory, IPojoInitializer.empty());
	}
	
	public static  ILazyPojo forBean(Class beanClass) {
		return forBean(beanClass, IPropertyResolver.empty(), IPojoInitializer.empty());
	}
	
	public static  ILazyPojo forBean(Class beanClass, IPropertyResolver resolver, IPojoInitializer initializer) {
		IPojoFactory factory = new PojoInjectionFactory<>(TypeToken.of(beanClass), resolver);
		return new LazyPojo<>(factory, initializer);
	}
	
	public static > ILazyPojo forProvider(Class providerClass) {
		return forProvider(providerClass, IPropertyResolver.empty(), IPojoInitializer.empty());
	}
	
	public static > ILazyPojo forProvider(
			Class providerClass, IPropertyResolver resolver, IPojoInitializer factoryInitializer) {
		TypeToken typeToken = ReflectionUtils.getProviderReturnTypeToken(providerClass);
		IPojoFactory pojoFactory = new PojoInjectionFactory<>(TypeToken.of(providerClass), resolver);
		PojoFactoryAdapter factoryAdapter = new PojoFactoryAdapter(pojoFactory, typeToken, factoryInitializer);
		return new LazyPojo<>(factoryAdapter, factoryAdapter);
	}
	
	public static  ILazyPojo forProvider(
			Provider provider, IPropertyResolver resolver, IPojoInitializer initializer) {
		IPojoFactory pojoFactory = new PojoProviderFactory<>(provider, resolver);
		return new LazyPojo<>(pojoFactory, initializer);
	}
	
	public static  ILazyPojo forFactory(
			IPojoFactory pojoFactory, IPojoInitializer initializer) {
		return new LazyPojo<>(pojoFactory, initializer);
	}
	
	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 TypeToken getType() {
		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(this, factory, 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(this, factory, 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);
			}
		}
	}

	@SuppressWarnings("unchecked")
	private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
		stream.defaultReadObject();
		Object obj = stream.readObject();
		synchronized (this) {
			if (obj != null) {
				this.instance = (T) obj;
			}
		}
	}
	
	@Override
	public String toString() {
		return String.format("%s(%s)@%s", 
				getClass().getSimpleName(), 
				factory.getType().toString(), 
				Integer.toHexString(System.identityHashCode(this)));
	}
	


}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy