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

com.github.mjeanroy.spring.mappers.objects.AbstractObjectMapper Maven / Gradle / Ivy

/**
 * The MIT License (MIT)
 *
 * Copyright (c) 2014 
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package com.github.mjeanroy.spring.mappers.objects;

import com.github.mjeanroy.spring.mappers.Mapper;
import com.github.mjeanroy.spring.mappers.commons.ClassUtils;
import com.github.mjeanroy.spring.mappers.factory.ObjectFactory;
import com.github.mjeanroy.spring.mappers.iterables.Iterables;
import com.github.mjeanroy.spring.mappers.iterables.LazyUnmodifiableCollectionMapper;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.github.mjeanroy.spring.mappers.commons.PreConditions.notNull;

/**
 * Simple abstraction that defines commons methods to object mapper implementations.
 * These mappers offers class level type checking with generic and can be used to
 * map iterables source objects.
 *
 * @param  Type of source objects.
 * @param  Type of destination objects.
 */
public abstract class AbstractObjectMapper implements ObjectMapper {

	/**
	 * Mapper that will be used internally to map source object
	 * to destination object.
	 */
	protected final Mapper mapper;

	/**
	 * Class of source objects.
	 */
	protected final Class klassT;

	/**
	 * Class of destination objects.
	 */
	protected final Class klassU;

	/**
	 * Factory used to instantiate destination objects.
	 */
	protected final ObjectFactory factory;

	/**
	 * Create new mapper.
	 * Generic types will be detected at object creation.
	 *
	 * @param mapper Mapper used to map source to destination.
	 */
	@SuppressWarnings("unchecked")
	protected AbstractObjectMapper(Mapper mapper) {
		this.mapper = notNull(mapper, "Mapper must not be null");
		this.klassT = (Class) ClassUtils.getGenericType(getClass(), 0);
		this.klassU = (Class) ClassUtils.getGenericType(getClass(), 1);
		this.factory = null;
	}

	/**
	 * Create new mapper.
	 *
	 * @param mapper Mapper used to map source to destination.
	 * @param klassT Source type.
	 * @param klassU Destination type.
	 */
	protected AbstractObjectMapper(Mapper mapper, Class klassT, Class klassU) {
		this.mapper = notNull(mapper, "Mapper must not be null");
		this.klassT = notNull(klassT, "Class T must bot be null");
		this.klassU = notNull(klassU, "Class U must bot be null");
		this.factory = null;
	}

	/**
	 * Create new mapper.
	 *
	 * @param mapper Mapper used to map source to destination.
	 * @param klassT Source type.
	 * @param klassU Destination type.
	 * @param factory Factory used to instantiate destination object.
	 */
	protected AbstractObjectMapper(Mapper mapper, Class klassT, Class klassU, ObjectFactory factory) {
		this.mapper = notNull(mapper, "Mapper must not be null");
		this.klassT = notNull(klassT, "Class T must bot be null");
		this.klassU = notNull(klassU, "Class U must bot be null");
		this.factory = notNull(factory, "Factory must bot be null");
	}

	@Override
	public U from(T source) {
		return source == null ? null : convert(source);
	}

	@Override
	public U convert(T source) {
		if (factory != null) {
			return mapper.map(source, factory);
		} else {
			return mapper.map(source, klassU);
		}
	}

	@Override
	public Iterable from(Iterable sources) {
		// Copy to list implementation, this is not a real lazy implementation since
		// original list must be copied in memory even if it is not already a collection
		// If original sources elements is already a collection, this is not really
		// important, since it is already in memory !
		List list = Iterables.toList(sources);
		return new LazyUnmodifiableCollectionMapper(list, this);
	}

	@Override
	public  Map from(Map sources) {
		Map map = buildDestinationMap(sources);
		for (Map.Entry entry : sources.entrySet()) {
			U destination = from(entry.getValue());
			map.put(entry.getKey(), destination);
		}
		return map;
	}

	/**
	 * Build destination map.
	 * Source map is used to build destination map (to get target
	 * size).
	 *
	 * This method can be overriden to build map in another way.
	 *
	 * @param sources Source map.
	 * @param  Type of key in map.
	 * @return Destination map (empty).
	 */
	protected  Map buildDestinationMap(Map sources) {
		return new HashMap(sources.size());
	}
}