Skip to content

Commit

Permalink
Merge branch 'v0.15.x_bugfix' into v0.15.x
Browse files Browse the repository at this point in the history
  • Loading branch information
S1artie committed Jul 8, 2016
2 parents 041c15e + c485d71 commit 39101f6
Show file tree
Hide file tree
Showing 16 changed files with 650 additions and 106 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
package de.gebit.integrity.parameter.conversion;

import java.lang.reflect.Array;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
Expand Down Expand Up @@ -174,8 +175,8 @@ public Object convertValue(Class<?> aTargetType, Class<?> aParameterizedType, Ob
* @throws InstantiationException
*/
public Object convertValue(Class<?> aTargetType, Class<?> aParameterizedType, Object aValue,
ConversionContext aConversionContext, Set<Object> someVisitedObjects) throws UnresolvableVariableException,
UnexecutableException {
ConversionContext aConversionContext, Set<Object> someVisitedObjects)
throws UnresolvableVariableException, UnexecutableException {
ConversionContext tempConversionContext = safeguardConversionContext(aConversionContext);

if (someVisitedObjects.contains(aValue)) {
Expand All @@ -194,8 +195,8 @@ public Object convertValue(Class<?> aTargetType, Class<?> aParameterizedType, Ob
return convertEncapsulatedConstantValueToTargetType(aTargetType, aParameterizedType,
(ConstantValue) aValue, tempConversionContext, someVisitedObjects);
} else {
return convertPlainValueToTargetType(aTargetType, aParameterizedType, aValue,
tempConversionContext, someVisitedObjects);
return convertPlainValueToTargetType(aTargetType, aParameterizedType, aValue, tempConversionContext,
someVisitedObjects);
}
} finally {
someVisitedObjects.remove(aValue);
Expand Down Expand Up @@ -253,20 +254,14 @@ protected Object convertPlainValueToTargetType(Class<?> aTargetType, Class<?> aP
// both are arrays
tempResultArray = Array.newInstance(tempActualParamType, Array.getLength(aValue));
for (int i = 0; i < Array.getLength(aValue); i++) {
Array.set(
tempResultArray,
i,
convertPlainValueToTargetType(tempActualParamType, aParameterizedType,
Array.get(aValue, i), aConversionContext, someVisitedValues));
Array.set(tempResultArray, i, convertPlainValueToTargetType(tempActualParamType, aParameterizedType,
Array.get(aValue, i), aConversionContext, someVisitedValues));
}
} else {
// target is an array, but value is a single value
tempResultArray = Array.newInstance(tempActualParamType, 1);
Array.set(
tempResultArray,
0,
convertPlainValueToTargetType(tempActualParamType, aParameterizedType, aValue,
aConversionContext, someVisitedValues));
Array.set(tempResultArray, 0, convertPlainValueToTargetType(tempActualParamType, aParameterizedType,
aValue, aConversionContext, someVisitedValues));
}
return tempResultArray;
} else {
Expand Down Expand Up @@ -338,18 +333,37 @@ private Object convertSingleValueToTargetType(Class<?> aTargetType, Class<?> aPa
Class<?> tempSourceType = transformPrimitiveTypes(aValue.getClass());
String tempSourceTypeName = tempSourceType.getName();

// No conversion necessary if target type is a superclass or the same as the current type
if (tempTargetType != null && tempTargetType.isAssignableFrom(tempSourceType)) {
// ...except if the source type is one of Integritys' internal types, which shouldn't generally been given
// to fixtures in an unconverted state.
if (!tempSourceTypeName.startsWith("de.gebit.integrity.dsl.")) {
return aValue;
if (Map.class.isAssignableFrom(tempSourceType)) {
// Maps need special attention: we may have to convert their contents. Therefore we perform a Map-to-Map
// conversion in this case, which iterates over inner value and ensures those are also converted, if
// necessary.
// In order to do this, we need to specify a concrete map target type.
if (tempTargetType == null) {
tempTargetType = HashMap.class; // HashMap is a good default
} else if (Map.class.isAssignableFrom(tempTargetType)) {
// If the target type is also a map, see whether the target is an abstract type
if ((tempTargetType.getModifiers() & Modifier.ABSTRACT) != 0) {
// If it is, just use the source value type as target. This basically performs no conversion of the
// map object itself, but it nevertheless results in an execution of the Map-to-Map conversion,
// which triggers conversion of inner values
tempTargetType = tempSourceType;
}
}
} else {
// No conversion necessary if target type is a superclass or the same as the current type
if (tempTargetType != null && tempTargetType.isAssignableFrom(tempSourceType)) {
// ...except if the source type is one of Integritys' internal types, which shouldn't generally been
// given
// to fixtures in an unconverted state.
if (!tempSourceTypeName.startsWith("de.gebit.integrity.dsl.")) {
return aValue;
}
}
}

if (tempTargetType == null && tempSourceTypeName.startsWith("java.")) {
// Java types generally have themselves as "default type" and don't need to be converted to anything
return aValue;
if (tempTargetType == null && tempSourceTypeName.startsWith("java.")) {
// Java types generally have themselves as "default type" and don't need to be converted to anything
return aValue;
}
}

try {
Expand All @@ -372,8 +386,8 @@ private Object convertSingleValueToTargetType(Class<?> aTargetType, Class<?> aPa
throw exc;
// SUPPRESS CHECKSTYLE IllegalCatch
} catch (Throwable exc) {
throw new ConversionFailedException(aValue.getClass(), tempTargetType,
"Unexpected error during conversion", exc);
throw new ConversionFailedException(aValue.getClass(), tempTargetType, "Unexpected error during conversion",
exc);
}
}

Expand Down Expand Up @@ -502,8 +516,8 @@ protected Object convertEncapsulatedConstantValueToTargetType(Class<?> aTargetTy
} else if (((Constant) aValue).getName().eContainer() instanceof ConstantDefinition) {
// Without the variable manager, we can still attempt to resolve statically.
try {
return parameterResolver.resolveStatically((ConstantDefinition) ((Constant) aValue).getName()
.eContainer(), null);
return parameterResolver
.resolveStatically((ConstantDefinition) ((Constant) aValue).getName().eContainer(), null);
} catch (ClassNotFoundException exc) {
exc.printStackTrace();
} catch (InstantiationException exc) {
Expand Down Expand Up @@ -580,8 +594,8 @@ protected Object convertEncapsulatedValueCollectionToTargetType(Class<?> aTarget
// this is actually an array
Object tempResultArray = Array.newInstance(tempTargetArrayType, aCollection.getMoreValues().size() + 1);
for (int i = 0; i < aCollection.getMoreValues().size() + 1; i++) {
ValueOrEnumValueOrOperation tempValue = (i == 0 ? aCollection.getValue() : aCollection.getMoreValues()
.get(i - 1));
ValueOrEnumValueOrOperation tempValue = (i == 0 ? aCollection.getValue()
: aCollection.getMoreValues().get(i - 1));
Object tempResultValue = convertEncapsulatedValueToTargetType(tempTargetType, aParameterizedType,
tempValue, aConversionContext, someVisitedValues);
Array.set(tempResultArray, i, tempResultValue);
Expand Down Expand Up @@ -720,9 +734,8 @@ public FormattedString[] convertValueToStringArray(Object aValue, ConversionCont
FormattedString[] tempResult;
try {
if (aValue instanceof ValueOrEnumValueOrOperationCollection) {
tempResult = (FormattedString[]) convertEncapsulatedValueCollectionToTargetType(
FormattedString[].class, null, (ValueOrEnumValueOrOperationCollection) aValue,
tempConversionContext, someVisitedValues);
tempResult = (FormattedString[]) convertEncapsulatedValueCollectionToTargetType(FormattedString[].class,
null, (ValueOrEnumValueOrOperationCollection) aValue, tempConversionContext, someVisitedValues);
} else if (aValue instanceof ValueOrEnumValueOrOperation) {
tempResult = (FormattedString[]) convertEncapsulatedValueToTargetType(FormattedString[].class, null,
(ValueOrEnumValueOrOperation) aValue, tempConversionContext, someVisitedValues);
Expand Down Expand Up @@ -958,8 +971,8 @@ public String toString() {
* @throws IllegalAccessException
*/
protected Conversion<?, ?> findAndInstantiateConversion(Class<?> aSourceType, Class<?> aTargetType,
Set<Object> someVisitedValues, ConversionContext aConversionContext) throws InstantiationException,
IllegalAccessException {
Set<Object> someVisitedValues, ConversionContext aConversionContext)
throws InstantiationException, IllegalAccessException {
Class<? extends Conversion<?, ?>> tempConversionClass = findConversion(aSourceType, aTargetType,
someVisitedValues, aConversionContext);

Expand Down Expand Up @@ -1034,8 +1047,8 @@ public String toString() {
* @return a conversion class, or null if none was found
*/
protected Class<? extends Conversion<?, ?>> searchDerivedConversionMap(Class<?> aSourceType, Class<?> aTargetType) {
List<Class<? extends Conversion<?, ?>>> tempList = derivedConversions.get(new ConversionKey(aSourceType,
aTargetType));
List<Class<? extends Conversion<?, ?>>> tempList = derivedConversions
.get(new ConversionKey(aSourceType, aTargetType));
if (tempList != null && !tempList.isEmpty()) {
return tempList.get(0);
}
Expand Down Expand Up @@ -1173,8 +1186,8 @@ public String toString() {
* @throws IllegalAccessException
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
protected <C extends Conversion> C createConversionInstance(Class<C> aConversionClass, Set<Object> someVisitedValues)
throws InstantiationException, IllegalAccessException {
protected <C extends Conversion> C createConversionInstance(Class<C> aConversionClass,
Set<Object> someVisitedValues) throws InstantiationException, IllegalAccessException {
if (aConversionClass == null) {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@
import de.gebit.integrity.parameter.conversion.conversions.java.other.EnumToString;
import de.gebit.integrity.parameter.conversion.conversions.java.other.MapToBean;
import de.gebit.integrity.parameter.conversion.conversions.java.other.MapToFormattedString;
import de.gebit.integrity.parameter.conversion.conversions.java.other.MapToMap;
import de.gebit.integrity.parameter.conversion.conversions.java.other.MapToString;
import de.gebit.integrity.parameter.conversion.conversions.java.other.ObjectToFormattedString;
import de.gebit.integrity.parameter.conversion.conversions.java.other.ObjectToMap;
Expand Down Expand Up @@ -209,6 +210,7 @@ protected void initializeConversions() {
addConversion(MapToBean.class);
addConversion(MapToString.class);
addConversion(MapToFormattedString.class);
addConversion(MapToMap.class);
addConversion(ObjectToMap.class);
addConversion(EnumToString.class);
addConversion(EnumToFormattedString.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import java.util.Hashtable;
import java.util.Map;
import java.util.Map.Entry;
import java.util.SortedMap;
import java.util.TreeMap;

import de.gebit.integrity.comparator.MapComparisonResult;
import de.gebit.integrity.parameter.conversion.Conversion;
Expand Down Expand Up @@ -51,7 +53,7 @@ public abstract class AbstractMapToString<T> extends Conversion<Map, T> {
* the conversion context
* @return the resulting string
*/
protected FormattedString convertToFormattedString(Map aSource, ConversionContext aConversionContext)
protected FormattedString convertToFormattedString(Map<?, ?> aSource, ConversionContext aConversionContext)
throws ConversionFailedException {
String tempParentMapPath = (String) aConversionContext.getProperty(MAP_PATH_PROPERTY);

Expand All @@ -66,16 +68,28 @@ protected FormattedString convertToFormattedString(Map aSource, ConversionContex
}
nestedObjectDepthMap.put(Thread.currentThread(), tempDepth);

// In order to provide a consistent ordering of map entries in the string, we want to sort the map by natural
// key ordering
SortedMap<?, ?> tempSortedSource = null;
if (aSource instanceof SortedMap) {
// Either our source map is already sorted...
tempSortedSource = (SortedMap) aSource;
} else {
// ...or we need to sort it by creating a TreeMap and filling it
tempSortedSource = new TreeMap<>(aSource);
}

try {
boolean tempFirst = true;
for (Entry<?, ?> tempEntry : ((Map<?, ?>) aSource).entrySet()) {
for (Entry<?, ?> tempEntry : ((Map<?, ?>) tempSortedSource).entrySet()) {
String tempCurrentMapPath = (tempParentMapPath != null ? tempParentMapPath + "." : "")
+ tempEntry.getKey();
aConversionContext.withProperty(MAP_PATH_PROPERTY, tempCurrentMapPath);

boolean tempCurrentPathFailed = (aConversionContext.getComparisonResult() instanceof MapComparisonResult)
&& ((MapComparisonResult) aConversionContext.getComparisonResult()).getFailedPaths().contains(
tempCurrentMapPath);
boolean tempCurrentPathFailed = (aConversionContext
.getComparisonResult() instanceof MapComparisonResult)
&& ((MapComparisonResult) aConversionContext.getComparisonResult()).getFailedPaths()
.contains(tempCurrentMapPath);

FormattedString[] tempConvertedValues = convertValueToFormattedStringArrayRecursive(
tempEntry.getValue(), aConversionContext);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/*******************************************************************************
* Copyright (c) 2016 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.conversions.java.other;

import java.util.Map;
import java.util.Map.Entry;

import de.gebit.integrity.operations.UnexecutableException;
import de.gebit.integrity.parameter.conversion.Conversion;
import de.gebit.integrity.parameter.conversion.ConversionContext;
import de.gebit.integrity.parameter.conversion.ConversionFailedException;
import de.gebit.integrity.utils.ParameterUtil.UnresolvableVariableException;

/**
* A default Integrity conversion.
*
*
* @author Rene Schneider - initial API and implementation
*
*/
@SuppressWarnings("rawtypes")
@de.gebit.integrity.parameter.conversion.Conversion.Priority(Integer.MIN_VALUE)
public class MapToMap extends Conversion<Map, Map> {

@SuppressWarnings("unchecked")
@Override
public Map convert(Map aSource, Class<? extends Map> aTargetType, ConversionContext aConversionContext)
throws ConversionFailedException {

try {
Map tempTargetInstance = aTargetType.newInstance();

Class<?> tempTargetValueType = null;
if (aTargetType.getTypeParameters().length >= 2) {
tempTargetValueType = aTargetType.getTypeParameters()[1].getGenericDeclaration().getComponentType();
}

for (Entry<?, ?> tempEntry : ((Map<?, ?>) aSource).entrySet()) {
// // find setter
// Method tempWriteMethod = new PropertyDescriptor(tempEntry.getKey(), aTargetType).getWriteMethod();
// if (tempWriteMethod == null || tempWriteMethod.getParameterTypes().length != 1) {
// throw new ConversionFailedException(aSource.getClass(), aTargetType,
// "No accessible standards-compliant setter found for '" + tempEntry.getKey() + "'");
// }
//
// aTargetType.getp
// Class<?> tempTargetType = tempWriteMethod.getParameterTypes()[0];
// Class<?> tempParameterizedType = null;
//
// // See whether we can find a generic type parameter for the given target class
// Class<?> tempClassInFocus = aTargetType;
// while (tempClassInFocus != null) {
// try {
// Field tempField = tempClassInFocus.getDeclaredField(tempEntry.getKey());
// Type tempGenericType = tempField.getGenericType();
// if (tempGenericType instanceof ParameterizedType) {
// Type tempInnerType = ((ParameterizedType) tempGenericType).getActualTypeArguments()[0];
// if (tempInnerType instanceof WildcardType) {
// if (((WildcardType) tempInnerType).getUpperBounds() == null) {
// tempParameterizedType = null;
// } else {
// Type tempUpperBound = ((WildcardType) tempInnerType).getUpperBounds()[0];
// if (tempUpperBound instanceof ParameterizedType) {
// tempParameterizedType = (Class<?>) ((ParameterizedType) tempUpperBound)
// .getRawType();
// } else {
// tempParameterizedType = (Class<?>) tempUpperBound;
// }
// }
// // lower bounds not currently supported!
//
// } else {
// if (tempInnerType instanceof ParameterizedType) {
// tempParameterizedType = (Class<?>) ((ParameterizedType) tempInnerType).getRawType();
// } else {
// tempParameterizedType = (Class<?>) tempInnerType;
// }
// }
// }
// break;
// } catch (SecurityException exc) {
// // don't care, just continue
// } catch (NoSuchFieldException exc) {
// // don't care, just continue
// }
// tempClassInFocus = tempClassInFocus.getSuperclass();
// }

Object tempConvertedValue;
// if (tempEntry.getValue() instanceof Map) { // map itself
// // case for only one element within an array type
// Class<?> tempOriginalClass = tempWriteMethod.getParameterTypes()[0];
// Class<?> tempClass = tempOriginalClass;
// if (tempOriginalClass.isArray()) {
// tempClass = tempClass.getComponentType();
// }
//
// tempConvertedValue = convert(((Map) tempEntry.getValue()), tempClass, aConversionContext);
//
// if (tempOriginalClass.isArray()) {
// Object tempCopy = tempConvertedValue;
// tempConvertedValue = Array.newInstance(tempClass, 1);
// Array.set(tempConvertedValue, 0, tempCopy);
// }
// } else { // value
tempConvertedValue = convertValueRecursive(tempTargetValueType, null, tempEntry.getValue(),
aConversionContext);
// }
tempTargetInstance.put(tempEntry.getKey(), tempConvertedValue);
}
return tempTargetInstance;
} catch (

InstantiationException exc) {
throw new ConversionFailedException(aSource.getClass(), aTargetType, null, exc);
} catch (IllegalAccessException exc) {
throw new ConversionFailedException(aSource.getClass(), aTargetType, null, exc);
} catch (UnresolvableVariableException exc) {
throw new ConversionFailedException(aSource.getClass(), aTargetType, null, exc);
} catch (ClassNotFoundException exc) {
throw new ConversionFailedException(aSource.getClass(), aTargetType, null, exc);
} catch (UnexecutableException exc) {
throw new ConversionFailedException(aSource.getClass(), aTargetType, null, exc);
} catch (IllegalArgumentException exc) {
throw new ConversionFailedException(aSource.getClass(), aTargetType, null, exc);
} catch (SecurityException exc) {
throw new ConversionFailedException(aSource.getClass(), aTargetType, null, exc);
}
}

}
Loading

0 comments on commit 39101f6

Please sign in to comment.