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

org.atemsource.atem.utility.transform.impl.EntityTypeTransformation Maven / Gradle / Ivy

/*******************************************************************************
 * Stefan Meyer, 2012 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 ******************************************************************************/
package org.atemsource.atem.utility.transform.impl;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.atemsource.atem.api.type.EntityType;
import org.atemsource.atem.api.type.Type;
import org.atemsource.atem.utility.transform.api.AttributeTransformation;
import org.atemsource.atem.utility.transform.api.JavaTransformation;
import org.atemsource.atem.utility.transform.api.Transformation;
import org.atemsource.atem.utility.transform.api.TransformationContext;
import org.atemsource.atem.utility.transform.api.UniTransformation;
import org.atemsource.atem.utility.transform.impl.builder.TransformationFinder;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;


@Component
@Scope("prototype")
public class EntityTypeTransformation implements Transformation
{
	private final List> embeddedTransformations =
		new ArrayList>();

	private EntityType entityTypeA;

	private EntityType entityTypeB;

	private TransformationFinder finder;

	private final List> javaTransformations = new ArrayList>();

	private final Set> subTransformations = new HashSet>();

	private EntityTypeTransformation superTransformation;

	private Transformation typeConverter;

	public void addSubTransformation(EntityTypeTransformation subTransformation)
	{
		this.subTransformations.add(subTransformation);
	}

	public void addTransformation(AttributeTransformation transformation)
	{
		this.embeddedTransformations.add(transformation);
	}

	public void addTransformation(JavaTransformation javaTransformation)
	{
		javaTransformations.add(javaTransformation);
	}

	private A createA(B b, TransformationContext ctx)
	{
		if (b == null)
		{
			return null;
		}
		if (ctx.isTransformed(b))
		{
			return (A) ctx.getTransformed(b);
		}
		else
		{
			A valueA = getTypeConverter().getBA().convert(b, ctx);
			ctx.transformed(b, valueA);
			transformBAChildren(b, valueA, ctx);
			return valueA;
		}
	}

	private B createB(A a, TransformationContext ctx)
	{
		if (a == null)
		{
			return null;
		}
		if (ctx.isTransformed(a))
		{
			return (B) ctx.getTransformed(a);
		}
		else
		{
			B valueB = getTypeConverter().getAB().convert(a, ctx);
			ctx.transformed(a, valueB);
			transformABChildren(a, valueB, ctx);
			return valueB;
		}
	}

	@Override
	public UniTransformation getAB()
	{
		return new UniTransformation()
		{

			@Override
			public B convert(A a, TransformationContext ctx)
			{

				if (a == null)
				{
					return null;
				}
				EntityType entityType = ctx.getEntityTypeByA(a);
				if (finder != null)
				{

					UniTransformation ab = finder.getAB(a, ctx);
					if (ab != null)
					{
						return ab.convert(a, ctx);
					}
				}
				EntityTypeTransformation transformationByTypeA = getTransformationByTypeA(entityType);
				if (transformationByTypeA == null)
				{
					throw new IllegalStateException("cannot find transformation for " + entityType.getCode());
				}
				return transformationByTypeA.createB(a, ctx);
			}

			@Override
			public Type getSourceType()
			{
				return entityTypeA;
			}

			@Override
			public Type getTargetType()
			{
				return entityTypeB;
			}

			@Override
			public B merge(A a, B b, TransformationContext ctx)
			{
				EntityType entityType = ctx.getEntityTypeByA(a);
				if (finder != null)
				{
					UniTransformation ab = finder.getAB(a, ctx);
					if (ab != null)
					{
						return ab.merge(a, b, ctx);
					}
				}
				EntityTypeTransformation transformation = getTransformationByTypeA(entityType);
				if (transformation != null)
				{
					transformation.transformABChildren(a, b, ctx);
				}
				else
				{
					throw new IllegalStateException("cannot find transformation for " + entityType.getCode());
				}
				return b;
			}

			@Override
			public Type getTargetType(Type sourceType) {
				return getTypeB(sourceType);
			}
		};
	}

	protected Type getTypeB(Type sourceType) {
		return getTransformationByTypeA((EntityType) sourceType).getEntityTypeB();
	}
	protected Type getTypeA(Type sourceType) {
		return getTransformationByTypeB((EntityType) sourceType).getEntityTypeA();
	}

	@Override
	public UniTransformation getBA()
	{
		return new UniTransformation()
		{

			@Override
			public A convert(B b, TransformationContext ctx)
			{

				EntityType entityType = ctx.getEntityTypeByB(b);
				if (entityType == null)
				{
					entityType = entityTypeB;
				}
				if (finder != null)
				{
					UniTransformation ba = finder.getBA(b, ctx);
					if (ba != null)
					{
						return ba.convert(b, ctx);
					}
				}
				return getTransformationByTypeB(entityType).createA(b, ctx);
			}

			@Override
			public Type getSourceType()
			{
				return entityTypeB;
			}

			@Override
			public Type getTargetType()
			{
				return entityTypeA;
			}

			@Override
			public A merge(B b, A a, TransformationContext ctx)
			{
				EntityType entityType = ctx.getEntityTypeByB(b);
				if (entityType == null)
				{
					entityType = entityTypeB;
				}
				if (finder != null)
				{
					UniTransformation ba = finder.getBA(b, ctx);
					if (ba != null)
					{
						return ba.merge(b, a, ctx);
					}
				}
				getTransformationByTypeB(entityType).transformBAChildren(b, a, ctx);

				return a;
			}

			@Override
			public Type getTargetType(Type sourceType) {
				return getTypeA(sourceType);
			}

		};
	}

	private EntityTypeTransformation getBySubtypesA(EntityType entityType)
	{
		if (entityType.equals(getEntityTypeA()))
		{
			return this;
		}
		EntityTypeTransformation transformation = null;
		for (EntityTypeTransformation subTransformation : subTransformations)
		{
			EntityTypeTransformation otherTransformation = subTransformation.getBySubtypesA(entityType);
			if (otherTransformation != null)
			{
				if (transformation != null)
				{
					throw new IllegalStateException("there are two transformations for the same type");
				}
				else
				{
					transformation = otherTransformation;
				}
			}

		}
		return transformation;
	}

	private EntityTypeTransformation getBySubtypesB(EntityType entityType)
	{
		if (entityType.equals(getEntityTypeB()))
		{
			return this;
		}
		else if (!getEntityTypeB().isAssignableFrom(entityType))
		{
			return null;
		}
		EntityTypeTransformation transformation = null;
		for (EntityTypeTransformation subTransformation : subTransformations)
		{
			EntityTypeTransformation otherTransformation = subTransformation.getBySubtypesB(entityType);
			if (otherTransformation != null)
			{
				if (transformation != null)
				{
					throw new IllegalStateException("there are two transformations for the same type");
				}
				else
				{
					transformation = otherTransformation;
				}
			}

		}
		if (transformation != null)
		{
			return transformation;
		}
		else
		{
			return this;
		}
	}

	public EntityType getEntityTypeA()
	{
		return entityTypeA;
	}

	public EntityType getEntityTypeB()
	{
		return entityTypeB;
	}

	public EntityTypeTransformation getSuperTransformation()
	{
		return superTransformation;
	}

	protected EntityTypeTransformation getTransformationByTypeA(EntityType entityType)
	{

		if (entityType.equals(getEntityTypeA()))
		{
			return this;
		}
		else if (entityType.isAssignableFrom(getEntityTypeA()))
		{
			EntityTypeTransformation transformation = superTransformation.getTransformationByTypeA(entityType);
			if (transformation == null)
			{
				return this;
			}
			else
			{
				return transformation;
			}
		}
		else if (getEntityTypeA().isAssignableFrom(entityType))
		{
			EntityTypeTransformation transformation = getBySubtypesA(entityType);
			if (transformation == null)
			{
				return this;
			}
			else
			{
				return transformation;
			}
		}
		return this;
	}

	protected EntityTypeTransformation getTransformationByTypeB(EntityType entityType)
	{

		if (entityType.equals(getEntityTypeB()))
		{
			return this;
		}
		else if (entityType.isAssignableFrom(getEntityTypeB()))
		{
			return superTransformation.getTransformationByTypeB(entityType);
		}
		else
		{
			return getBySubtypesB(entityType);
		}
	}

	@Override
	public Type getTypeA()
	{
		return getEntityTypeA();
	}

	@Override
	public Type getTypeB()
	{
		return getEntityTypeB();
	}

	public Transformation getTypeConverter()
	{
		return typeConverter;
	}

	public void setEntityTypeA(EntityType entityTypeA)
	{
		this.entityTypeA = entityTypeA;
	}

	public void setEntityTypeB(EntityType entityTypeB)
	{
		this.entityTypeB = entityTypeB;
	}

	public void setFinder(TransformationFinder finder)
	{
		this.finder = finder;
	}

	public void setSuperTransformation(EntityTypeTransformation superTransformation)
	{
		this.superTransformation = superTransformation;

	}

	public void setTypeConverter(Transformation typeConverter)
	{
		this.typeConverter = typeConverter;
	}

	protected void transformABChildren(A valueA, B valueB, TransformationContext ctx)
	{
		if (superTransformation != null)
		{
			superTransformation.transformABChildren(valueA, valueB, ctx);
		}
		for (JavaTransformation transformation : javaTransformations)
		{
			transformation.mergeAB(valueA, valueB, ctx);
		}
		for (AttributeTransformation transformation : embeddedTransformations)
		{
			transformation.mergeAB(valueA, valueB, ctx);
		}
	}

	protected void transformBAChildren(B valueB, A valueA, TransformationContext ctx)
	{
		if (superTransformation != null)
		{
			superTransformation.transformBAChildren(valueB, valueA, ctx);
		}
		for (JavaTransformation transformation : javaTransformations)
		{
			transformation.mergeBA(valueB, valueA, ctx);
		}
		for (AttributeTransformation transformation : embeddedTransformations)
		{
			transformation.mergeBA(valueB, valueA, ctx);
		}
	}

}