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

org.unidal.converter.ConverterRegistry Maven / Gradle / Ivy

The newest version!
package org.unidal.converter;

import java.lang.reflect.Array;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ConverterRegistry {
	private Map, ConverterEntry> m_converterMap = new HashMap, ConverterEntry>();

	// Interface or abstract class to concrete class mapping
	private Map, Class> m_typeMap = new HashMap, Class>();

	public Converter findConverter(Type fromType, Type targetType) {
		boolean isClass = targetType instanceof Class;
		Class fromClass = TypeUtil.getRawType(fromType);
		Class targetClass = TypeUtil.getRawType(targetType);

		// Is a primitive type? convert it to wrapper type
		if (isClass && targetClass.isPrimitive()) {
			targetClass = TypeUtil.getWrapClass(targetClass);
			targetType = targetClass;
		}

		ConverterEntry entry = m_converterMap.get(targetClass);
		Converter c = (entry == null ? null : entry.getCacheConverter(fromClass));

		if (c != null) {
			return c;
		} else if (isClass && targetClass.isArray()) {
			// is Array type?
			c = getConverter(fromType, targetType, Array.class);
		} else {
			// try specific converter
			c = getConverter(fromType, targetType, targetClass);

			if (c == null) {
				// try generic one
				c = getConverter(fromType, targetType, Type.class);
			}
		}

		if (c != null) {
			if (entry == null) {
				synchronized (m_converterMap) {
					entry = new ConverterEntry();
					m_converterMap.put(targetClass, entry);
				}
			}

			entry.putCacheConverter(fromClass, c);

			return c;
		} else {
			throw new ConverterException("No registered converter found to convert from " + fromType + " to " + targetType);
		}
	}

	public Class findType(Class fromClass) {
		Class toClass = m_typeMap.get(fromClass);

		if (toClass != null) {
			return toClass;
		} else {
			return fromClass;
		}
	}

	private Converter getConverter(Type fromType, Type targetType, Class targetClass) {
		Class current = targetClass;

		while (true) {
			ConverterEntry entry = m_converterMap.get(current);

			if (entry != null) {
				List> converters = entry.getConverters();

				for (Converter c : converters) {
					if (c.canConvert(fromType, targetType)) {
						return c;
					}
				}
			}

			current = current.getSuperclass();

			if (current == null || current == Object.class) {
				break;
			}
		}

		return null;
	}

	public void registerConverter(Converter converter) {
		registerConverter(converter, ConverterPriority.NORMAL.getValue());
	}

	public void registerConverter(Converter converter, int priority) {
		Type targetType = converter.getTargetType();
		Class targetClass = TypeUtil.getRawType(targetType);
		ConverterEntry entry = m_converterMap.get(targetClass);

		if (entry == null) {
			synchronized (m_converterMap) {
				entry = m_converterMap.get(targetClass);

				if (entry == null) {
					entry = new ConverterEntry();
					m_converterMap.put(targetClass, entry);
				}
			}
		}

		entry.addConverter(converter, priority);
	}

	public void registerType(Class fromClass, Class toClass) {
		Class oldClass = m_typeMap.put(fromClass, toClass);

		if (oldClass != null) {
			throw new IllegalStateException("Can't map to same " + fromClass + " from " + oldClass + " and " + toClass);
		}
	}

	private static class ConverterEntry {
		// list of converters that support converting to the target class
		private List> m_converters;

		// list of priorities for the converters
		private List m_priorities;

		// cache map from fromClass to Converter
		private Map, Converter> m_cacheMap;

		public ConverterEntry() {
			m_converters = new ArrayList>();
			m_priorities = new ArrayList();
			m_cacheMap = new HashMap, Converter>();
		}

		public void addConverter(Converter converter, int priority) {
			if (!m_converters.contains(converter)) {
				int size = m_priorities.size();
				int index = size;

				for (int i = 0; i < size; i++) {
					if (priority > m_priorities.get(i)) {
						index = i;
						break;
					}
				}

				m_priorities.add(index, priority);
				m_converters.add(index, converter);
			} else {
				System.out.println("Converter already registered: " + converter);
			}
		}

		public Converter getCacheConverter(Class fromClass) {
			return m_cacheMap.get(fromClass);
		}

		public List> getConverters() {
			return m_converters;
		}

		public void putCacheConverter(Class fromClass, Converter converter) {
			m_cacheMap.put(fromClass, converter);
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy