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

net.projectmonkey.object.mapper.construction.RootPopulationContext Maven / Gradle / Ivy

Go to download

Object mapping implementation written as an alternative to modelmapper which is able to support inheritance, handles flattening / expanding in a precise way, and is extensible / configurable

The newest version!
package net.projectmonkey.object.mapper.construction;

import net.projectmonkey.object.mapper.annotations.group.Group;
import net.projectmonkey.object.mapper.util.TypeResolver;
import net.projectmonkey.object.mapper.analysis.cache.TypePair;
import net.projectmonkey.object.mapper.analysis.result.PropertyConfiguration;
import net.projectmonkey.object.mapper.analysis.result.PropertyPathElement;
import net.projectmonkey.object.mapper.annotations.group.Groups;
import net.projectmonkey.object.mapper.util.Types;

import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.*;

/*
 *
 *  * Copyright 2012 the original author or authors.
 *  *
 *  * 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.
 *
 */

/**
 * @author Andy Moody
 */
public class RootPopulationContext implements PopulationContext
{
	private final TypePair types;
	private final SourceType source;
	private DestinationType destination;
	private RootPropertyPathElement sourcePathElement;
	private RootPropertyPathElement destinationPathElement;
	private Map, Class> destinationTypeArguments;

	public RootPopulationContext(final SourceType source, Class destinationType)
	{
		Class sourceType = (Class) Types.deProxy(source.getClass()); //this is safe since it will never be constructed with a null source
		this.types = TypePair.of(sourceType, destinationType);
		this.source = source;
		this.sourcePathElement = new RootPropertyPathElement(types.getSourceType());
		this.destinationPathElement = new RootPropertyPathElement(types.getDestinationType());
		destinationTypeArguments = new HashMap, Class>();
	}

	@Override
	public SourceType getSource()
	{
		return source;
	}

	@Override
	public DestinationType getDestination()
	{
		return destination;
	}

	@Override
	public Class getDestinationType(){
		return types.getDestinationType();
	}

	@Override
	public Class getSourceType(){
		return types.getSourceType();
	}

	@Override
	public Class getParentSourceType()
	{
		return null;
	}

	@Override
	public Class getParentDestinationType()
	{
		return null;
	}

	@Override
	public Object getParentDestination()
	{
		return null;
	}

	@Override
	public Object getParentSource()
	{
		return null;
	}

	@Override
	public PropertyConfiguration getSourceConfiguration(final Class group)
	{
		return sourcePathElement.getConfigurationForGroup(group);
	}

	@Override
	public PropertyConfiguration getDestinationConfiguration(final Class group)
	{
		return destinationPathElement.getConfigurationForGroup(group);
	}

	@Override
	public Type getDestinationGenericType()
	{
		return getDestinationType();
	}

	@Override
	public void setDestination(final DestinationType destination)
	{
		this.destination = destination;
	}

	@Override
	public PropertyPathElement getSourceProperty()
	{
		return sourcePathElement;
	}

	@Override
	public PropertyPathElement getDestinationProperty()
	{
		return destinationPathElement;
	}

	@Override
	public void addDestinationTypeArguments(final Map, Class> destinationTypesByVariable)
	{
		for (TypeVariable typeVariable : destinationTypesByVariable.keySet())
		{
			if(!this.destinationTypeArguments.containsKey(typeVariable))
			{
				this.destinationTypeArguments.put(typeVariable, destinationTypesByVariable.get(typeVariable));
			}
		}
	}

	public Map, Class> getDestinationTypeArguments()
	{
		return destinationTypeArguments;
	}

	private static class RootPropertyPathElement extends PropertyPathElement
	{
		
		private Class type;

		private RootPropertyPathElement(final Class type)
		{
			super(type.getSimpleName(), calculateGroupsForType(type));
			this.type = type;
		}

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

		@Override
		public Type getGenericType()
		{
			return TypeResolver.Unknown.class;
		}

		@Override
		public Object getValue(final Object source)
		{
			return source;
		}

		@Override
		public void setValue(final Object value, final Object destination)
		{
			//do nothing.
		}

		@Override
		public boolean equals(final Object o)
		{
			if (this == o)
			{
				return true;
			}
			if (o == null || getClass() != o.getClass())
			{
				return false;
			}

			RootPropertyPathElement that = (RootPropertyPathElement) o;

			if (type != null ? !type.equals(that.type) : that.type != null)
			{
				return false;
			}

			return true;
		}

		@Override
		public int hashCode()
		{
			return type != null ? type.hashCode() : 0;
		}

		protected static Map,PropertyConfiguration> calculateGroupsForType(final Class clazz)
		{
			Map, PropertyConfiguration> toReturn = new HashMap, PropertyConfiguration>();
			List groups = new ArrayList();
			if(clazz.isAnnotationPresent(Groups.class))
			{
				groups.addAll(Arrays.asList(clazz.getAnnotation(Groups.class).value()));
			}
			if(clazz.isAnnotationPresent(Group.class))
			{
				groups.add(clazz.getAnnotation(Group.class));
			}

			for (Group group : groups)
			{
				toReturn.put(group.value(), new PropertyConfiguration(group));
			}

			return toReturn;
		}

	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy