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

se.l4.commons.serialization.internal.reflection.FactoryDefinition Maven / Gradle / Ivy

The newest version!
package se.l4.commons.serialization.internal.reflection;

import java.beans.ConstructorProperties;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import com.fasterxml.classmate.ResolvedType;
import com.fasterxml.classmate.members.ResolvedConstructor;
import com.google.common.base.Defaults;
import com.google.common.base.MoreObjects;
import com.google.common.primitives.Primitives;

import se.l4.commons.serialization.Expose;
import se.l4.commons.serialization.Factory;
import se.l4.commons.serialization.SerializationException;
import se.l4.commons.serialization.SerializerCollection;

/**
 * Factory that can be used to create an instance of a certain object.
 *
 * @author Andreas Holstenson
 *
 */
public class FactoryDefinition
{
	private final SerializerCollection collection;
	final Argument[] arguments;
	private final boolean hasSerializedFields;
	private final boolean isInjectable;
	private final Constructor raw;

	public FactoryDefinition(SerializerCollection collection,
			Map fields,
			Map nonRenamed,
			ResolvedConstructor constructor)
	{
		this.collection = collection;

		List args = new ArrayList<>();

		raw = constructor.getRawMember();

		ConstructorProperties cp = raw.getAnnotation(ConstructorProperties.class);
		String[] names = cp == null ? null : cp.value();

		Annotation[][] annotations = raw.getParameterAnnotations();

		boolean hasSerializedFields = false;

		for(int i=0, n=constructor.getArgumentCount(); i data)
	{
		if(! hasSerializedFields)
		{
			return 0;
		}

		int score = 0;

		for(Argument arg : arguments)
		{
			if(arg instanceof FactoryDefinition.SerializedArgument)
			{
				if(data.containsKey(((SerializedArgument) arg).name))
				{
					score++;
				}
			}
		}

		return score;
	}

	/**
	 * Create a new instance using the given deserialized data. The data
	 * is only used if this factory has any serialized fields.
	 *
	 * @param data
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public T create(Map data)
	{
		Object[] args = new Object[arguments.length];
		for(int i=0, n=args.length; i data);
	}

	class SerializedArgument
		implements Argument
	{
		final Class type;
		final String name;

		public SerializedArgument(Class type, String name)
		{
			this.type = type;
			this.name = name;
		}

		@Override
		public Object getValue(Map data)
		{
			Object value = data.get(name);
			if(value == null && type.isPrimitive())
			{
				return Defaults.defaultValue(type);
			}

			return value;
		}
	}

	private class InjectedArgument
		implements Argument
	{
		private final Class type;
		private final Annotation[] annotations;

		public InjectedArgument(Class type, Annotation[] annotations)
		{
			this.type = type;
			this.annotations = annotations;
		}

		@Override
		public Object getValue(Map data)
		{
			return collection.getInstanceFactory()
				.create(type, annotations);
		}
	}

	@Override
	public String toString()
	{
		return MoreObjects.toStringHelper(this)
			.add("constructor", raw)
			.toString();
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy