org.springframework.ldap.odm.typeconversion.impl.ConverterManagerImpl Maven / Gradle / Ivy
/*
* Copyright 2005-2013 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
*
* https://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.springframework.ldap.odm.typeconversion.impl;
import java.util.HashMap;
import java.util.Map;
import org.springframework.ldap.odm.typeconversion.ConverterException;
import org.springframework.ldap.odm.typeconversion.ConverterManager;
/**
* An implementation of
* {@link org.springframework.ldap.odm.typeconversion.ConverterManager}.
*
* The algorithm used is to:
*
* - Try to find and use a {@link Converter} registered for the
fromClass
,
* syntax
and toClass
and use it.
* - If this fails, then if the
toClass isAssignableFrom
the
* fromClass
then just assign it.
* - If this fails try to find and use a {@link Converter} registered for the
*
fromClass
and the toClass
ignoring the
* syntax
.
* - If this fails then throw a
* {@link org.springframework.ldap.odm.typeconversion.ConverterException}.
*
*
* @author Paul Harvey <paul.at.pauls-place.me.uk>
*/
public final class ConverterManagerImpl implements ConverterManager {
/**
* Separator used to form keys into the converters Map.
*/
private static final String KEY_SEP = ":";
/**
* Map of keys created via makeConverterKey to Converter instances.
*/
private final Map converters = new HashMap();
/**
* Make a key into the converters map - the keys is formed from the
* fromClass
, syntax and toClass
* @param fromClass The class to convert from.
* @param syntax The LDAP syntax.
* @param toClass The class to convert to.
* @return key
*/
private String makeConverterKey(Class fromClass, String syntax, Class toClass) {
StringBuilder key = new StringBuilder();
if (syntax == null) {
syntax = "";
}
key.append(fromClass.getName()).append(KEY_SEP).append(syntax).append(KEY_SEP).append(toClass.getName());
return key.toString();
}
/**
* Create an empty ConverterManagerImpl
*/
public ConverterManagerImpl() {
}
/**
* Used to help in the process of dealing with primitive types by mapping them to
* their equivalent boxed class.
*/
private static Map, Class> primitiveTypeMap = new HashMap, Class>();
static {
primitiveTypeMap.put(Byte.TYPE, Byte.class);
primitiveTypeMap.put(Short.TYPE, Short.class);
primitiveTypeMap.put(Integer.TYPE, Integer.class);
primitiveTypeMap.put(Long.TYPE, Long.class);
primitiveTypeMap.put(Float.TYPE, Float.class);
primitiveTypeMap.put(Double.TYPE, Double.class);
primitiveTypeMap.put(Boolean.TYPE, Boolean.class);
primitiveTypeMap.put(Character.TYPE, Character.class);
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.ldap.odm.typeconversion.ConverterManager#canConvert(java.lang.
* Class, java.lang.String, java.lang.Class)
*/
public boolean canConvert(Class fromClass, String syntax, Class toClass) {
Class fixedToClass = toClass;
if (toClass.isPrimitive()) {
fixedToClass = primitiveTypeMap.get(toClass);
}
Class fixedFromClass = fromClass;
if (fromClass.isPrimitive()) {
fixedFromClass = primitiveTypeMap.get(fromClass);
}
return fixedToClass.isAssignableFrom(fixedFromClass)
|| (this.converters.get(makeConverterKey(fixedFromClass, syntax, fixedToClass)) != null)
|| (this.converters.get(makeConverterKey(fixedFromClass, null, fixedToClass)) != null);
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.ldap.odm.typeconversion.ConverterManager#convert(java.lang.
* Object, java.lang.String, java.lang.Class)
*/
@SuppressWarnings("unchecked")
public T convert(Object source, String syntax, Class toClass) {
Object result = null;
// What are we converting form
Class fromClass = source.getClass();
// Deal with primitives
Class targetClass = toClass;
if (toClass.isPrimitive()) {
targetClass = primitiveTypeMap.get(toClass);
}
// Try to convert with any syntax we have been given
Converter syntaxConverter = this.converters.get(makeConverterKey(fromClass, syntax, targetClass));
if (syntaxConverter != null) {
try {
result = syntaxConverter.convert(source, targetClass);
}
catch (Exception ex) {
// Ignore as we may still be able to convert successfully
}
}
// Do we actually need to do any conversion?
if (result == null && targetClass.isAssignableFrom(fromClass)) {
result = source;
}
// If we were given a syntax and we failed to convert drop back to any mapping
// that will work from class -> to class
if (result == null && syntax != null) {
Converter nullSyntaxConverter = this.converters.get(makeConverterKey(fromClass, null, targetClass));
if (nullSyntaxConverter != null) {
try {
result = nullSyntaxConverter.convert(source, targetClass);
}
catch (Exception ex) {
// Handled at the end of the method
}
}
}
if (result == null) {
throw new ConverterException(
String.format("Cannot convert %1$s of class %2$s via syntax %3$s to class %4$s", source,
source.getClass(), syntax, toClass));
}
// We cannot do the safe thing of doing a .cast as we need to rely on
// auto-unboxing to deal with primitives!
return (T) result;
}
/**
* Add a {@link Converter} to this ConverterManager
.
* @param fromClass The class the Converter
should be used to convert
* from.
* @param syntax The LDAP syntax that the Converter
should be used for.
* @param toClass The class the Converter
should be used to convert to.
* @param converter The Converter
to add.
*/
public void addConverter(Class fromClass, String syntax, Class toClass, Converter converter) {
this.converters.put(makeConverterKey(fromClass, syntax, toClass), converter);
}
}