Merge pull request #51 from olegz/INT-1968

ObjectToMapTransformer now handles BigDecimal
This commit is contained in:
Mark Fisher
2011-09-02 12:46:02 -04:00
5 changed files with 207 additions and 600 deletions

View File

@@ -1,160 +0,0 @@
/*
* Copyright 2002-2010 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
*
* http://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.integration.transformer;
import java.beans.PropertyDescriptor;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.util.CollectionUtils;
/**
* @author Oleg Zhurakousky
* @since 2.0
*/
class CycleDetector {
private final ExpressionParser parser = new SpelExpressionParser();
private final String[] defaultIgnorePakages = new String[]{
"com.apple",
"com.sun",
"java.awt",
"java",
"javax",
"org.jcp",
"org.omg",
"sun"
};
private boolean ignoreClassAttribute = true;
private boolean ignoreDefaultPackages = true;
/**
*
* @param target
* @param ignorePakages
*/
public void detectCycle(Object target, String... ignorePakages){
Map<Object, Set<Object>> objectReferenceMap = new HashMap<Object, Set<Object>>();
this.doDetect(target, objectReferenceMap, ignorePakages);
}
/*
*
*/
private void doDetect(Object target, Map<Object, Set<Object>> objectReferenceMap, String[] ignorePakages){
if (propertyInIgnoredPackage(target, ignorePakages)){
return;
}
if (collectionMapOrArray(target)){
Iterable<?> iterable = null;
if (target instanceof Collection<?>) {
iterable = (Iterable<?>) target;
} else if (target instanceof Map<?, ?>){
iterable = ((Map<?, ?>) target).values();
} else if (target.getClass().isArray()){
iterable = CollectionUtils.arrayToList(target);
}
for (Object value : iterable) {
this.doDetect(value, objectReferenceMap, ignorePakages);
}
} else {
if (!objectReferenceMap.containsKey(target)){
objectReferenceMap.put(target, new HashSet<Object>());
}
EvaluationContext context = new StandardEvaluationContext(target);
BeanWrapperImpl bw = new BeanWrapperImpl(target);
PropertyDescriptor[] descriptors = bw.getPropertyDescriptors();
for (PropertyDescriptor propertyDescriptor : descriptors) {
String propertyName = propertyDescriptor.getName();
if (propertyName.equals("class") && ignoreClassAttribute){
continue; // no need to process
}
Expression expression = parser.parseExpression(propertyName);
Object propertyValue = null;
try {
propertyValue = expression.getValue(context);
} catch (Exception e) {/*nothing to do, might only happen when 'ignoreClassAttribute' is set to false ('true' by default)*/}
if (propertyValue != null){
if (!collectionMapOrArray(propertyValue)){
Set<Object> references = objectReferenceMap.get(target);
if (!references.contains(propertyValue)){
references.add(propertyValue);
}
if (objectReferenceMap.containsKey(propertyValue)){
references = objectReferenceMap.get(propertyValue);
if (references.contains(target)){
throw new MessageTransformationException("Cyclic reference detected between: " +
propertyValue.getClass().getSimpleName() + " - " + target.getClass().getSimpleName());
}
}
}
this.doDetect(propertyValue, objectReferenceMap, ignorePakages);
}
}
}
}
/*
*
*/
private boolean collectionMapOrArray(Object elementValue){
return (elementValue instanceof Map<?,?> ||
elementValue instanceof Collection<?> ||
elementValue.getClass().isArray());
}
/*
*
*/
private boolean propertyInIgnoredPackage(Object elementValue, String[] ignorePakagess){
if (this.collectionMapOrArray(elementValue)){
return false;
}
for (String packagePattern : ignorePakagess) {
if (elementValue.getClass().getPackage().getName().startsWith(packagePattern)){
return true;
}
}
if (ignoreDefaultPackages){
for (String packagePattern : defaultIgnorePakages) {
if (elementValue.getClass().getPackage().getName().startsWith(packagePattern)){
return true;
}
}
}
return false;
}
public boolean isIgnoreClassAttribute() {
return ignoreClassAttribute;
}
public void setIgnoreClassAttribute(boolean ignoreClassAttribute) {
this.ignoreClassAttribute = ignoreClassAttribute;
}
public boolean isIgnoreDefaultPackages() {
return ignoreDefaultPackages;
}
public void setIgnoreDefaultPackages(boolean ignoreDefaultPackages) {
this.ignoreDefaultPackages = ignoreDefaultPackages;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 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.
@@ -13,20 +13,25 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.transformer;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
/**
* Will transform an object graph into a flat Map where keys are valid SpEL expressions
* and values are of java.lang.* type. This means that this transformer will recursively navigate
* through the Object graph until the value could be java.lang.*
* It supports Collections, Maps and Arrays which means it will flatten Object's attributes that are defined as such:<br>
* Will transform an object graph into a Map. It supports a conventional Map (map of maps) where complex attributes are
* represented as Map values as well as a flat Map where keys document the path to the value. It supports Collections,
* Maps and Arrays which means that for flat maps it will flatten an Object's properties as such:<br>
*
* private Map<String, Map<String, Object>> testMapInMapData;<br>
* private List<String> departments;<br>
* private String[] akaNames;<br>
* private Map<String, List<String>> mapWithListData;<br>
*
* The resulting Map structure will look similar to this:<br>
*
@@ -34,20 +39,69 @@ import java.util.Map;
* departments[0]=HR<br>
* person.lname=Case
*
* By default it will transform to a flat Map. If you need to transform to a Map of Maps set the 'shouldFlattenKeys'
* property to 'false' via the {@link ObjectToMapTransformer#setShouldFlattenKeys(boolean)} method.
*
* @author Oleg Zhurakousky
* @since 2.0
*/
public class ObjectToMapTransformer extends AbstractPayloadTransformer<Object, Map<?,?>> {
/*
* (non-Javadoc)
* @see org.springframework.integration.transformer.AbstractPayloadTransformer#transformPayload(java.lang.Object)
*/
private volatile boolean shouldFlattenKeys = true;
public void setShouldFlattenKeys(boolean shouldFlattenKeys) {
this.shouldFlattenKeys = shouldFlattenKeys;
}
@SuppressWarnings("unchecked")
protected Map<String, Object> transformPayload(Object payload) throws Exception {
CycleDetector cycleDetector = new CycleDetector();
cycleDetector.detectCycle(payload);
ObjectToSpelMapBuilder builder = new ObjectToSpelMapBuilder();
return builder.buildSpelMap(payload);
ObjectMapper mapper = new ObjectMapper();
Map<String,Object> result = new ObjectMapper().readValue(mapper.writeValueAsString(payload), Map.class);
if (this.shouldFlattenKeys) {
result = this.flattenMap(result);
}
return result;
}
private Map<String, Object> flattenMap(Map<String,Object> result){
Map<String,Object> resultMap = new HashMap<String, Object>();
this.doFlatten("", result, resultMap);
return resultMap;
}
private void doFlatten(String propertyPrefix, Map<String,Object> inputMap, Map<String,Object> resultMap){
if (StringUtils.hasText(propertyPrefix)) {
propertyPrefix = propertyPrefix + ".";
}
for (String key : inputMap.keySet()) {
Object value = inputMap.get(key);
this.doProcessElement(propertyPrefix + key, value, resultMap);
}
}
private void doProcessCollection(String propertyPrefix, Collection<?> list, Map<String, Object> resultMap) {
int counter = 0;
for (Object element : list) {
this.doProcessElement(propertyPrefix + "[" + counter + "]", element, resultMap);
counter ++;
}
}
@SuppressWarnings("unchecked")
private void doProcessElement(String propertyPrefix, Object element, Map<String, Object> resultMap) {
if (element instanceof Map) {
this.doFlatten(propertyPrefix, (Map<String, Object>) element, resultMap);
}
else if (element instanceof Collection) {
this.doProcessCollection(propertyPrefix, (Collection<?>) element, resultMap);
}
else if (element != null && element.getClass().isArray()) {
Collection<?> collection = CollectionUtils.arrayToList(element);
this.doProcessCollection(propertyPrefix, collection, resultMap);
}
else {
resultMap.put(propertyPrefix, element);
}
}
}

View File

@@ -1,142 +0,0 @@
/*
* Copyright 2002-2010 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
*
* http://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.integration.transformer;
import java.beans.PropertyDescriptor;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.util.CollectionUtils;
/**
* @author Oleg Zhurakousky
* @since 2.0
*/
class ObjectToSpelMapBuilder {
private final ExpressionParser parser = new SpelExpressionParser();
private boolean serializeTypeName;
public Map<String, Object> buildSpelMap(Object rootObject) {
Map<String, Object> propertiesMap = new HashMap<String, Object>();
EvaluationContext context = new StandardEvaluationContext(rootObject);
this.buildProperties(context, "", propertiesMap, rootObject);
return propertiesMap;
}
private void buildProperties(EvaluationContext context, String parentPropertyPath, Map<String, Object> propertiesMap, Object object) {
BeanWrapperImpl bw = new BeanWrapperImpl(object);
PropertyDescriptor[] descriptors = bw.getPropertyDescriptors();
for (PropertyDescriptor propertyDescriptor : descriptors) {
Class<?> propertyType = propertyDescriptor.getPropertyType();
String propertyName = propertyDescriptor.getName();
String propertyPath = parentPropertyPath + propertyName;
if (propertyType.isArray() || Collection.class.isAssignableFrom(propertyType)) {
this.processArray(context, propertyPath, propertyName, propertyType, propertiesMap);
}
else if (propertyType.isAnonymousClass()) {
throw new IllegalArgumentException("anonymous class property transformation is not supported");
}
else if (propertyType.isAssignableFrom(Map.class)) {
Expression expression = parser.parseExpression(propertyPath);
Map<?,?> map = (Map<?,?>) expression.getValue(context);
if (map != null) {
this.processMap(context, propertiesMap, map, parentPropertyPath, propertyName);
}
}
else {
Expression expression = parser.parseExpression(propertyPath);
Object propertyValue = expression.getValue(context);
if (propertyValue != null) {
this.processElementValue(context, propertyValue, propertyName, propertyPath, propertiesMap);
}
}
}
}
private void processMap(EvaluationContext context, Map<String, Object> mappedProperties, Map<?,?> mapToTransform, String propertyPath, String propertyName) {
Iterator<?> mapIter = mapToTransform.keySet().iterator();
while (mapIter.hasNext()) {
Object keyElement = mapIter.next();
Object elementValue = mapToTransform.get(keyElement);
String mapPropertyPath = propertyPath + propertyName + "['" + keyElement.toString() + "']";
if (elementValue.getClass().isArray() || elementValue instanceof Collection<?>) {
this.processArray(context, mapPropertyPath, "", elementValue.getClass(), mappedProperties);
}
else if (elementValue instanceof Map<?,?>) {
this.processMap(context, mappedProperties, (Map<?, ?>) elementValue, mapPropertyPath, "");
}
else {
this.processElementValue(context, elementValue, propertyName, mapPropertyPath, mappedProperties);
}
}
}
private void processArray(EvaluationContext context, String propertyPath, String propertyName, Class<?> elementType, Map<String, Object> propertiesMap) {
Expression arrayExp = parser.parseExpression(propertyPath);
Object array = arrayExp.getValue(context);
List<?> arrayElements = null;
if (elementType.isArray()) {
arrayElements = CollectionUtils.arrayToList(array);
}
else {
arrayElements = (List<?>) array;
}
int i = 0;
for (Object arrayElement : arrayElements) {
String arrayPropertyPath = propertyPath + "[" + i++ + "]";
if (arrayElement instanceof Map<?, ?>) {
// last argument is empty because it is not a named property, but an array element
this.processMap(context, propertiesMap, (Map<?, ?>) arrayElement, arrayPropertyPath, "");
}
else if (arrayElement.getClass().isArray()){
this.processArray(context, arrayPropertyPath, propertyName, elementType, propertiesMap);
}
else {
this.processElementValue(context, arrayElement, propertyName, arrayPropertyPath, propertiesMap);
}
}
}
private void processElementValue(EvaluationContext context, Object elementValue, String propertyName, String propertyPath, Map<String, Object> propertiesMap) {
// JDK packages considered shared, thus serializable
if (elementValue.getClass().getPackage().getName().startsWith("java.lang")) {
if (propertyName.equals("class") && !this.serializeTypeName) {
return;
}
else {
propertiesMap.put(propertyPath, elementValue);
}
}
else {
this.buildProperties(context, propertyPath + ".", propertiesMap, elementValue);
}
}
}

View File

@@ -1,266 +0,0 @@
/*
* Copyright 2002-2010 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
*
* http://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.integration.transformer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.Test;
/**
* @author Oleg Zhurakousky
*
*/
public class CycleDetectorTests {
@Test
public void testWithNoIgnoredPackages(){
Parent parent = this.prepare(false);
CycleDetector builder = new CycleDetector();
builder.setIgnoreDefaultPackages(false);
builder.detectCycle(parent);
// should not throw an exception
}
@Test
public void testWithNoIgnoredPackagesAndClassProperty(){
Parent parent = this.prepare(false);
CycleDetector builder = new CycleDetector();
builder.setIgnoreDefaultPackages(false);
builder.setIgnoreClassAttribute(false);
builder.detectCycle(parent);
// should not throw an exception
}
@Test
public void testWithAditionalIgnoredPackages(){
Parent parent = this.prepare(true);
CycleDetector builder = new CycleDetector();
builder.detectCycle(parent, "org.springframework.integration.transformer");
// should not throw an exception, however if you remove additional package from
// the above method there is a cycle in the domain core
}
@Test
public void testObjectReferenceMapWithoutCycle(){
Parent parent = this.prepare(false);
CycleDetector builder = new CycleDetector();
builder.detectCycle(parent);
// should not throw an exception
}
@Test(expected=MessageTransformationException.class)
public void testObjectReferenceMapWithCycle(){
Parent parent = this.prepare(true);
CycleDetector builder = new CycleDetector();
builder.detectCycle(parent);
}
@Test
public void testWithNoCyclesInArray(){
Parent parent = this.prepare(false);
Foo[] foos = new Foo[]{new Foo(), new Foo()};
parent.getAddress().setFoos(foos);
CycleDetector builder = new CycleDetector();
builder.detectCycle(parent);
}
@Test(expected=MessageTransformationException.class)
public void testWithCyclesInArray(){
Parent parent = this.prepare(false);
Foo foo = new Foo();
Bar bar = new Bar();
foo.setBar(bar);
bar.setFoo(foo);
Foo[] foos = new Foo[]{foo, new Foo()};
parent.getAddress().setFoos(foos);
CycleDetector builder = new CycleDetector();
builder.detectCycle(parent);
}
@Test
public void testWithNoCyclesInMapWithList(){
Parent parent = this.prepare(false);
Foo fooA = new Foo();
Foo fooB = new Foo();
Foo[] foos = new Foo[]{fooA, fooB};
parent.getAddress().setFoos(foos);
List<Foo> fooList = new ArrayList<Foo>();
fooList.add(fooA);
fooList.add(fooB);
Map<Object, List<Foo>> mapOfFoos = new HashMap<Object, List<Foo>>();
mapOfFoos.put("listOfFoos", fooList);
parent.getChild().setMapOfFoos(mapOfFoos);
CycleDetector builder = new CycleDetector();
builder.detectCycle(parent);
}
@Test(expected=MessageTransformationException.class)
public void testWithCyclesInMapWithList(){
Parent parent = this.prepare(false);
Foo fooA = new Foo();
Bar bar = new Bar();
bar.setFoo(fooA);
fooA.setBar(bar);
Foo fooB = new Foo();
Foo[] foos = new Foo[]{new Foo(), new Foo()};
parent.getAddress().setFoos(foos);
List<Foo> fooList = new ArrayList<Foo>();
fooList.add(fooA);
fooList.add(fooB);
Map<Object, List<Foo>> mapOfFoos = new HashMap<Object, List<Foo>>();
mapOfFoos.put("listOfFoos", fooList);
parent.getChild().setMapOfFoos(mapOfFoos);
CycleDetector builder = new CycleDetector();
builder.detectCycle(parent);
}
//################# Test Classes ###################
public Parent prepare(boolean cycle){
Parent parent = new Parent();
Child child = new Child();
Address address = new Address();
address.setStreet("123 Main st");
child.setAddress(address);
List<String> nickNames = new ArrayList<String>();
nickNames.add("spanky");
nickNames.add("goofy");
child.setNickNames(nickNames);
child.setName("Seva");
if (cycle){
child.setParent(parent);
}
parent.setAddress(address);
parent.setChild(child);
parent.setName("Oleg");
return parent;
}
/*
*
*/
public static class Parent{
private Address address;
private Child child;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public Child getChild() {
return child;
}
public void setChild(Child child) {
this.child = child;
}
}
/*
*
*/
public static class Child{
private String name;
private List<String> nickNames;
private Map<Object, List<Foo>> mapOfFoos;
private Address address;
private Parent parent;
public Parent getParent() {
return parent;
}
public void setParent(Parent parent) {
this.parent = parent;
}
public List<String> getNickNames() {
return nickNames;
}
public void setNickNames(List<String> nickNames) {
this.nickNames = nickNames;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Map<Object, List<Foo>> getMapOfFoos() {
return mapOfFoos;
}
public void setMapOfFoos(Map<Object, List<Foo>> mapOfFoos) {
this.mapOfFoos = mapOfFoos;
}
}
/*
*
*/
public static class Address{
private String street;
private Foo[] foos;
public Foo[] getFoos() {
return foos;
}
public void setFoos(Foo[] foos) {
this.foos = foos;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
}
public static class Foo{
private Bar bar;
public Bar getBar() {
return bar;
}
public void setBar(Bar bar) {
this.bar = bar;
}
}
public static class Bar{
private Foo foo;
public Foo getFoo() {
return foo;
}
public void setFoo(Foo foo) {
this.foo = foo;
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 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.
@@ -15,17 +15,19 @@
*/
package org.springframework.integration.transformer;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertTrue;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.junit.Test;
import org.springframework.expression.EvaluationContext;
import org.springframework.context.expression.MapAccessor;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
@@ -33,6 +35,11 @@ import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.integration.Message;
import org.springframework.integration.support.MessageBuilder;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
/**
*
* @author Oleg Zhurakousky
@@ -41,27 +48,101 @@ import org.springframework.integration.support.MessageBuilder;
public class ObjectToMapTransformerTests {
@SuppressWarnings("unchecked")
@Test
public void testObjectToSpelMapTransformer(){
public void testObjectToSpelMapTransformer() throws JsonParseException, JsonMappingException, JsonGenerationException, IOException{
Employee employee = this.buildEmployee();
EvaluationContext context = new StandardEvaluationContext(employee);
StandardEvaluationContext context = new StandardEvaluationContext();
context.addPropertyAccessor(new MapAccessor());
ExpressionParser parser = new SpelExpressionParser();
ObjectToMapTransformer transformer = new ObjectToMapTransformer();
Message<Employee> message = MessageBuilder.withPayload(employee).build();
Message<?> transformedMessage = transformer.transform(message);
Map<String, Object> transformedMap = (Map<String, Object>) transformedMessage.getPayload();
System.out.println(transformedMap);
assertNotNull(transformedMap);
for (String key : transformedMap.keySet()) {
Expression expression = parser.parseExpression(key);
//System.out.println("Testing: " + key);
Object valueFromTheMap = transformedMap.get(key);
Object valueFromExpression = expression.getValue(context);
String packageNameOfValueType = valueFromTheMap.getClass().getPackage().getName();
assertTrue(packageNameOfValueType.startsWith("java.lang"));
assertEquals(valueFromTheMap, valueFromExpression);
}
Object valueFromTheMap = null;
Object valueFromExpression = null;
Expression expression = null;
expression = parser.parseExpression("departments[0]");
valueFromTheMap = transformedMap.get("departments[0]");
valueFromExpression = expression.getValue(context, employee, String.class);
assertEquals(valueFromTheMap, valueFromExpression);
expression = parser.parseExpression("person.address.coordinates");
valueFromTheMap = transformedMap.get("person.address.coordinates");
valueFromExpression = expression.getValue(context, employee, Map.class);
assertEquals(valueFromTheMap, valueFromExpression);
expression = parser.parseExpression("person.akaNames[0]");
valueFromTheMap = transformedMap.get("person.akaNames[0]");
valueFromExpression = expression.getValue(context, employee, String.class);
assertEquals(valueFromTheMap, valueFromExpression);
expression = parser.parseExpression("testMapInMapData.internalMapA.bar");
valueFromTheMap = transformedMap.get("testMapInMapData.internalMapA.bar");
valueFromExpression = expression.getValue(context, employee, String.class);
assertEquals(valueFromTheMap, valueFromExpression);
expression = parser.parseExpression("companyAddress.street");
valueFromTheMap = transformedMap.get("companyAddress.street");
valueFromExpression = expression.getValue(context, employee, String.class);
assertEquals(valueFromTheMap, valueFromExpression);
expression = parser.parseExpression("person.lname");
valueFromTheMap = transformedMap.get("person.lname");
valueFromExpression = expression.getValue(context, employee, String.class);
assertEquals(valueFromTheMap, valueFromExpression);
expression = parser.parseExpression("person.address.mapWithListData.mapWithListTestData[1]");
valueFromTheMap = transformedMap.get("person.address.mapWithListData.mapWithListTestData[1]");
valueFromExpression = expression.getValue(context, employee, String.class);
assertEquals(valueFromTheMap, valueFromExpression);
expression = parser.parseExpression("companyAddress.city");
valueFromTheMap = transformedMap.get("companyAddress.city");
valueFromExpression = expression.getValue(context, employee, String.class);
assertEquals(valueFromTheMap, valueFromExpression);
expression = parser.parseExpression("person.akaNames[2]");
valueFromTheMap = transformedMap.get("person.akaNames[2]");
valueFromExpression = expression.getValue(context, employee, String.class);
assertEquals(valueFromTheMap, valueFromExpression);
expression = parser.parseExpression("person.child");
valueFromTheMap = transformedMap.get("person.child");
valueFromExpression = expression.getValue(context, employee, String.class);
assertNull(valueFromTheMap);
assertNull(valueFromExpression);
expression = parser.parseExpression("testMapInMapData.internalMapA.foo");
valueFromTheMap = transformedMap.get("testMapInMapData.internalMapA.foo");
valueFromExpression = expression.getValue(context, employee, String.class);
assertEquals(valueFromTheMap, valueFromExpression);
expression = parser.parseExpression("person.address.city");
valueFromTheMap = transformedMap.get("person.address.city");
valueFromExpression = expression.getValue(context, employee, String.class);
assertEquals(valueFromTheMap, valueFromExpression);
expression = parser.parseExpression("companyAddress.coordinates.latitude[0]");
valueFromTheMap = transformedMap.get("companyAddress.coordinates.latitude[0]");
valueFromExpression = expression.getValue(context, employee, Integer.class);
assertEquals(valueFromTheMap, valueFromExpression);
expression = parser.parseExpression("person.remarks[1].baz");
valueFromTheMap = transformedMap.get("person.remarks[1].baz");
valueFromExpression = expression.getValue(context, employee, String.class);
assertEquals(valueFromTheMap, valueFromExpression);
expression = parser.parseExpression("listOfDates[0][1]");
valueFromTheMap = new Date((Long) transformedMap.get("listOfDates[0][1]"));
valueFromExpression = expression.getValue(context, employee, Date.class);
assertEquals(valueFromTheMap, valueFromExpression);
}
@Test(expected=MessageTransformationException.class)
public void testObjectToSpelMapTransformerWithCycle(){
Employee employee = this.buildEmployee();
@@ -86,9 +167,22 @@ public class ObjectToMapTransformerTests {
coordinates.put("longitude", new Long[]{(long)156});
companyAddress.setCoordinates(coordinates);
List<Date> datesA = new ArrayList<Date>();
datesA.add(new Date(System.currentTimeMillis() + 10000));
datesA.add(new Date(System.currentTimeMillis() + 20000));
List<Date> datesB = new ArrayList<Date>();
datesB.add(new Date(System.currentTimeMillis() + 30000));
datesB.add(new Date(System.currentTimeMillis() + 40000));
List<List<Date>> listOfDates = new ArrayList<List<Date>>();
listOfDates.add(datesA);
listOfDates.add(datesB);
Employee employee = new Employee();
employee.setCompanyName("ABC Inc.");
employee.setCompanyAddress(companyAddress);
employee.setListOfDates(listOfDates);
ArrayList departments = new ArrayList();
departments.add("HR");
departments.add("IT");
@@ -98,6 +192,8 @@ public class ObjectToMapTransformerTests {
person.setFname("Justin");
person.setLname("Case");
person.setAkaNames("Hard", "Use", "Beer");
person.setBirthDate(new Date());
person.setAge(new BigDecimal(10));
Address personAddress = new Address();
personAddress.setCity("Philly");
personAddress.setStreet("123 Main");
@@ -137,10 +233,17 @@ public class ObjectToMapTransformerTests {
public static class Employee{
private List<String> departments;
private List<List<Date>> listOfDates;
private String companyName;
private Person person;
private Address companyAddress;
private Map<String, Map<String, Object>> testMapInMapData;
public List<List<Date>> getListOfDates() {
return listOfDates;
}
public void setListOfDates(List<List<Date>> listOfDates) {
this.listOfDates = listOfDates;
}
public Map<String, Map<String, Object>> getTestMapInMapData() {
return testMapInMapData;
}
@@ -180,6 +283,24 @@ public class ObjectToMapTransformerTests {
private String[] akaNames;
private List<Map<String, Object>> remarks;
private Child child;
private BigDecimal age;
public BigDecimal getAge() {
return age;
}
public void setAge(BigDecimal age) {
this.age = age;
}
public Date getBirthDate() {
return birthDate;
}
public void setBirthDate(Date birthDate) {
this.birthDate = birthDate;
}
private Date birthDate;
public Child getChild() {
return child;
}