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

com.github.nill14.utils.init.inject.PojoInjectionDescriptor Maven / Gradle / Ivy

The newest version!
package com.github.nill14.utils.init.inject;

import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.Set;
import java.util.stream.Stream;

import com.github.nill14.utils.init.api.IBeanDescriptor;
import com.github.nill14.utils.init.api.IParameterType;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.reflect.TypeToken;


@SuppressWarnings("serial")
public class PojoInjectionDescriptor implements Serializable, IBeanDescriptor {

	
	private final ImmutableList fields;
	private final ImmutableList methods;
	private final ImmutableList constructors;

	private final TypeToken typeToken;
	private final Set> interfaces;

	@SuppressWarnings("unchecked")
	public PojoInjectionDescriptor(IParameterType parameterType) {
		this((TypeToken) TypeToken.of(parameterType.getGenericType()));
	}
	
	@SuppressWarnings("unchecked")
	public PojoInjectionDescriptor(Class pojoClazz) {
		this(TypeToken.of((Class) pojoClazz));
	}

	public PojoInjectionDescriptor(TypeToken typeToken) {
		Preconditions.checkNotNull(typeToken);
		this.typeToken = typeToken;
		interfaces = typeToken.getTypes().interfaces().rawTypes();
		
		fields = ImmutableList.copyOf(
				injectableFields(ReflectionUtils.getInstanceFields(typeToken), typeToken.getRawType()).iterator());
		
		methods = ImmutableList.copyOf(
				injectableMethods(ReflectionUtils.getInstanceMethods(typeToken), typeToken.getRawType()).iterator());
		
		constructors = ImmutableList.copyOf(
				injectableConstructors(Stream.of(typeToken.getRawType().getDeclaredConstructors())).iterator());
		
//		ImmutableList.Builder builder = ImmutableList.builder();
//		for (FieldInjectionDescriptor f : fields) {
//			builder.add(f.getParameterType());
//		}
//		for (MethodInjectionDescriptor m : methods) {
//			builder.addAll(m.getParameterTypes());
//		}
//		TODO gather optional and mandatory dependencies 
	}
	
	@Override
	public ImmutableList getFieldDescriptors() {
		return fields;
	}

	@Override
	public ImmutableList getMethodDescriptors() {
		return methods;
	}
	
	@Override
	public ImmutableList getConstructorDescriptors() {
		return constructors;
	}

	
	@Override
	public Set> getInterfaces() {
		return interfaces;
	}
	
	@Override
	public Set> getDeclaredTypes() {
		return typeToken.getTypes().rawTypes();
	}


	private Stream injectableConstructors(Stream> constructors) {
		return constructors.map(c -> {
			if (c.getParameterCount() == 0 
					|| c.isAnnotationPresent(javax.inject.Inject.class) 
					|| c.isAnnotationPresent(com.google.inject.Inject.class)) {
				return new ConstructorInjectionDescriptor(c);
			} 
			else return null;
		}).filter(x -> x != null);
	}	
	
	
	private Stream injectableMethods(Stream nonStaticMethods, Class declaringClass) {
		return nonStaticMethods.map(m -> {
			if (m.isAnnotationPresent(javax.inject.Inject.class) 
					|| m.isAnnotationPresent(com.google.inject.Inject.class)) {
				return new MethodInjectionDescriptor(m, declaringClass);
			} 
			else return null;
		}).filter(x -> x != null);
	}	

	private Stream injectableFields(Stream nonStaticFields, Class declaringClass) {
		return nonStaticFields.map(f -> {
			if (f.isAnnotationPresent(javax.inject.Inject.class) 
					|| f.isAnnotationPresent(com.google.inject.Inject.class)) {
				return new FieldInjectionDescriptor(f, declaringClass);
			} 
			else return null;
		}).filter(x -> x != null);
	}

	@SuppressWarnings("unchecked")
	@Override
	public Class getRawType() {
		return (Class) typeToken.getRawType();
	}
	
	@Override
	public Type getGenericType() {
		return typeToken.getType();
	}

	@Override
	public boolean canBeInstantiated() {
		Class clazz = typeToken.getRawType();
		return !clazz.isInterface() && !Modifier.isAbstract(clazz.getModifiers()) && !constructors.isEmpty();
	}	

	@Override
	public String toString() {
		return typeToken.toString();
	}
	
	private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
		throw new InvalidObjectException("Proxy required");
	}
	
    private Object writeReplace() {
        return new SerializableProxy(this);
    }
    
    private static class SerializableProxy implements Serializable {
    	private final TypeToken  token;

    	public SerializableProxy(PojoInjectionDescriptor pd) {
			this.token = pd.typeToken;
		}
    	
    	private Object readResolve() {
    		return new PojoInjectionDescriptor<>(token);
    	}
    }

	@Override
	public TypeToken getToken() {
		return typeToken;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((typeToken == null) ? 0 : typeToken.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		PojoInjectionDescriptor other = (PojoInjectionDescriptor) obj;
		if (typeToken == null) {
			if (other.typeToken != null)
				return false;
		} else if (!typeToken.equals(other.typeToken))
			return false;
		return true;
	}
	
	
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy