| /* |
| * 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.lang.reflect.Type; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.LinkedList; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.concurrent.CopyOnWriteArrayList; |
| import java.util.stream.Collectors; |
| import java.util.stream.Stream; |
| |
| import org.junit.After; |
| import org.junit.Before; |
| import org.junit.Ignore; |
| import org.junit.Test; |
| import org.osgi.util.function.Function; |
| |
| import static org.junit.Assert.assertArrayEquals; |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertNull; |
| |
| public class ConverterBuilderTest { |
| private Converter converter; |
| |
| @Before |
| public void setUp() { |
| converter = Converters.standardConverter(); |
| } |
| |
| @After |
| public void tearDown() { |
| converter = null; |
| } |
| |
| @Test |
| public void testStringArrayToStringAdapter() { |
| ConverterBuilder cb = converter.newConverterBuilder(); |
| Converter ca = cb. |
| rule(new TypeRule<String[],String>(String[].class, String.class, |
| v -> Stream.of(v).collect(Collectors.joining(",")))). |
| rule(new TypeRule<String,String[]>(String.class, String[].class, |
| v -> v.split(","))). |
| build(); |
| |
| assertEquals("A", converter.convert(new String[] {"A", "B"}).to(String.class)); |
| assertEquals("A,B", ca.convert(new String[] {"A", "B"}).to(String.class)); |
| |
| assertArrayEquals(new String [] {"A,B"}, |
| converter.convert("A,B").to(String[].class)); |
| assertArrayEquals(new String [] {"A","B"}, |
| ca.convert("A,B").to(String[].class)); |
| } |
| |
| static String convertToString(char[] a) { |
| StringBuilder sb = new StringBuilder(); |
| for (char c : a) { |
| sb.append(c); |
| } |
| return sb.toString(); |
| } |
| |
| @Test |
| public void testSecondLevelAdapter() { |
| ConverterBuilder cb = converter.newConverterBuilder(); |
| cb.rule(new TypeRule<>(char[].class, String.class, ConverterBuilderTest::convertToString)); |
| cb.rule(Integer.class, (f,t) -> -1); |
| cb.rule(Long.class, (f,t) -> -1L); |
| Converter ca = cb.build(); |
| |
| assertEquals("hi", ca.convert(new char[] {'h', 'i'}).to(String.class)); |
| assertEquals(Integer.valueOf(-1), ca.convert("Hello").to(Integer.class)); |
| assertEquals(Long.valueOf(-1), ca.convert("Hello").to(Long.class)); |
| |
| // Shadow the Integer variant but keep Long going to the Number variant. |
| Converter ca2 = ca.newConverterBuilder().rule( |
| new TypeRule<String,Integer>(String.class, Integer.class, s -> s.length())).build(); |
| assertEquals(5, (int) ca2.convert("Hello").to(Integer.class)); |
| assertEquals(Long.valueOf(-1), ca2.convert("Hello").to(Long.class)); |
| } |
| |
| @Test @Ignore |
| public void testConvertToBaseArray() { |
| // TODO |
| } |
| |
| @Test @Ignore |
| public void testThrowExceptionInCustomConverter() { |
| // TODO |
| } |
| |
| @Test @Ignore |
| public void testMixedListToNumberCase() { |
| // TODO |
| } |
| |
| @Test |
| public void testCannotHandleSpecific() { |
| Converter ca = converter.newConverterBuilder().rule( |
| new TypeRule<>(Integer.class, Long.class, new Function<Integer,Long>() { |
| @Override |
| public Long apply(Integer obj) { |
| if (obj.intValue() != 1) |
| return new Long(-obj.intValue()); |
| return null; |
| } |
| })).build(); |
| |
| |
| assertEquals(Long.valueOf(-2), ca.convert(Integer.valueOf(2)).to(Long.class)); |
| |
| // This is the exception that the rule cannot handle |
| assertEquals(Long.valueOf(1), ca.convert(Integer.valueOf(1)).to(Long.class)); |
| } |
| |
| @Test |
| public void testWildcardAdapter() { |
| ConverterFunction foo = new ConverterFunction() { |
| @Override |
| public Object apply(Object obj, Type type) throws Exception { |
| if (!(obj instanceof List)) |
| return ConverterFunction.CANNOT_HANDLE; |
| |
| |
| List<?> t = (List<?>) obj; |
| if (t.size() == 0) |
| // Empty list is converted to null |
| return null; |
| |
| if (type instanceof Class) { |
| if (Number.class.isAssignableFrom((Class<?>) type)) |
| return converter.convert(t.size()).to(type); |
| } |
| return ConverterFunction.CANNOT_HANDLE; |
| } |
| }; |
| |
| ConverterBuilder cb = converter.newConverterBuilder(); |
| cb.rule(foo); |
| cb.rule((v,t) -> v.toString()); |
| Converter ca = cb.build(); |
| |
| assertEquals(3L, (long) ca.convert(Arrays.asList("a", "b", "c")).to(Long.class)); |
| assertEquals(3, (long) ca.convert(Arrays.asList("a", "b", "c")).to(Integer.class)); |
| assertEquals("[a, b, c]", ca.convert(Arrays.asList("a", "b", "c")).to(String.class)); |
| assertNull(ca.convert(Arrays.asList()).to(String.class)); |
| } |
| |
| @Test |
| public void testWildcardAdapter1() { |
| ConverterFunction foo = new ConverterFunction() { |
| @Override |
| public Object apply(Object obj, Type type) throws Exception { |
| if (!(obj instanceof List)) |
| return ConverterFunction.CANNOT_HANDLE; |
| |
| List<?> t = (List<?>) obj; |
| if (type instanceof Class) { |
| if (Number.class.isAssignableFrom((Class<?>) type)) |
| return converter.convert(t.size()).to(type); |
| } |
| return ConverterFunction.CANNOT_HANDLE; |
| } |
| }; |
| |
| ConverterBuilder cb = converter.newConverterBuilder(); |
| cb.rule((v,t) -> converter.convert(1).to(t)); |
| cb.rule(foo); |
| Converter ca = cb.build(); |
| |
| // The catchall converter should be called always because it can handle all and was registered first |
| assertEquals(1L, (long) ca.convert(Arrays.asList("a", "b", "c")).to(Long.class)); |
| assertEquals(1, (int) ca.convert(Arrays.asList("a", "b", "c")).to(Integer.class)); |
| assertEquals("1", ca.convert(Arrays.asList("a", "b", "c")).to(String.class)); |
| } |
| |
| @Test |
| public void testWildcardAdapter2() { |
| Map<Object, Object> snooped = new HashMap<>(); |
| ConverterBuilder cb = converter.newConverterBuilder(); |
| cb.rule(new Rule<String[],ArrayList<String>>(v -> { |
| Arrays.sort(v, Collections.reverseOrder()); |
| return new ArrayList<>(Arrays.asList(v)); |
| }) {}); |
| cb.rule(new Rule<String[],List<String>>(v -> { |
| Arrays.sort(v, Collections.reverseOrder()); |
| return new CopyOnWriteArrayList<>(Arrays.asList(v)); |
| }) {}); |
| cb.rule((v,t) -> { snooped.put(v,t); return ConverterFunction.CANNOT_HANDLE;}); |
| Converter ca = cb.build(); |
| |
| assertEquals(new ArrayList<>(Arrays.asList("c", "b", "a")), ca.convert( |
| new String [] {"a", "b", "c"}).to(new TypeReference<ArrayList<String>>() {})); |
| assertEquals("Precondition", 0, snooped.size()); |
| String[] sa0 = new String [] {"a", "b", "c"}; |
| assertEquals(new LinkedList<>(Arrays.asList("a", "b", "c")), ca.convert( |
| sa0).to(LinkedList.class)); |
| assertEquals(1, snooped.size()); |
| assertEquals(LinkedList.class, snooped.get(sa0)); |
| assertEquals(new CopyOnWriteArrayList<>(Arrays.asList("c", "b", "a")), ca.convert( |
| new String [] {"a", "b", "c"}).to(new TypeReference<List<String>>() {})); |
| |
| snooped.clear(); |
| String[] sa = new String [] {"a", "b", "c"}; |
| assertEquals(new CopyOnWriteArrayList<>(Arrays.asList("a", "b", "c")), ca.convert( |
| sa).to(CopyOnWriteArrayList.class)); |
| assertEquals(1, snooped.size()); |
| assertEquals(CopyOnWriteArrayList.class, snooped.get(sa)); |
| } |
| |
| static interface MyIntf { |
| int value(); |
| } |
| |
| static class MyBean implements MyIntf { |
| int intfVal; |
| String beanVal; |
| |
| @Override |
| public int value() { |
| return intfVal; |
| } |
| |
| public String getValue() { |
| return beanVal; |
| } |
| } |
| |
| static class MyCustomDTO { |
| public String field; |
| } |
| } |