Skip to content

Commit

Permalink
[converter] Avoid losing generics information in nested types
Browse files Browse the repository at this point in the history
Signed-off-by: Tim Ward <[email protected]>
  • Loading branch information
timothyjward committed Dec 22, 2017
1 parent 5f9e349 commit e833950
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ private <T> T convertToDTO(Class< ? > sourceCls, Class< ? > targetAsCls) {
val = converter.convert(val).sourceAsDTO().to(
f.getType());
else
val = converter.convert(val).to(f.getType());
val = converter.convert(val).to(f.getGenericType());
f.set(dto, val);
}
}
Expand Down Expand Up @@ -662,7 +662,7 @@ public Object invoke(Object proxy, Method method, Object[] args)
if (propName == null)
return null;

Class< ? > targetType = method.getReturnType();
// Class< ? > targetType = method.getReturnType();

Object val = m.get(propName);
if (val == null && keysIgnoreCase) {
Expand Down Expand Up @@ -692,7 +692,7 @@ public Object invoke(Object proxy, Method method, Object[] args)
}
}

return converter.convert(val).to(targetType);
return converter.convert(val).to(method.getGenericReturnType());
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -749,6 +749,49 @@ public void testDTOWithGenerics() {
assertEquals(dto2SubAAA.charSet, new HashSet<Character>(Arrays.asList('b', 'a', 'r')));
}

@Test
public void testMapToDTOWithGenerics() {
Map<String, Object> dto = new HashMap<>();

dto.put("longList", Arrays.asList((short)999, "1000"));

Map<String, Object> dtoMap = new LinkedHashMap<>();
dto.put("dtoMap", dtoMap);

Map<String, Object> subDTO1 = new HashMap<>();
subDTO1.put("charSet", new HashSet<>(Arrays.asList("foo", (int) 'o', 'o')));
dtoMap.put("zzz", subDTO1);

Map<String, Object> subDTO2 = new HashMap<>();
subDTO2.put("charSet", new HashSet<>(Arrays.asList('b', 'a', 'r')));
dtoMap.put("aaa", subDTO2);

MyDTO2 converted = converter.convert(dto).to(MyDTO2.class);

assertEquals(Arrays.asList(999L, 1000L), converted.longList);
Map<String, MyDTO3> nestedMap = converted.dtoMap;

// Check iteration order is preserved by iterating
int i=0;
for (Iterator<Map.Entry<String, MyDTO3>> it = nestedMap.entrySet().iterator(); it.hasNext(); i++) {
Map.Entry<String, MyDTO3> entry = it.next();
switch (i) {
case 0:
assertEquals("zzz", entry.getKey());
MyDTO3 dto1 = entry.getValue();
assertEquals(new HashSet<Character>(Arrays.asList('f', 'o')), dto1.charSet);
break;
case 1:
assertEquals("aaa", entry.getKey());
MyDTO3 dto2 = entry.getValue();
assertEquals(new HashSet<Character>(Arrays.asList('b', 'a', 'r')), dto2.charSet);
break;
default:
fail("Unexpected number of elements on map");
}
}
}

@Test
public void testMapToDTOWithSurplusMapFiels() {
Map<String, String> m = new HashMap<>();
Expand Down Expand Up @@ -1134,6 +1177,15 @@ public void testLongArrayToLongCollection() {
assertEquals(la[i], it.next());
}
}

@Test
public void testMapToInterfaceWithGenerics() {
Map<String, Object> dto = new HashMap<>();
dto.put("charSet", new HashSet<>(Arrays.asList("foo", (int) 'o', 'o')));

MyGenericInterface converted = converter.convert(dto).to(MyGenericInterface.class);
assertEquals(new HashSet<Character>(Arrays.asList('f', 'o')), converted.charSet());
}

static class MyClass2 {
private final String value;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.osgi.util.converter;

import java.util.Set;

public interface MyGenericInterface {
public Set<Character> charSet();
}

0 comments on commit e833950

Please sign in to comment.