/*******************************************************************************
* Copyright (c) 2013 Rene Schneider, GEBIT Solutions GmbH and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package de.gebit.integrity.parameter.conversion;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Set;
import com.google.inject.Inject;
import de.gebit.integrity.operations.UnexecutableException;
import de.gebit.integrity.string.FormattedString;
import de.gebit.integrity.utils.ParameterUtil.UnresolvableVariableException;
/**
* A {@link Conversion} defines a transformation from one type into another.
*
* @param <FROM>
* the source type
* @param <TO>
* the target type
* @author Rene Schneider - initial API and implementation
*
*/
public abstract class Conversion<FROM extends Object, TO extends Object> {
/**
* The value converter used for recursive conversion.
*/
@Inject
private ValueConverter valueConverter;
/**
* This set is used for automatic endless loop protection.
*/
private Set<Object> visitedObjects;
/**
* Performs the conversion.
*
* @param aSource
* the source object to convert
* @param aTargetType
* TODO
* @param aConversionContext
* controls some conversion parameters and rules; may be null if the default {@link ConversionContext}
* values shall be used
* @return the converted object
* @throws ConversionFailedException
* in case of conversion errors
*/
public abstract TO convert(FROM aSource, Class<? extends TO> aTargetType, ConversionContext aConversionContext)
throws ConversionFailedException;
/**
* Add this annotation to a {@link Conversion} implementation to set the priority of this conversion. Priorities are
* used to determine the default conversion which is used if no target conversion is given and thus multiple
* conversions may be used. Highest priority wins. If none is given {@link Integer#MIN_VALUE} is assumed.
*
*
* @author Rene Schneider - initial API and implementation
*
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Priority {
/**
* The priority. Higher is more.
*/
int value() default Integer.MIN_VALUE;
}
public void setVisitedObjects(Set<Object> someVisitedObjects) {
visitedObjects = someVisitedObjects;
}
/**
* Recursively converts the given value to the defined target type. This method provides implicit protection against
* endless recursion loops.
*
* @param aTargetType
* the target type
* @param aParameterizedType
* the parameterized type in case of generics
* @param aValue
* the value to convert
* @param aConversionContext
* some parameters controlling the conversion (if null, a default context is used)
* @return the converted value
* @throws UnresolvableVariableException
* @throws ClassNotFoundException
* @throws UnexecutableException
* @throws InstantiationException
*/
protected Object convertValueRecursive(Class<?> aTargetType, Class<?> aParameterizedType, Object aValue,
ConversionContext aConversionContext) throws UnresolvableVariableException, ClassNotFoundException,
UnexecutableException, InstantiationException {
if ((valueConverter instanceof AbstractModularValueConverter) && visitedObjects != null) {
return ((AbstractModularValueConverter) valueConverter).convertValue(aTargetType, aParameterizedType,
aValue, aConversionContext, visitedObjects);
} else {
return valueConverter.convertValue(aTargetType, aParameterizedType, aValue, aConversionContext);
}
}
/**
* Recursively converts the given value to a string array. This method provides implicit protection against endless
* recursion loops.
*
* @param aValue
* the value to convert
* @param aConversionContext
* some parameters controlling the conversion (if null, a default context is used)
* @return the converted string array
*/
protected FormattedString[] convertValueToFormattedStringArrayRecursive(Object aValue,
ConversionContext aConversionContext) {
if ((valueConverter instanceof AbstractModularValueConverter) && visitedObjects != null) {
return ((AbstractModularValueConverter) valueConverter).convertValueToStringArray(aValue,
aConversionContext, visitedObjects);
} else {
return valueConverter.convertValueToFormattedStringArray(aValue, aConversionContext);
}
}
}