diff --git a/core/src/test/java/DefaultPackageTestCase.java b/core/src/test/java/DefaultPackageTestCase.java new file mode 100644 index 00000000..f6b46ba9 --- /dev/null +++ b/core/src/test/java/DefaultPackageTestCase.java @@ -0,0 +1,55 @@ +import org.junit.Assert; +import org.junit.Test; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.OrikaSystemProperties; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.impl.generator.JavassistCompilerStrategy; + +public class DefaultPackageTestCase { + public static class Label { + private String text; + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + } + + public static class XmlLabel { + private String text; + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + } + + @Test + public void test() { + + System.setProperty(OrikaSystemProperties.COMPILER_STRATEGY, + JavassistCompilerStrategy.class.getName()); + + System.setProperty(OrikaSystemProperties.WRITE_SOURCE_FILES, "true"); + System.setProperty(OrikaSystemProperties.WRITE_CLASS_FILES, "true"); + + MapperFactory factory = new DefaultMapperFactory.Builder().build(); + MapperFacade mapper = factory.getMapperFacade(); + + XmlLabel xmlLabel1 = new XmlLabel(); + xmlLabel1.setText("label"); + + Label label = mapper.map(xmlLabel1, Label.class); + + Assert.assertEquals(xmlLabel1.getText(), label.getText()); + + } +} diff --git a/core/src/test/java/ma/glasnost/orika/examples/Example1TestCase.java b/core/src/test/java/ma/glasnost/orika/examples/Example1TestCase.java new file mode 100644 index 00000000..14dedf19 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/examples/Example1TestCase.java @@ -0,0 +1,172 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.examples; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.metadata.Property; +import ma.glasnost.orika.metadata.TypeFactory; +import ma.glasnost.orika.property.IntrospectorPropertyResolver; +import ma.glasnost.orika.property.PropertyResolver; +import ma.glasnost.orika.test.MappingUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.List; + +/** + * @author matt.deboer@gmail.com + * + */ +public class Example1TestCase { + + private static final String NESTED_OPEN = PropertyResolver.ELEMENT_PROPERT_PREFIX; + private static final String NESTED_CLOSE = PropertyResolver.ELEMENT_PROPERT_SUFFIX; + + @Test + public void resolveProperties() { + + PropertyResolver propertyResolver = new IntrospectorPropertyResolver(); + + Property aliasesFirst = propertyResolver.getProperty(TypeFactory.valueOf(PersonDto.class), "aliases" + NESTED_OPEN + "[0]" + NESTED_CLOSE); + + Assert.assertNotNull(aliasesFirst); + Assert.assertEquals(TypeFactory.valueOf(String.class), aliasesFirst.getType()); + Assert.assertNotNull(aliasesFirst.getContainer()); + Assert.assertEquals(TypeFactory.valueOf(String[][].class), aliasesFirst.getContainer().getType()); + } + + /** + * ! + */ + @Test + public void nestedElements() { + + MapperFactory mapperFactory = MappingUtil.getMapperFactory(true); + + mapperFactory.classMap(Person.class, PersonDto.class) + .field("name.first", "firstName") + .field("name.last", "lastName") + .field("knownAliases" + NESTED_OPEN + "first" + NESTED_CLOSE, "aliases" + NESTED_OPEN + "[0]" + NESTED_CLOSE) + .field("knownAliases" + NESTED_OPEN + "last" + NESTED_CLOSE, "aliases" + NESTED_OPEN + "[1]" + NESTED_CLOSE) + .byDefault() + .register(); + + MapperFacade mapper = mapperFactory.getMapperFacade(); + + List aliases = new ArrayList<>(); + aliases.add(new Name("Joe", "Williams")); + aliases.add(new Name("Terry", "Connor")); + Person source = new Person(new Name("John","Doe"), new Date(), aliases); + + PersonDto dest = mapper.map(source, PersonDto.class); + + Assert.assertNotNull(dest); + Assert.assertEquals(source.getName().getFirst(), dest.getFirstName()); + Assert.assertEquals(source.getName().getLast(), dest.getLastName()); + Assert.assertEquals(source.getKnownAliases().get(0).getFirst(), dest.getAliases()[0][0]); + Assert.assertEquals(source.getKnownAliases().get(0).getLast(), dest.getAliases()[0][1]); + Assert.assertEquals(source.getKnownAliases().get(1).getFirst(), dest.getAliases()[1][0]); + Assert.assertEquals(source.getKnownAliases().get(1).getLast(), dest.getAliases()[1][1]); + + } + + public static class Person { + private final Name name; + private final List knownAliases; + private final Date birthDate; + + public Person(Name name, Date birthDate, List knownAliases) { + this.name = name; + this.birthDate = (Date) birthDate.clone(); + this.knownAliases = new ArrayList<>(knownAliases); + } + + public List getKnownAliases() { + return Collections.unmodifiableList(knownAliases); + } + + public Name getName() { + return name; + } + + public Date getBirthDate() { + return (Date) birthDate.clone(); + } + } + + public static class Name { + private final String first; + private final String last; + + public Name(String first, String last) { + this.first = first; + this.last = last; + } + + public String getFirst() { + return first; + } + + public String getLast() { + return last; + } + } + + public static class PersonDto { + private String firstName; + private String lastName; + private Date birthDate; + private String[][] aliases; + + public String getFirstName() { + return firstName; + } + + public String getLastName() { + return lastName; + } + + public Date getBirthDate() { + return birthDate; + } + + public String[][] getAliases() { + return aliases; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public void setBirthDate(Date birthDate) { + this.birthDate = birthDate; + } + + public void setAliases(String[][] aliases) { + this.aliases = aliases; + } + } +} diff --git a/core/src/test/java/ma/glasnost/orika/examples/Example2TestCase.java b/core/src/test/java/ma/glasnost/orika/examples/Example2TestCase.java new file mode 100644 index 00000000..15919bd4 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/examples/Example2TestCase.java @@ -0,0 +1,201 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.examples; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Collection; + +/** + * @author matt.deboer@gmail.com + * + */ +public class Example2TestCase { + + public static class Property { + public String key; + public String value; + + public Property(String key, String value) { + this.key = key; + this.value = value; + } + + public String toString() { + return "[" + key + "=" + value + "]"; + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((key == null) ? 0 : key.hashCode()); + result = prime * result + ((value == null) ? 0 : value.hashCode()); + return result; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Property other = (Property) obj; + if (key == null) { + if (other.key != null) + return false; + } else if (!key.equals(other.key)) + return false; + if (value == null) { + if (other.value != null) + return false; + } else if (!value.equals(other.value)) + return false; + return true; + } + + } + + public static class A { + public A1 a1; + public A2 a2; + public Property p1; + public Property p2; + } + + public static class A1 { + public Property Pa11; + public Property Pa12; + } + + public static class A2 { + public Property Pa21; + public Property Pa22; + } + + public static class B { + public Property p1; + public Property p2; + } + + public static class B1 extends B { + public Property Pb11; + public Property Pb12; + } + + public static class B2 extends B { + public Property Pb21; + public Property Pb22; + } + + /** + * + * How to map the + * + * 1. A.p1 -> b.p1 + * + * 2. A.p2 -> b.p2 + * + * 3. A.a1.Pa11 -> B1.Pb11. + * + * 4. A.a1.Pa12 -> B1.Pb12 + * + * 5. A.a2.Pa11 -> B2.Pb11. + * + * 6. A.a2.Pa12 -> B2.Pb12 + */ + @Test + public void map() { + + /* + * Construct the mapper factory; + */ + MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build(); + + /* + * Register mappings for the fields whose names done match; 'byDefault' covers the matching ones + */ + mapperFactory.classMap(A.class, B1.class) + .field("a1.Pa11", "Pb11") + .field("a1.Pa12", "Pb12") + .byDefault() + .register(); + + mapperFactory.classMap(A.class, B2.class) + .field("a2.Pa21", "Pb21") + .field("a2.Pa22", "Pb22") + .byDefault() + .register(); + + /* + * Construct some test object + */ + A source = new A(); + source.p1 = new Property("p1", "p1.value"); + source.p2 = new Property("p2", "p2.value"); + source.a1 = new A1(); + source.a1.Pa11 = new Property("Pa11", "Pa11.value"); + source.a1.Pa12 = new Property("Pa12", "Pa12.value"); + source.a2 = new A2(); + source.a2.Pa21 = new Property("Pa21", "Pa21.value"); + source.a2.Pa22 = new Property("Pa22", "Pa22.value"); + + MapperFacade mapper = mapperFactory.getMapperFacade(); + + Collection collectionA = new ArrayList<>(); + collectionA.add(source); + + /* + * Map the collection of A into a collection of B1 using 'mapAsList' + */ + Collection collectionB1 = mapper.mapAsList(collectionA, B1.class); + + Assert.assertNotNull(collectionB1); + B1 b1 = collectionB1.iterator().next(); + Assert.assertEquals(source.p1, b1.p1); + Assert.assertEquals(source.p2, b1.p2); + Assert.assertEquals(source.a1.Pa11, b1.Pb11); + Assert.assertEquals(source.a1.Pa12, b1.Pb12); + + /* + * Map the collection of A into a collection of B2 using 'mapAsList' + */ + Collection collectionB2 = mapper.mapAsList(collectionA, B2.class); + + B2 b2 = collectionB2.iterator().next(); + Assert.assertNotNull(b2); + Assert.assertEquals(source.p1, b2.p1); + Assert.assertEquals(source.p2, b2.p2); + Assert.assertEquals(source.a2.Pa21, b2.Pb21); + Assert.assertEquals(source.a2.Pa22, b2.Pb22); + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/BrokenTest.java b/core/src/test/java/ma/glasnost/orika/test/BrokenTest.java new file mode 100644 index 00000000..4f046839 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/BrokenTest.java @@ -0,0 +1,21 @@ +package ma.glasnost.orika.test; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import org.junit.Test; + +import java.util.GregorianCalendar; + +public class BrokenTest { + + @Test + public void testConvertingGregorianCalendar() { + MapperFactory mapperFactory = new DefaultMapperFactory.Builder() + .build(); + + MapperFacade mapperFacade = mapperFactory.getMapperFacade(); + GregorianCalendar gc = new GregorianCalendar(); + Object dest = mapperFacade.map(gc, Object.class); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/ConcurrentRule.java b/core/src/test/java/ma/glasnost/orika/test/ConcurrentRule.java new file mode 100644 index 00000000..c8c129ba --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/ConcurrentRule.java @@ -0,0 +1,137 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test; + +import org.junit.rules.MethodRule; +import org.junit.runners.model.FrameworkMethod; +import org.junit.runners.model.Statement; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.util.concurrent.CompletionService; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorCompletionService; +import java.util.concurrent.Executors; + +/** + * ConcurrentRule is a JUnit Rule which allows a given test method + * to be executed currently by a specified number of threads concurrently.

+ * + * The first Exception thrown by any of the threads is captured and re-thrown + * as the overall exception of the method. + * + * TODO: note that the current implementation also invokes @Before and + * @After methods concurrently; future task is to make this behavior + * configurable. + * + * + * + * @author matt.deboer@gmail.com + * based on work by: Mathieu Carbou (mathieu.carbou@gmail.com) + */ +public final class ConcurrentRule implements MethodRule { + + /** + * Concurrent is used to mark the number of threads which should + * be used to invoke the test method simultaneously. + * + */ + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.METHOD}) + public @interface Concurrent { + int value() default 10; + } + + + /* (non-Javadoc) + * @see org.junit.rules.MethodRule#apply(org.junit.runners.model.Statement, org.junit.runners.model.FrameworkMethod, java.lang.Object) + */ + public Statement apply(final Statement theStatement, final FrameworkMethod theFrameworkMethod, final Object theObject) { + return new Statement() { + + private final FrameworkMethod frameworkMethod = theFrameworkMethod; + private final Statement statement = theStatement; + @SuppressWarnings("unused") + private final Object object = theObject; + + @Override + public void evaluate() throws Throwable { + Concurrent concurrent = frameworkMethod.getAnnotation(Concurrent.class); + if (concurrent == null) + statement.evaluate(); + else { + + /* + * create a completion service to get jobs in the order they finish, to be able + * to cancel remaining jobs as fast as possible if an exception occurs + */ + CompletionService completionService = + new ExecutorCompletionService<>(Executors.newFixedThreadPool(concurrent.value())); + + /* + * Use a latch to pause all threads at a certain point, then + * cause them all to become eligible for execution at once + * for maximum possibility of contention + */ + final CountDownLatch simultaneousStart = new CountDownLatch(1); + + // create the tasks + for (int i = 0; i < concurrent.value(); i++) { + completionService.submit(() -> { + try { + simultaneousStart.await(); + + statement.evaluate(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } catch (Throwable throwable) { + if (throwable instanceof Exception) { + throw (Exception) throwable; + } else if (throwable instanceof Error) { + throw (Error) throwable; + } + RuntimeException r = new RuntimeException(throwable.getMessage(), throwable); + r.setStackTrace(throwable.getStackTrace()); + throw r; + } + return null; + }); + } + simultaneousStart.countDown(); + Throwable throwable = null; + for (int i = 0; i < concurrent.value(); i++) { + try { + completionService.take().get(); + } catch (ExecutionException e) { + // only keep the first exception, but wait for all threads to finish + if(throwable == null) { + throwable = e.getCause(); + } + } + } + if(throwable != null) { + throw throwable; + } + } + } + }; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/DynamicSuite.java b/core/src/test/java/ma/glasnost/orika/test/DynamicSuite.java new file mode 100644 index 00000000..18e1e244 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/DynamicSuite.java @@ -0,0 +1,444 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test; + +import javassist.ClassPool; +import javassist.CtClass; +import javassist.CtConstructor; +import javassist.CtField; +import javassist.CtMethod; +import org.junit.Test; +import org.junit.internal.builders.AllDefaultPossibilitiesBuilder; +import org.junit.runner.Description; +import org.junit.runner.Runner; +import org.junit.runner.notification.RunNotifier; +import org.junit.runners.BlockJUnit4ClassRunner; +import org.junit.runners.ParentRunner; +import org.junit.runners.model.InitializationError; +import org.junit.runners.model.RunnerBuilder; +import org.junit.runners.model.TestClass; + +import java.io.File; +import java.io.UnsupportedEncodingException; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.net.URL; +import java.net.URLClassLoader; +import java.net.URLDecoder; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.regex.Pattern; + +/** + * DynamicSuite resolves and runs a test suite dynamically containing all + * classes matched by a specified pattern.
+ * Use the @RunWith annotation, specifying DyanimcSuite.class as + * the value in order to run a test class as a dynamic suite.
+ *
+ * + * The pattern may be customized by specifying an value with the + * TestCasePattern annotation.
+ *
+ * + * The tests may also be run as a "scenario" by marking the class with the + * @Scenario annotation. Running tests as a scenario will cause all + * of the resolved test cases' methods to be suffixed with the scenario name.
+ * This is necessary in case you want to run these tests again, under a new + * "scenario", since normally, JUnit attempts to avoid running the same test + * method more than once.
+ *
+ * The JUnit 4+ @BeforeClass and @AfterClass + * annotations may used to define setup and tear-down methods to be performed + * before and after the entire suite, respectively. + * + * @author matt.deboer@gmail.com + * + */ +public class DynamicSuite extends ParentRunner { + + private static final String DEFAULT_TEST_CASE_PATTERN = ".*TestCase"; + + /** + * The TestCasePattern annotation specifies the pattern from + * which test case classes should be matched. + */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.TYPE) + public @interface TestCasePattern { + String value(); + } + + /** + * The Scenario annotation is used to mark the dynamic suite + * with a specific name that should be appended to each executed test name. + * This is useful in the case where you want to create multiple copies of a + * particular dynamic suite definition, but would like to run them with + * slightly different configuration for the entire suite (which could be + * achieved using the @BeforeClass and @AfterClass + * annotations for setup/tear-down of the entire suite).
+ *
+ * If the 'name' parameter is not supplied, then the class simpleName is + * used as a default.
+ * Without the unique scenario name, multiple copies of the tests resolved + * by the suite would not be run as JUnit avoids running the same test more + * than once, where uniqueness based on test name. + * + * @see @@org.junit.BeforeClass, @org.junit.AfterClass + * + */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.TYPE) + public @interface Scenario { + String name() default ""; + } + + /** + * Resolves the @Scenario annotation if present; if found, the + * scenario will be given a unique name suffix for all of the tests, + * otherwise, a default scenario is run with no name suffix. + * + * @param testClass + * the class which defines the DynamicSuite + * @return + */ + private static String getScenarioName(TestClass testClass) { + + Scenario s = testClass.getJavaClass().getAnnotation(Scenario.class); + String name = null; + if (s != null) { + name = "".equals(s.name().trim()) ? testClass.getJavaClass() + .getSimpleName() : s.name(); + } + return name; + } + + /** + * Resolves the test classes that are matched by the specified test pattern. + * + * @param theClass + * the root class which defines the DynamicSuite; the + * @TestCasePattern annotation will be used to + * determine the pattern of test cases to include, and the root + * folder will be determined based on the root folder for the + * class-loader of theClass. + * @param + * @return + */ + public static List> findTestCases(Class theClass) { + List classFolders = new ArrayList<>(); + try { + ClassLoader loader = theClass.getClassLoader(); + if (loader instanceof URLClassLoader) { + for (URL url: ((URLClassLoader)loader).getURLs()) { + File file = new File(URLDecoder.decode(url.getFile(), "UTF-8")); + if (file.isDirectory()) { + classFolders.add(file); + } + } + } else { + classFolders.add(new File(URLDecoder.decode(theClass.getResource("/").getFile(), "UTF-8"))); + } + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + String testCaseRegex = getTestCasePattern(theClass); + List> classes = new ArrayList<>(); + for (File classFolder: classFolders) { + classes.addAll(findTestCases(classFolder, testCaseRegex)); + } + return classes; + } + + private static boolean containsTests(Class testClass) { + boolean containsTests = false; + for (Method m: testClass.getMethods()) { + Test test = m.getAnnotation(Test.class); + if (test != null) { + containsTests = true; + break; + } + if (m.getName().startsWith("test") + && Modifier.isPublic(m.getModifiers()) + && !Modifier.isStatic(m.getModifiers())) { + containsTests = true; + break; + } + } + return containsTests; + } + + /** + * Resolves the test classes that are matched by the specified test pattern. + * + * @param classFolder + * the root folder under which to search for test cases + * @param testCaseRegex + * the pattern to use when looking for test cases to include; + * send null to use the value annotated on the class designated + * by the class parameter. + * @return + */ + public static List> findTestCases(File classFolder, + String testCaseRegex) { + try { + Pattern testCasePattern = Pattern.compile(testCaseRegex); + + ClassLoader tccl = Thread.currentThread().getContextClassLoader(); + List> testCases = new ArrayList<>(); + + int classFolderPathLength = classFolder.getAbsolutePath().length(); + + LinkedList stack = new LinkedList<>(Arrays.asList(classFolder.listFiles())); + File currentDirectory = classFolder; + String currentPackage = ""; + while (!stack.isEmpty()) { + + File file = stack.removeFirst(); + + if (file.isDirectory()) { + // push + stack.addAll(Arrays.asList(file.listFiles())); + } else { + if (file.getName().endsWith(".class")) { + String className = file.getAbsolutePath().replace( + classFolder.getAbsolutePath() + File.separator, + ""); + className = className.replaceAll("[\\\\/]", ".") + .replace(".class", ""); + if (testCasePattern.matcher(className).matches()) { + if (!currentDirectory.equals(file.getParentFile())) { + currentDirectory = file.getParentFile(); + currentPackage = currentDirectory + .getAbsolutePath().substring( + classFolderPathLength + 1); + currentPackage = currentPackage.replaceAll( + "[\\/]", "."); + } + Class theClass = Class.forName(className, false, tccl); + if (containsTests(theClass)) { + testCases.add(theClass); + } + } + } + } + } + + return testCases; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Resolves a test class pattern (regular expression) which is used to + * resolve the names of classes that will be included in this test suite. + * + * @param klass + * the class which defines the DynamicSuite + * @return the compiled Pattern + */ + private static String getTestCasePattern(Class klass) { + + String pattern = DEFAULT_TEST_CASE_PATTERN; + TestCasePattern annotation = klass.getAnnotation(TestCasePattern.class); + if (annotation != null) { + pattern = annotation.value(); + } + return pattern; + } + + // ============================================================================= + + private final List fRunners; + private final String name; + + public DynamicSuite(Class klass, RunnerBuilder builder) + throws InitializationError { + this(builder, klass, findTestCases(klass).toArray(new Class[0])); + } + + public DynamicSuite(RunnerBuilder builder, Class[] classes) + throws InitializationError { + this(null, builder.runners(null, classes)); + } + + protected DynamicSuite(Class klass, Class[] suiteClasses) + throws InitializationError { + this(new AllDefaultPossibilitiesBuilder(true), klass, suiteClasses); + } + + protected DynamicSuite(RunnerBuilder builder, Class klass, + Class[] suiteClasses) throws InitializationError { + this(klass, builder.runners(klass, suiteClasses)); + } + + protected DynamicSuite(Class klass, List runners) + throws InitializationError { + super(klass); + try { + TestScenarioProxyFactory proxyFactory = new TestScenarioProxyFactory(); + String scenarioName = getScenarioName(getTestClass()); + + if (scenarioName == null) { + this.fRunners = runners; + this.name = klass.getName(); + } else { + this.name = klass.getName() + "[" + scenarioName + "]"; + this.fRunners = new ArrayList<>(runners.size()); + for (Runner runner : runners) { + if (!(runner instanceof BlockJUnit4ClassRunner)) { + throw new IllegalArgumentException( + "Unexpected Runner type: " + + runner.getClass().getName()); + } + fRunners.add(proxyFactory.forTestScenario(runner, + scenarioName)); + } + } + } catch (Exception e) { + throw new InitializationError(e); + } + + } + + @Override + protected String getName() { + return name; + } + + @Override + protected List getChildren() { + return fRunners; + } + + @Override + protected Description describeChild(Runner child) { + return child.getDescription(); + } + + @Override + protected void runChild(Runner runner, final RunNotifier notifier) { + runner.run(notifier); + } + + /** + * Provides a unique name for each test based on appending the scenario + * name; this is accomplished by sub-classing the existing runner with a + * class which will provide the modified testName value. + * + * @author matt.deboer@gmail.com + * + */ + private static class TestScenarioProxyFactory { + + private final ClassPool pool; + private final ConcurrentHashMap> proxyCache; + + private TestScenarioProxyFactory() { + this.pool = new ClassPool(); + this.pool.appendSystemPath(); + this.proxyCache = new ConcurrentHashMap<>(); + } + + @SuppressWarnings("unchecked") + public Runner forTestScenario(Runner delegate, String scenarioName) { + + final String proxyName = delegate.getClass().getName() + + "_$$_Proxy"; + Class proxyClass = proxyCache.get(proxyName); + if (proxyClass == null) { + + try { + try { + /* + * Try to load the class; in case another javassist pool + * has already created this class, just reuse it. + */ + proxyClass = (Class) pool + .getClassLoader().loadClass(proxyName); + } catch (ClassNotFoundException e) { + synchronized (pool) { + try { + proxyClass = (Class) pool + .getClassLoader().loadClass(proxyName); + } catch (ClassNotFoundException e2) { + /* + * Generate a subclass of the provided type, + * where the testName method is overridden to + * provide the modified name which includes the + * scenario + */ + CtClass superClass = pool.get(delegate + .getClass().getName()); + CtClass subClass = pool.makeClass(proxyName); + subClass.setSuperclass(superClass); + + CtField scenarioNameField = CtField + .make("private java.lang.String scenarioName;", + subClass); + subClass.addField(scenarioNameField); + + CtMethod overriddenMethod = CtMethod + .make("protected java.lang.String testName(org.junit.runners.model.FrameworkMethod method) { \n" + + "return java.lang.String.format(\"%s[%s]\", new Object[]{ super.testName(method), scenarioName});\n" + + "}", subClass); + subClass.addMethod(overriddenMethod); + + CtConstructor constructor = new CtConstructor( + new CtClass[] { + pool.get(Class.class.getName()), + pool.get(String.class.getName()) }, + subClass); + constructor + .setBody("{ super($1); this.scenarioName = $2; }"); + subClass.addConstructor(constructor); + proxyClass = (Class)subClass.toClass(); + + } + } + } + + } catch (Exception e) { + throw new RuntimeException(e); + } + Class existing = proxyCache.putIfAbsent(proxyName, + (Class) proxyClass); + if (existing != null) { + proxyClass = existing; + } + } + + try { + return proxyClass.getConstructor(Class.class, String.class) + .newInstance(delegate.getDescription().getTestClass(), + scenarioName); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/HibernateUtil.java b/core/src/test/java/ma/glasnost/orika/test/HibernateUtil.java new file mode 100644 index 00000000..387c7385 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/HibernateUtil.java @@ -0,0 +1,44 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test; + +import org.hibernate.SessionFactory; +import org.hibernate.cfg.Configuration; + +public final class HibernateUtil { + + private HibernateUtil() { + + } + + public static final SessionFactory sessionFactory; + + static { + try { + sessionFactory = new Configuration().configure().buildSessionFactory(); + } catch (Throwable ex) { + System.err.println("Initial SessionFactory creation failed." + ex); + throw new ExceptionInInitializerError(ex); + } + } + + public static SessionFactory getSessionFactory() { + return sessionFactory; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/InterfaceDefaultMethodTest.java b/core/src/test/java/ma/glasnost/orika/test/InterfaceDefaultMethodTest.java new file mode 100644 index 00000000..0e6a3565 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/InterfaceDefaultMethodTest.java @@ -0,0 +1,46 @@ +package ma.glasnost.orika.test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; + +import org.junit.Test; + +import ma.glasnost.orika.impl.DefaultMapperFactory; + +public class InterfaceDefaultMethodTest { + + @Test + public void defaultInterfaceImplementationsTest() { + DefaultMapperFactory mapperFactory = new DefaultMapperFactory.Builder().build(); + + mapperFactory.classMap(A.class, B.class).byDefault().register(); + + B b = mapperFactory.getMapperFacade().map(new A(), B.class); + assertThat(b, notNullValue()); + assertThat(b.getId(), is("test")); + } + + public static interface BaseA { + + default String getId() { + return "test"; + } + } + + public static class A implements BaseA { + // inherited default methods from Interface + } + + public static class B { + String id; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/JavaDateApiTest.java b/core/src/test/java/ma/glasnost/orika/test/JavaDateApiTest.java new file mode 100644 index 00000000..769e5a23 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/JavaDateApiTest.java @@ -0,0 +1,253 @@ +package ma.glasnost.orika.test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; + +import java.time.DayOfWeek; +import java.time.Duration; +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.Month; +import java.time.MonthDay; +import java.time.OffsetDateTime; +import java.time.OffsetTime; +import java.time.Period; +import java.time.Year; +import java.time.YearMonth; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; + +import org.junit.Test; + +import ma.glasnost.orika.CustomConverter; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.metadata.Type; + +/** + * Support for JSR-310 (Date and Time). + *

+ * + * @see https://github.com/orika-mapper/orika/issues/170 + * @see https://github.com/orika-mapper/orika/issues/96 + */ +public class JavaDateApiTest { + + private static final org.slf4j.Logger LOG = org.slf4j.LoggerFactory.getLogger(JavaDateApiTest.class); + + @Test + public void testJavaDateApiMappings() { + DefaultMapperFactory mapperFactory = new DefaultMapperFactory.Builder().build(); + + // prepare input + A a = new A(); + a.setInstant(Instant.parse("2007-12-03T10:15:30.00Z")); + a.setDuration(Duration.parse("-PT6H3M")); + a.setLocalDate(LocalDate.parse("2007-12-03")); + a.setLocalTime(LocalTime.parse("10:15:30.00")); + a.setLocalDateTime(LocalDateTime.parse("2007-12-03T10:15:30.00")); + a.setZonedDateTime(ZonedDateTime.parse("2007-12-03T10:15:30.00+02:00[Europe/Vienna]")); + a.setDayOfWeek(DayOfWeek.MONDAY); + a.setMonth(Month.JULY); + a.setMonthDay(MonthDay.parse("--12-03")); + a.setOffsetDateTime(OffsetDateTime.parse("2007-12-03T10:15:30.00+02:00")); + a.setOffsetTime(OffsetTime.parse("10:15:30.00+02:00")); + a.setPeriod(Period.parse("-P1Y2M")); + a.setYear(Year.parse("2007")); + a.setYearMonth(YearMonth.parse("2007-12")); + a.setZoneOffset(ZoneOffset.of("+02:00")); + + // run Test: + A mappedA = mapperFactory.getMapperFacade().map(a, A.class); + + // validate result + assertThat(mappedA, notNullValue()); + assertThat(mappedA.getInstant(), is(a.getInstant())); + assertThat(mappedA.getDuration(), is(a.getDuration())); + assertThat(mappedA.getLocalDate(), is(a.getLocalDate())); + assertThat(mappedA.getLocalTime(), is(a.getLocalTime())); + assertThat(mappedA.getLocalDateTime(), is(a.getLocalDateTime())); + assertThat(mappedA.getZonedDateTime(), is(a.getZonedDateTime())); + assertThat(mappedA.getDayOfWeek(), is(a.getDayOfWeek())); + assertThat(mappedA.getMonth(), is(a.getMonth())); + assertThat(mappedA.getMonthDay(), is(a.getMonthDay())); + assertThat(mappedA.getOffsetDateTime(), is(a.getOffsetDateTime())); + assertThat(mappedA.getOffsetTime(), is(a.getOffsetTime())); + assertThat(mappedA.getOffsetTime(), is(a.getOffsetTime())); + assertThat(mappedA.getPeriod(), is(a.getPeriod())); + assertThat(mappedA.getYear(), is(a.getYear())); + assertThat(mappedA.getYearMonth(), is(a.getYearMonth())); + assertThat(mappedA.getZoneOffset(), is(a.getZoneOffset())); + + } + + @Test + public void testJavaDateApiMappings_withCustomConverter_shouldOverwriteDefaultBehavior() { + DefaultMapperFactory mapperFactory = new DefaultMapperFactory.Builder().build(); + mapperFactory.getConverterFactory().registerConverter(new CustomConverter() { + public Instant convert(Instant source, Type destType, MappingContext mappingContext) { + if (source == null) { + return null; + } + // TestCase: add 28 days during Mapping + return source.plus(Period.parse("P28D")); + } + }); + + // prepare input + A a = new A(); + a.setInstant(Instant.parse("2007-03-04T10:15:30.00Z")); + + // run Test: + A mappedA = mapperFactory.getMapperFacade().map(a, A.class); + + // validate result + assertThat(mappedA, notNullValue()); + assertThat(mappedA.getInstant(), is(Instant.parse("2007-04-01T10:15:30.00Z"))); + + } + + public static class A { + + private Instant instant; + private Duration duration; + private LocalDate localDate; + private LocalTime localTime; + private LocalDateTime localDateTime; + private ZonedDateTime zonedDateTime; + private DayOfWeek dayOfWeek; + private Month month; + private MonthDay monthDay; + private OffsetDateTime offsetDateTime; + private OffsetTime offsetTime; + private Period period; + private Year year; + private YearMonth yearMonth; + private ZoneOffset zoneOffset; + + public Instant getInstant() { + return instant; + } + + public void setInstant(Instant instant) { + this.instant = instant; + } + + public Duration getDuration() { + return duration; + } + + public void setDuration(Duration duration) { + this.duration = duration; + } + + public LocalDate getLocalDate() { + return localDate; + } + + public void setLocalDate(LocalDate localDate) { + this.localDate = localDate; + } + + public LocalTime getLocalTime() { + return localTime; + } + + public void setLocalTime(LocalTime localTime) { + this.localTime = localTime; + } + + public LocalDateTime getLocalDateTime() { + return localDateTime; + } + + public void setLocalDateTime(LocalDateTime localDateTime) { + this.localDateTime = localDateTime; + } + + public ZonedDateTime getZonedDateTime() { + return zonedDateTime; + } + + public void setZonedDateTime(ZonedDateTime zonedDateTime) { + this.zonedDateTime = zonedDateTime; + } + + public DayOfWeek getDayOfWeek() { + return dayOfWeek; + } + + public void setDayOfWeek(DayOfWeek dayOfWeek) { + this.dayOfWeek = dayOfWeek; + } + + public Month getMonth() { + return month; + } + + public void setMonth(Month month) { + this.month = month; + } + + public MonthDay getMonthDay() { + return monthDay; + } + + public void setMonthDay(MonthDay monthDay) { + this.monthDay = monthDay; + } + + public OffsetDateTime getOffsetDateTime() { + return offsetDateTime; + } + + public void setOffsetDateTime(OffsetDateTime offsetDateTime) { + this.offsetDateTime = offsetDateTime; + } + + public OffsetTime getOffsetTime() { + return offsetTime; + } + + public void setOffsetTime(OffsetTime offsetTime) { + this.offsetTime = offsetTime; + } + + public Period getPeriod() { + return period; + } + + public void setPeriod(Period period) { + this.period = period; + } + + public Year getYear() { + return year; + } + + public void setYear(Year year) { + this.year = year; + } + + public YearMonth getYearMonth() { + return yearMonth; + } + + public void setYearMonth(YearMonth yearMonth) { + this.yearMonth = yearMonth; + } + + public ZoneOffset getZoneOffset() { + return zoneOffset; + } + + public void setZoneOffset(ZoneOffset zoneOffset) { + this.zoneOffset = zoneOffset; + } + + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/MappingUtil.java b/core/src/test/java/ma/glasnost/orika/test/MappingUtil.java new file mode 100644 index 00000000..e7ea4f55 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/MappingUtil.java @@ -0,0 +1,57 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test; + +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public abstract class MappingUtil { + + public static final String DISABLE_DEBUG_MODE = "ma.glasnost.orika.test.MappingUtil.noDebug"; + + private static final Logger LOGGER = LoggerFactory.getLogger(MappingUtil.class); + + /** + * @return a new default instance of MapperFactory + */ + public static MapperFactory getMapperFactory() { + return new DefaultMapperFactory.Builder().build(); + } + + /** + * @return a new default instance of MapperFactory, with the specified debug + * mode configuration. + * @param debugMode if true, EclipseJdt will be used for the compiler + * strategy (for step-debugging in IDEs), and class and source files will be written to disk. + */ + public static MapperFactory getMapperFactory(boolean debugMode) { + if (debugMode) { + if (Boolean.parseBoolean(System.getProperty(DISABLE_DEBUG_MODE))) { + LOGGER.warn("Debug mode was requested via MappingUtil when it was explicitly disabled"); + return getMapperFactory(); + } else { + return new DefaultMapperFactory.Builder().build(); + } + } else { + return getMapperFactory(); + } + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/MavenProjectUtil.java b/core/src/test/java/ma/glasnost/orika/test/MavenProjectUtil.java new file mode 100644 index 00000000..20c5d369 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/MavenProjectUtil.java @@ -0,0 +1,53 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test; + +import java.io.File; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; + +/** + * MavenProjectUtil provides lookup of the current project's root folder, + * assuming the default compile directory somewhere beneath the 'target' folder; + * uses lookup of the current class' class-file as a resource and walks up + * to the target folder + * + * @author matt.deboer@gmail.com + * + */ +public class MavenProjectUtil { + public static File findProjectRoot() { + File classFile; + try { + classFile = new File(URLDecoder.decode( + MavenProjectUtil.class.getClassLoader().getResource(MavenProjectUtil.class.getName().replace(".","/") + ".class").getFile(),"UTF-8")); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException("Failed to get Maven project root",e); + } + File classFolder = classFile; + for (int i=0, len=MavenProjectUtil.class.getName().split("\\.").length; i < len; ++i) + classFolder = classFolder.getParentFile(); + + while(classFolder != null && !(classFolder.isDirectory() && "target".equals(classFolder.getName()))) + classFolder = classFolder.getParentFile(); + + return classFolder != null ? classFolder.getParentFile() : null; + + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/TestUtil.java b/core/src/test/java/ma/glasnost/orika/test/TestUtil.java new file mode 100644 index 00000000..c7dc6a7e --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/TestUtil.java @@ -0,0 +1,75 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test; + +public final class TestUtil { + + private static final org.slf4j.Logger LOG = org.slf4j.LoggerFactory.getLogger(TestUtil.class); + + /** + * @see #expectException(MethodToCall, Class) + * @param call + * The Method to test + * @return The expected Exception + */ + public static Exception expectException(final MethodToCall call) { + return expectException(call, Exception.class); + } + /** + * Test the Exception-Case of your Logic. + *

+ * Example Usage: + *

+ * + *
+     * MyException expectedException = TestUtils.expectException(() -> myService.myMethodToTest(), MyException.class);
+     *
+     * assertThat(expectedException.getMessage(), containsString("..."));
+     * 
+ * + * @param + * The type of the expected Exception. + * @param call + * The Method to test + * @param expectedExceptionType + * . + * @return The expected Exception + */ + @SuppressWarnings("unchecked") + public static T expectException(final MethodToCall call, final Class expectedExceptionType) { + try { + call.run(); + throw new AssertionError("The Method should throw an Exception"); + } catch (final Exception e) { + if (!expectedExceptionType.isInstance(e)) { + LOG.info("Wrong Exception: " + e.getMessage(), e); + throw new AssertionError("Wrong Exception instance: " + e.getClass() + ". Message: " + e.getMessage()); + } + return (T) e; + } + } + + /** + * Functional Interface for {@link TestUtil#expectException(MethodToCall, Class)}. + * + * @FunctionalInterface + */ + public interface MethodToCall { + void run() throws Exception; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/array/ArrayTestCase.java b/core/src/test/java/ma/glasnost/orika/test/array/ArrayTestCase.java new file mode 100644 index 00000000..7122405c --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/array/ArrayTestCase.java @@ -0,0 +1,140 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.array; + +import java.util.Arrays; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.test.MappingUtil; + +import org.junit.Assert; +import org.junit.Test; + +public class ArrayTestCase { + + @Test + public void testSimplePrimitiveArray() { + ArrayTestCaseClasses.A source = new ArrayTestCaseClasses.A(); + byte[] buffer = new byte[]{1,2,3,4}; + source.setBuffer(buffer); + + MapperFacade mapperFacade = MappingUtil.getMapperFactory().getMapperFacade(); + + ArrayTestCaseClasses.B destination = mapperFacade.map(source, ArrayTestCaseClasses.B.class); + + Assert.assertArrayEquals(source.getBuffer(), destination.getBuffer()); + + } + + @Test + public void testSimplePrimitiveToWrapperArray() { + ArrayTestCaseClasses.A source = new ArrayTestCaseClasses.A(); + byte[] buffer = new byte[]{1,2,3,4}; + source.setBuffer(buffer); + + MapperFacade mapperFacade = MappingUtil.getMapperFactory().getMapperFacade(); + + ArrayTestCaseClasses.C destination = mapperFacade.map(source, ArrayTestCaseClasses.C.class); + + Assert.assertArrayEquals(new Byte[]{1,2,3,4}, destination.getBuffer()); + } + + @Test + public void testArrayToList() { + MapperFacade mapperFacade = MappingUtil.getMapperFactory().getMapperFacade(); + + ArrayTestCaseClasses.A source = new ArrayTestCaseClasses.A(); + byte[] buffer = new byte[]{1,2,3,4}; + source.setBuffer(buffer); + + + ArrayTestCaseClasses.D destination = mapperFacade.map(source, ArrayTestCaseClasses.D.class); + + Assert.assertEquals(Arrays.asList((byte)1,(byte)2,(byte)3,(byte)4), destination.getBuffer()); + + } + + @Test + public void testWrapperArrayToList() { + MapperFacade mapperFacade = MappingUtil.getMapperFactory().getMapperFacade(); + + ArrayTestCaseClasses.C source = new ArrayTestCaseClasses.C(); + Byte[] buffer = new Byte[]{1,2,3,4}; + source.setBuffer(buffer); + + + ArrayTestCaseClasses.D destination = mapperFacade.map(source, ArrayTestCaseClasses.D.class); + + Assert.assertEquals(Arrays.asList((byte)1,(byte)2,(byte)3,(byte)4), destination.getBuffer()); + + } + + @Test + public void testListToArray() { + MapperFacade mapperFacade = MappingUtil.getMapperFactory().getMapperFacade(); + + ArrayTestCaseClasses.D source = new ArrayTestCaseClasses.D(); + source.setBuffer(Arrays.asList((byte)1,(byte)2,(byte)3,(byte)4)); + + + ArrayTestCaseClasses.A destination = mapperFacade.map(source, ArrayTestCaseClasses.A.class); + + Assert.assertArrayEquals(new byte[] {(byte)1,(byte)2,(byte)3,(byte)4}, destination.getBuffer()); + + } + + @Test + public void testMappingArrayOfString() { + + Product p = new Product(); + p.setTags(new String[] { "music", "sport" }); + + ProductDTO productDTO = MappingUtil.getMapperFactory().getMapperFacade().map(p, ProductDTO.class); + + Assert.assertArrayEquals(p.getTags(), productDTO.getTags()); + } + + public static class Product { + + private String[] tags; + + public String[] getTags() { + return tags.clone(); + } + + public void setTags(String[] tags) { + this.tags = tags; + } + + } + + public static class ProductDTO { + + private String[] tags; + + public String[] getTags() { + return tags.clone(); + } + + public void setTags(String[] tags) { + this.tags = tags; + } + + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/array/ArrayTestCaseClasses.java b/core/src/test/java/ma/glasnost/orika/test/array/ArrayTestCaseClasses.java new file mode 100644 index 00000000..bfc24625 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/array/ArrayTestCaseClasses.java @@ -0,0 +1,74 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.array; + +import java.util.List; + +public class ArrayTestCaseClasses { + + public static class A { + private byte[] buffer; + + public byte[] getBuffer() { + return buffer; + } + + public void setBuffer(byte[] buffer) { + this.buffer = buffer; + } + } + + public static class B { + private byte[] buffer; + + public byte[] getBuffer() { + return buffer; + } + + public void setBuffer(byte[] buffer) { + this.buffer = buffer; + } + } + + public static class C { + private Byte[] buffer; + + public Byte[] getBuffer() { + return buffer; + } + + public void setBuffer(Byte[] buffer) { + this.buffer = buffer; + } + } + + public static class D { + private List buffer; + + public List getBuffer() { + return buffer; + } + + public void setBuffer(List buffer) { + this.buffer = buffer; + } + + + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/ArrayTestCase.java b/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/ArrayTestCase.java new file mode 100644 index 00000000..b0722dde --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/ArrayTestCase.java @@ -0,0 +1,130 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.boundmapperfacade; + +import java.util.Arrays; + +import ma.glasnost.orika.BoundMapperFacade; +import ma.glasnost.orika.test.MappingUtil; +import ma.glasnost.orika.test.array.ArrayTestCaseClasses; +import ma.glasnost.orika.test.array.ArrayTestCaseClasses.A; +import ma.glasnost.orika.test.array.ArrayTestCaseClasses.B; +import ma.glasnost.orika.test.array.ArrayTestCaseClasses.C; +import ma.glasnost.orika.test.array.ArrayTestCaseClasses.D; + +import org.junit.Assert; +import org.junit.Test; + +public class ArrayTestCase { + + @Test + public void testSimplePrimitiveArray() { + ArrayTestCaseClasses.A source = new ArrayTestCaseClasses.A(); + byte[] buffer = new byte[]{1,2,3,4}; + source.setBuffer(buffer); + + BoundMapperFacade mapperFacade = MappingUtil.getMapperFactory().getMapperFacade(ArrayTestCaseClasses.A.class, ArrayTestCaseClasses.B.class); + + ArrayTestCaseClasses.B destination = mapperFacade.map(source); + + Assert.assertArrayEquals(source.getBuffer(), destination.getBuffer()); + + } + + @Test + public void testSimplePrimitiveToWrapperArray() { + ArrayTestCaseClasses.A source = new ArrayTestCaseClasses.A(); + byte[] buffer = new byte[]{1,2,3,4}; + source.setBuffer(buffer); + + BoundMapperFacade mapperFacade = MappingUtil.getMapperFactory().getMapperFacade(A.class, C.class); + + ArrayTestCaseClasses.C destination = mapperFacade.map(source); + + Assert.assertArrayEquals(new Byte[]{1,2,3,4}, destination.getBuffer()); + } + + @Test + public void testArrayToList() { + BoundMapperFacade mapperFacade = MappingUtil.getMapperFactory().getMapperFacade(A.class, D.class); + + ArrayTestCaseClasses.A source = new ArrayTestCaseClasses.A(); + byte[] buffer = new byte[]{1,2,3,4}; + source.setBuffer(buffer); + + + D destination = mapperFacade.map(source); + + Assert.assertEquals(Arrays.asList((byte)1,(byte)2,(byte)3,(byte)4), destination.getBuffer()); + + } + + @Test + public void testListToArray() { + BoundMapperFacade mapperFacade = MappingUtil.getMapperFactory().getMapperFacade(A.class, D.class); + + D source = new D(); + source.setBuffer(Arrays.asList((byte)1,(byte)2,(byte)3,(byte)4)); + + + A destination = mapperFacade.mapReverse(source); + + Assert.assertArrayEquals(new byte[] {(byte)1,(byte)2,(byte)3,(byte)4}, destination.getBuffer()); + + } + + @Test + public void testMappingArrayOfString() { + + Product p = new Product(); + p.setTags(new String[] { "music", "sport" }); + + ProductDTO productDTO = MappingUtil.getMapperFactory().getMapperFacade(Product.class, ProductDTO.class).map(p); + + Assert.assertArrayEquals(p.getTags(), productDTO.getTags()); + } + + public static class Product { + + private String[] tags; + + public String[] getTags() { + return tags; + } + + public void setTags(String[] tags) { + this.tags = tags; + } + + } + + public static class ProductDTO { + + private String[] tags; + + public String[] getTags() { + return tags; + } + + public void setTags(String[] tags) { + this.tags = tags; + } + + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/BidirectionalMappingTestCase.java b/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/BidirectionalMappingTestCase.java new file mode 100644 index 00000000..5c388321 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/BidirectionalMappingTestCase.java @@ -0,0 +1,159 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.boundmapperfacade; + +import ma.glasnost.orika.BoundMapperFacade; +import ma.glasnost.orika.test.MappingUtil; + +import org.junit.Assert; +import org.junit.Test; + +public class BidirectionalMappingTestCase { + + @Test + public void testBidirectionalMapping() { + BoundMapperFacade mapper = MappingUtil.getMapperFactory().getMapperFacade(Book.class, BookDTO.class); + + Author author = new Author(); + author.setFirstName("Khalil"); + author.setLastName("Gibran"); + + Book book = new Book(); + book.setTitle("The Prophet"); + book.setAuthor(author); + author.setBook(book); + + BookDTO dto = mapper.map(book); + + Assert.assertEquals(book.getTitle(), dto.getTitle()); + Assert.assertEquals(book.getAuthor().getFirstName(), dto.getAuthor().getFirstName()); + + Assert.assertEquals(book.getAuthor().getLastName(), dto.getAuthor().getLastName()); + + Assert.assertTrue(dto == dto.getAuthor().getBook()); + } + + public static class Author { + private String firstName; + private String lastName; + private Book book; + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public Book getBook() { + return book; + } + + public void setBook(Book book) { + this.book = book; + } + + } + + public static class Book { + + private String title; + + private Author author; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public Author getAuthor() { + return author; + } + + public void setAuthor(Author author) { + this.author = author; + } + } + + public static class AuthorDTO { + private String firstName; + private String lastName; + private BookDTO book; + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public BookDTO getBook() { + return book; + } + + public void setBook(BookDTO book) { + this.book = book; + } + } + + public static class BookDTO { + + private String title; + + private AuthorDTO author; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public AuthorDTO getAuthor() { + return author; + } + + public void setAuthor(AuthorDTO author) { + this.author = author; + } + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/CollectionTestCase.java b/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/CollectionTestCase.java new file mode 100644 index 00000000..4d01daa8 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/CollectionTestCase.java @@ -0,0 +1,91 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.boundmapperfacade; + +import ma.glasnost.orika.test.MappingUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Set; + +public class CollectionTestCase { + + @Test + public void testStringToString() { + D source = new D(); + source.setTags(Arrays.asList("soa", "java", "rest")); + + A destination = MappingUtil.getMapperFactory().getMapperFacade(D.class, A.class).map(source); + + Assert.assertNotNull(destination.getTags()); + Assert.assertEquals(3, destination.getTags().size()); + } + + @Test + public void testStringToStringWithGetterOnlyCollection() { + D source = new D(); + source.setTags(Arrays.asList("soa", "java", "rest")); + + B destination = MappingUtil.getMapperFactory().getMapperFacade(D.class, B.class).map(source); + + Assert.assertNotNull(destination.getTags()); + Assert.assertEquals(3, destination.getTags().size()); + } + + static public class A { + private Set tags; + + public Set getTags() { + return tags; + } + + public void setTags(Set tags) { + this.tags = tags; + } + } + + public static class D { + private List tags; + + public List getTags() { + return tags; + } + + public void setTags(List tags) { + this.tags = tags; + } + } + + public static class B { + + private List tags; + + // Collection as typically generated by JAXB + public List getTags() { + if (tags==null) { + tags = new ArrayList<>(); + } + return tags; + } + + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/ConstructorMappingTestCase.java b/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/ConstructorMappingTestCase.java new file mode 100644 index 00000000..f5e246bd --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/ConstructorMappingTestCase.java @@ -0,0 +1,596 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.boundmapperfacade; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.converter.builtin.DateToStringConverter; +import ma.glasnost.orika.test.MappingUtil; +import ma.glasnost.orika.test.common.types.TestCaseClasses.Author; +import ma.glasnost.orika.test.common.types.TestCaseClasses.AuthorDTO; +import ma.glasnost.orika.test.common.types.TestCaseClasses.AuthorImpl; +import ma.glasnost.orika.test.common.types.TestCaseClasses.AuthorNested; +import ma.glasnost.orika.test.common.types.TestCaseClasses.Book; +import ma.glasnost.orika.test.common.types.TestCaseClasses.BookDTO; +import ma.glasnost.orika.test.common.types.TestCaseClasses.BookImpl; +import ma.glasnost.orika.test.common.types.TestCaseClasses.BookNested; +import ma.glasnost.orika.test.common.types.TestCaseClasses.Library; +import ma.glasnost.orika.test.common.types.TestCaseClasses.LibraryDTO; +import ma.glasnost.orika.test.common.types.TestCaseClasses.LibraryImpl; +import ma.glasnost.orika.test.common.types.TestCaseClasses.LibraryNested; +import ma.glasnost.orika.test.common.types.TestCaseClasses.Name; +import ma.glasnost.orika.test.common.types.TestCaseClasses.PrimitiveHolder; +import ma.glasnost.orika.test.common.types.TestCaseClasses.PrimitiveHolderDTO; +import ma.glasnost.orika.test.common.types.TestCaseClasses.PrimitiveWrapperHolder; +import ma.glasnost.orika.test.common.types.TestCaseClasses.PrimitiveWrapperHolderDTO; +import ma.glasnost.orika.test.constructor.TestCaseClasses.Holder; +import ma.glasnost.orika.test.constructor.TestCaseClasses.NestedPrimitiveHolder; +import ma.glasnost.orika.test.constructor.TestCaseClasses.Person; +import ma.glasnost.orika.test.constructor.TestCaseClasses.PersonVO; +import ma.glasnost.orika.test.constructor.TestCaseClasses.PersonVO2; +import ma.glasnost.orika.test.constructor.TestCaseClasses.PersonVO3; +import ma.glasnost.orika.test.constructor.TestCaseClasses.PrimitiveNumberHolder; +import ma.glasnost.orika.test.constructor.TestCaseClasses.WrapperHolder; +import org.junit.Assert; +import org.junit.Test; + +import java.net.URL; +import java.net.URLStreamHandler; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +public class ConstructorMappingTestCase { + + private static final String DATE_CONVERTER = "dateConverter"; + private static final String DATE_PATTERN = "dd/MM/yyyy"; + + @Test + public void testSimpleCase() throws Throwable { + + final SimpleDateFormat df = new SimpleDateFormat(DATE_PATTERN); + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.classMap(PersonVO.class, Person.class) + //.constructorA() + .fieldMap("dateOfBirth", "date") + .converter(DATE_CONVERTER) + .add() + .byDefault() + .register(); + factory.getConverterFactory().registerConverter(DATE_CONVERTER, new DateToStringConverter(DATE_PATTERN)); + + + + Person person = new Person(); + person.setFirstName("Abdelkrim"); + person.setLastName("EL KHETTABI"); + person.setDate(df.parse("01/01/1980")); + person.setAge(31L); + + PersonVO vo = factory.getMapperFacade(Person.class, PersonVO.class).map(person); + + Assert.assertEquals(person.getFirstName(), vo.getFirstName()); + Assert.assertEquals(person.getLastName(), vo.getLastName()); + Assert.assertTrue(person.getAge() == vo.getAge()); + Assert.assertEquals("01/01/1980", vo.getDateOfBirth()); + } + + + @Test + public void testFindConstructor() throws Throwable { + final SimpleDateFormat df = new SimpleDateFormat(DATE_PATTERN); + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.classMap(PersonVO3.class, Person.class) + .fieldMap("dateOfBirth", "date").converter(DATE_CONVERTER).add() + .byDefault() + .register(); + factory.getConverterFactory().registerConverter(DATE_CONVERTER, new DateToStringConverter(DATE_PATTERN)); + + + Person person = new Person(); + person.setFirstName("Abdelkrim"); + person.setLastName("EL KHETTABI"); + person.setDate(df.parse("01/01/1980")); + person.setAge(31L); + + PersonVO3 vo = factory.getMapperFacade(Person.class, PersonVO3.class).map(person); + + Assert.assertEquals(person.getFirstName(), vo.getFirstName()); + Assert.assertEquals(person.getLastName(), vo.getLastName()); + Assert.assertTrue(person.getAge() == vo.getAge()); + Assert.assertEquals("01/01/1980", vo.getDateOfBirth()); + } + + public static long yearsDifference(final Date start, final Date end) { + long diff = end.getTime() - start.getTime(); + return diff / TimeUnit.SECONDS.toMillis(60*60*24*365); + } + + @Test + public void testFindConstructor2() throws Throwable { + final SimpleDateFormat df = new SimpleDateFormat(DATE_PATTERN); + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.classMap(PersonVO3.class, Person.class) + .field("firstName", "firstName") + .field("lastName", "lastName") + .field("dateOfBirth", "date") + .register(); + factory.getConverterFactory().registerConverter(DATE_CONVERTER, new DateToStringConverter(DATE_PATTERN)); + + Person person = new Person(); + person.setFirstName("Abdelkrim"); + person.setLastName("EL KHETTABI"); + person.setDate(df.parse("01/01/1980")); + + Calendar c = Calendar.getInstance(); + c.set(Calendar.YEAR, 1980); + c.set(Calendar.MONTH, 0); + c.set(Calendar.DAY_OF_MONTH, 1); + + person.setAge(yearsDifference(c.getTime(), new Date())); + + PersonVO3 vo = factory.getMapperFacade(Person.class, PersonVO3.class).map(person); + + Assert.assertEquals(person.getFirstName(), vo.getFirstName()); + Assert.assertEquals(person.getLastName(), vo.getLastName()); + Assert.assertTrue(person.getAge() == vo.getAge()); + Assert.assertEquals("01/01/1980", vo.getDateOfBirth()); + } + + @Test + public void testAutomaticCaseWithHint() throws Throwable { + + final SimpleDateFormat df = new SimpleDateFormat(DATE_PATTERN); + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.registerDefaultFieldMapper((fromProperty, fromPropertyType) -> { + if ("dateOfBirth".equals(fromProperty)) { + return "date"; + } else if("date".equals(fromProperty)) { + return "dateOfBirth"; + } + return null; + }); + + factory.getConverterFactory().registerConverter(new DateToStringConverter(DATE_PATTERN)); + + + Person person = new Person(); + person.setFirstName("Abdelkrim"); + person.setLastName("EL KHETTABI"); + person.setDate(df.parse("01/01/1980")); + person.setAge(31L); + + PersonVO vo = factory.getMapperFacade().map(person, PersonVO.class); + + Assert.assertEquals(person.getFirstName(), vo.getFirstName()); + Assert.assertEquals(person.getLastName(), vo.getLastName()); + Assert.assertTrue(person.getAge() == vo.getAge()); + Assert.assertEquals("01/01/1980", vo.getDateOfBirth()); + } + + @Test + public void testPrimitiveToPrimitiveTypes() { + + PrimitiveHolder primitiveHolder = + new PrimitiveHolder( + Short.MAX_VALUE, + Integer.MAX_VALUE, + Long.MAX_VALUE, + Float.MAX_VALUE, + Double.MAX_VALUE, + Character.MAX_VALUE, + true, + Byte.MAX_VALUE); + + MapperFactory factory = MappingUtil.getMapperFactory(); + + PrimitiveHolderDTO dto = factory.getMapperFacade().map(primitiveHolder, PrimitiveHolderDTO.class); + + assertValidMapping(primitiveHolder,dto); + + PrimitiveHolder mapBack = factory.getMapperFacade().map(dto, PrimitiveHolder.class); + + assertValidMapping(mapBack, dto); + } + + @Test + public void testPrimitiveToWrapperTypes() { + + PrimitiveHolder primitiveHolder = + new PrimitiveHolder( + Short.MAX_VALUE, + Integer.MAX_VALUE, + Long.MAX_VALUE, + Float.MAX_VALUE, + Double.MAX_VALUE, + Character.MAX_VALUE, + true, + Byte.MAX_VALUE); + + MapperFactory factory = MappingUtil.getMapperFactory(); + + PrimitiveWrapperHolder wrapper = factory.getMapperFacade().map(primitiveHolder, PrimitiveWrapperHolder.class); + + assertValidMapping(wrapper, primitiveHolder); + + PrimitiveHolder mapBack = factory.getMapperFacade().map(wrapper, PrimitiveHolder.class); + + assertValidMapping(wrapper, mapBack); + } + + @Test + public void testWrapperToWrapperTypes() { + + PrimitiveWrapperHolder primitiveHolder = + new PrimitiveWrapperHolder( + Short.MAX_VALUE, + Integer.MAX_VALUE, + Long.MAX_VALUE, + Float.MAX_VALUE, + Double.MAX_VALUE, + Character.MAX_VALUE, + true, + Byte.MAX_VALUE); + + MapperFactory factory = MappingUtil.getMapperFactory(); + + PrimitiveWrapperHolderDTO dto = factory.getMapperFacade().map(primitiveHolder, PrimitiveWrapperHolderDTO.class); + + assertValidMapping(primitiveHolder, dto); + + PrimitiveWrapperHolder mapBack = factory.getMapperFacade().map(dto, PrimitiveWrapperHolder.class); + + assertValidMapping(mapBack, dto); + } + + @Test + public void testPrimitivePropertiesWithWrapperConstructor() throws Throwable { + + final SimpleDateFormat df = new SimpleDateFormat(DATE_PATTERN); + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.registerDefaultFieldMapper((fromProperty, fromPropertyType) -> { + if ("dateOfBirth".equals(fromProperty)) { + return "date"; + } else if("date".equals(fromProperty)) { + return "dateOfBirth"; + } + return null; + }); + + factory.getConverterFactory().registerConverter(new DateToStringConverter(DATE_PATTERN)); + + Person person = new Person(); + person.setFirstName("Abdelkrim"); + person.setLastName("EL KHETTABI"); + person.setDate(df.parse("01/01/1980")); + person.setAge(31L); + + PersonVO2 vo = factory.getMapperFacade().map(person, PersonVO2.class); + + Assert.assertEquals(person.getFirstName(), vo.getFirstName()); + Assert.assertEquals(person.getLastName(), vo.getLastName()); + Assert.assertTrue(person.getAge() == vo.getAge()); + Assert.assertEquals("01/01/1980", vo.getDateOfBirth()); + + } + + @Test + public void testBaseCaseWithCollectionTypes() { + + List books = new ArrayList<>(4); + + Author author1 = new AuthorImpl("Author #1"); + Author author2 = new AuthorImpl("Author #2"); + + books.add(new BookImpl("Book #1", author1)); + books.add(new BookImpl("Book #2", author1)); + books.add(new BookImpl("Book #3", author2)); + books.add(new BookImpl("Book #4", author2)); + + Library library = new LibraryImpl("Library #1", books); + + MapperFactory factory = MappingUtil.getMapperFactory(); + MapperFacade mapper = factory.getMapperFacade(); + + LibraryDTO mapped = mapper.map(library, LibraryDTO.class); + + assertValidMapping(library,mapped); + + Library libraryMapBack = mapper.map(mapped, LibraryImpl.class); + + assertValidMapping(libraryMapBack,mapped); + + } + + @Test + public void testMappingNestedTypes() { + + List books = new ArrayList<>(4); + + AuthorNested author1 = new AuthorNested(new Name("Abdelkrim","EL KHETTABI")); + AuthorNested author2 = new AuthorNested(new Name("Bill","Shakespeare")); + + books.add(new BookNested("Book #1", author1)); + books.add(new BookNested("Book #2", author1)); + books.add(new BookNested("Book #3", author2)); + books.add(new BookNested("Book #4", author2)); + + LibraryNested library = new LibraryNested("Library #1", books); + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.classMap(AuthorNested.class, AuthorDTO.class) + .field("name.fullName", "name") + .byDefault() + .register(); + + MapperFacade mapper = factory.getMapperFacade(); + + LibraryDTO mapped = mapper.map(library, LibraryDTO.class); + + assertValidMapping(library,mapped); + + /* + // this situation is a bit too complicated to handle normally; + // how would Orika even know how to create a Name object which takes + // in multiple parameters it cannot find on the source object? + LibraryNested libraryMapBack = mapper.map(mapped, LibraryNested.class); + + assertValidMapping(libraryMapBack,mapped); + + */ + } + + + @Test + public void testComplexMappingNestedTypes() { + + + PrimitiveNumberHolder numbers = + new PrimitiveNumberHolder( + Short.MAX_VALUE, + Integer.MAX_VALUE, + Long.MAX_VALUE, + Float.MAX_VALUE, + Double.MAX_VALUE); + + NestedPrimitiveHolder primitiveHolder = new NestedPrimitiveHolder(numbers, Character.MAX_VALUE, Boolean.TRUE, Byte.MAX_VALUE); + + Holder holder = new Holder(primitiveHolder); + + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.classMap(NestedPrimitiveHolder.class, PrimitiveWrapperHolder.class) + .field("numbers.shortValue", "shortValue") + .field("numbers.intValue", "intValue") + .field("numbers.longValue", "longValue") + .field("numbers.floatValue", "floatValue") + .field("numbers.doubleValue", "doubleValue") + .byDefault() + .register(); + + WrapperHolder wrapper = factory.getMapperFacade().map(holder, WrapperHolder.class); + + assertValidMapping(holder, wrapper); + + } + + + public static class URLDto1 { + public String protocolX; + public String hostX; + public int portX; + public String fileX; + } + + public static class URLDto2 { + public String protocol; + public String host; + public String file; + } + + public static class URLDto3 { + public String protocol; + public String host; + public int port; + public String file; + public URLStreamHandler handler; + } + + public static class URLDto4 { + public URL context; + public String spec; + } + + @Test + public void testConstructorsWithoutDebugInfo() { + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.registerClassMap( + factory.classMap(URLDto1.class, URL.class) + .field("protocolX", "protocol") + .field("hostX", "host") + .field("portX", "port") + .field("fileX", "file")); + MapperFacade mapper = factory.getMapperFacade(); + + URLDto1 dto1 = new URLDto1(); + dto1.protocolX = "http"; + dto1.hostX = "somewhere.com"; + dto1.portX = 8080; + dto1.fileX = "index.html"; + + URL url = mapper.map(dto1, URL.class); + Assert.assertNotNull(url); + Assert.assertEquals(dto1.protocolX, url.getProtocol()); + Assert.assertEquals(dto1.hostX, url.getHost()); + Assert.assertEquals(dto1.portX, url.getPort()); + + } + + @Test + public void testForUnexpectedRuntimeException() { + MapperFactory factory = MappingUtil.getMapperFactory(); + URLDto1 dto1 = new URLDto1(); + dto1.protocolX = "http"; + dto1.hostX = "somewhere.com"; + dto1.portX = 8080; + dto1.fileX = "index.html"; + Map map = factory.getMapperFacade(URLDto1.class, Map.class).map(dto1); + Assert.assertEquals(map.get("protocolX"), dto1.protocolX); + Assert.assertEquals(map.get("hostX"), dto1.hostX); + Assert.assertEquals(map.get("portX"), dto1.portX); + Assert.assertEquals(map.get("fileX"), dto1.fileX); + } + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Common mapping validations + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + private void assertValidMapping(Holder holder, WrapperHolder dto) { + assertValidMapping(holder.getNested(), dto.getNested()); + } + + private void assertValidMapping(NestedPrimitiveHolder nested, PrimitiveWrapperHolder wrapper) { + assertEquals(nested.getNumbers().getShortValue(), wrapper.getShortValue().shortValue()); + assertEquals(nested.getNumbers().getIntValue(), wrapper.getIntValue().intValue()); + assertEquals(nested.getNumbers().getLongValue(), wrapper.getLongValue().longValue()); + assertEquals(nested.getNumbers().getFloatValue(), wrapper.getFloatValue(), 1.0f); + assertEquals(nested.getNumbers().getDoubleValue(), wrapper.getDoubleValue(), 1.0d); + assertEquals(nested.getCharValue(), wrapper.getCharValue().charValue()); + assertEquals(nested.isBooleanValue(), wrapper.getBooleanValue()); + assertEquals(nested.getByteValue(), wrapper.getByteValue().byteValue()); + } + + private void assertValidMapping(PrimitiveHolder primitiveHolder, PrimitiveHolderDTO dto) { + assertEquals(primitiveHolder.getShortValue(), dto.getShortValue()); + assertEquals(primitiveHolder.getIntValue(), dto.getIntValue()); + assertEquals(primitiveHolder.getLongValue(), dto.getLongValue()); + assertEquals(primitiveHolder.getFloatValue(), dto.getFloatValue(), 1.0f); + assertEquals(primitiveHolder.getDoubleValue(), dto.getDoubleValue(), 1.0d); + assertEquals(primitiveHolder.getCharValue(), dto.getCharValue()); + assertEquals(primitiveHolder.isBooleanValue(), dto.isBooleanValue()); + assertEquals(primitiveHolder.getByteValue(), dto.getByteValue()); + } + + private void assertValidMapping(PrimitiveWrapperHolder primitiveHolder, PrimitiveWrapperHolderDTO dto) { + assertEquals(primitiveHolder.getShortValue(), dto.getShortValue()); + assertEquals(primitiveHolder.getIntValue(), dto.getIntValue()); + assertEquals(primitiveHolder.getLongValue(), dto.getLongValue()); + assertEquals(primitiveHolder.getFloatValue(), dto.getFloatValue(), 1.0f); + assertEquals(primitiveHolder.getDoubleValue(), dto.getDoubleValue(), 1.0d); + assertEquals(primitiveHolder.getCharValue(), dto.getCharValue()); + assertEquals(primitiveHolder.getBooleanValue(), dto.getBooleanValue()); + assertEquals(primitiveHolder.getByteValue(), dto.getByteValue()); + } + + private void assertValidMapping(PrimitiveWrapperHolder wrappers, PrimitiveHolder primitives) { + assertEquals(wrappers.getShortValue().shortValue(), primitives.getShortValue()); + assertEquals(wrappers.getIntValue().intValue(), primitives.getIntValue()); + assertEquals(wrappers.getLongValue().longValue(), primitives.getLongValue()); + assertEquals(wrappers.getFloatValue(), primitives.getFloatValue(), 1.0f); + assertEquals(wrappers.getDoubleValue(), primitives.getDoubleValue(), 1.0d); + assertEquals(wrappers.getCharValue().charValue(), primitives.getCharValue()); + assertEquals(wrappers.getBooleanValue(), primitives.isBooleanValue()); + assertEquals(wrappers.getByteValue().byteValue(), primitives.getByteValue()); + } + + + private void assertValidMapping(Library library, LibraryDTO dto) { + + assertNotNull(library); + assertNotNull(dto); + + assertNotNull(library.getBooks()); + assertNotNull(dto.getBooks()); + + List sortedBooks = library.getBooks(); + + List sortedDTOs = dto.getBooks(); + + assertEquals(sortedBooks.size(), sortedDTOs.size()); + + for (int i = 0, count=sortedBooks.size(); i < count; ++i) { + Book book = sortedBooks.get(i); + BookDTO bookDto = sortedDTOs.get(i); + assertValidMapping(book,bookDto); + } + } + + private void assertValidMapping(LibraryNested library, LibraryDTO dto) { + + assertNotNull(library); + assertNotNull(dto); + + assertNotNull(library.getBooks()); + assertNotNull(dto.getBooks()); + + List sortedBooks = library.getBooks(); + + List sortedDTOs = dto.getBooks(); + + assertEquals(sortedBooks.size(), sortedDTOs.size()); + + for (int i = 0, count=sortedBooks.size(); i < count; ++i) { + BookNested book = sortedBooks.get(i); + BookDTO bookDto = sortedDTOs.get(i); + assertValidMapping(book,bookDto); + } + } + + private void assertValidMapping(Book book, BookDTO dto) { + assertNotNull(book); + assertNotNull(dto); + assertEquals(book.getTitle(), dto.getTitle()); + assertValidMapping(book.getAuthor(), dto.getAuthor()); + } + + private void assertValidMapping(BookNested book, BookDTO dto) { + assertNotNull(book); + assertNotNull(dto); + assertEquals(book.getTitle(), dto.getTitle()); + assertValidMapping(book.getAuthor(), dto.getAuthor()); + } + + private void assertValidMapping(Author author, AuthorDTO authorDTO) { + assertNotNull(author); + assertNotNull(authorDTO); + assertEquals(author.getName(),authorDTO.getName()); + } + + private void assertValidMapping(AuthorNested author, AuthorDTO authorDTO) { + assertNotNull(author); + assertNotNull(authorDTO); + assertEquals(author.getName().getFullName(),authorDTO.getName()); + } + + + + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/GenericCollectionsTestCase.java b/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/GenericCollectionsTestCase.java new file mode 100644 index 00000000..e8e1336f --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/GenericCollectionsTestCase.java @@ -0,0 +1,142 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.boundmapperfacade; + +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.converter.builtin.PassThroughConverter; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.metadata.TypeBuilder; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; + +public class GenericCollectionsTestCase { + + /* Abstract class for person */ + public abstract static class Person { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public boolean equals(Object that) { + return Objects.equals(name, ((Person) that).name); + } + + public int hashCode() { + return Objects.hash(name); + } + } + + /* Concrete class for employee */ + public static class Employee extends Person { + } + + /* Task class for some Layer 1 */ + public static class TaskLayer1

{ + private List

workers = new ArrayList<>(); + + public List

getWorkers() { + return workers; + } + + public void setWorkers(List

workers) { + this.workers = workers; + } + } + + /* Task class for some Layer 2 (mapped from TaskLayer1) */ + public static class TaskLayer2

{ + private List

workers = new ArrayList<>(); + + public List

getWorkers() { + return workers; + } + + public void setWorkers(List

workers) { + this.workers = workers; + } + } + + /** + * This test uses the older Class-based mapping method, which is unable + * to determine the proper type hierarchy from the raw types + */ + @Test + public void testParameterizedCollection_rawTypes() { + + MapperFactory factory = new DefaultMapperFactory.Builder().build(); + + factory.classMap(TaskLayer1.class, TaskLayer2.class).byDefault().register(); + + + /* + * Let Orika know that it's okay to copy Employee or Person by reference... + */ + factory.getConverterFactory().registerConverter(new PassThroughConverter(Employee.class, Person.class)); + + + Employee e = new Employee(); + e.setName("Name"); + TaskLayer1 t1 = new TaskLayer1<>(); + t1.setWorkers(Arrays.asList(e)); + + + TaskLayer2 t2 = factory.getMapperFacade(TaskLayer1.class, TaskLayer2.class).map(t1); + Assert.assertNotNull(t2); + Assert.assertTrue(t1.getWorkers().containsAll(t2.getWorkers())); + Assert.assertTrue(t2.getWorkers().containsAll(t1.getWorkers())); + } + + /** + * This test attempts the same mapping using the newer type-based methods + * which allow passing in the exact runtime types. + */ + @Test + public void testParameterizedCollection_genericTypes() { + + MapperFactory factory = new DefaultMapperFactory.Builder().build(); + + Employee e = new Employee(); + e.setName("Name"); + TaskLayer1 t1 = new TaskLayer1<>(); + t1.setWorkers(Arrays.asList(e)); + + Type> sourceType = new TypeBuilder>(){}.build(); + Type> targetType = new TypeBuilder>(){}.build(); + + + factory.classMap(sourceType, targetType).byDefault().register(); + + TaskLayer2 t2 = factory.getMapperFacade(sourceType, targetType).map(t1); + Assert.assertNotNull(t2); + Assert.assertTrue(t1.getWorkers().containsAll(t2.getWorkers())); + Assert.assertTrue(t2.getWorkers().containsAll(t1.getWorkers())); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/InheritanceTestCase.java b/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/InheritanceTestCase.java new file mode 100644 index 00000000..c3a8d448 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/InheritanceTestCase.java @@ -0,0 +1,149 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.boundmapperfacade; + +import org.junit.Assert; +import ma.glasnost.orika.BoundMapperFacade; +import ma.glasnost.orika.CustomMapper; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.test.MappingUtil; + +import org.junit.Test; + +public class InheritanceTestCase { + + private final MapperFactory factory = MappingUtil.getMapperFactory(); + + @Test + public void testSimpleInheritance() { + + BoundMapperFacade mapper = factory.getMapperFacade(ChildEntity.class, ChildDTO.class); + + ChildEntity entity = new ChildEntity(); + entity.setId(1L); + entity.setName("Khettabi"); + + ChildDTO dto = mapper.map(entity); + + Assert.assertEquals(entity.getId(), dto.getId()); + Assert.assertEquals(entity.getName(), dto.getName()); + } + + @Test + public void resolveConcreteClass() { + BoundMapperFacade mapper = factory.getMapperFacade(ChildEntity.class, BaseDTO.class); + factory.registerClassMap(factory.classMap(ChildEntity.class, ChildDTO.class).byDefault()); + + ChildEntity entity = new ChildEntity(); + entity.setId(1L); + entity.setName("Khettabi"); + + BaseDTO dto = mapper.map(entity); + + Assert.assertTrue(dto instanceof ChildDTO); + Assert.assertEquals(entity.getName(), ((ChildDTO) dto).getName()); + } + + @Test + public void testDifferentLevelOfInheritance() { + factory.registerClassMap(factory.classMap(ChildEntity.class, Child2DTO.class) + .customize(new CustomMapper() { + + public void mapAtoB(ChildEntity a, Child2DTO b, MappingContext context) { + b.setMessage("Hello " + a.getName()); + } + + }).byDefault()); + + + BoundMapperFacade mapper = factory.getMapperFacade(ChildEntity.class, Child2DTO.class); + + ChildEntity entity = new ChildEntity(); + entity.setId(1L); + entity.setName("Khettabi"); + + Child2DTO dto = mapper.map(entity); + + Assert.assertEquals(entity.getId(), dto.getId()); + Assert.assertEquals(entity.getName(), dto.getName()); + Assert.assertEquals("Hello Khettabi", dto.getMessage()); + } + + public static abstract class BaseEntity { + private Long id; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + } + + public static abstract class BaseDTO { + private Long id; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + } + + public static class ChildEntity extends BaseEntity { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + public static class ChildDTO extends BaseDTO { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + public static class Child2DTO extends ChildDTO { + private String message; + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/InverseMappingTestCase.java b/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/InverseMappingTestCase.java new file mode 100644 index 00000000..8b412ef8 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/InverseMappingTestCase.java @@ -0,0 +1,441 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.boundmapperfacade; + +import ma.glasnost.orika.BoundMapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.metadata.ClassMapBuilder; +import ma.glasnost.orika.test.MappingUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.util.HashSet; +import java.util.Set; + +public class InverseMappingTestCase { + + @Test + public void testInverseOneToOneMapping() { + MapperFactory factory = MappingUtil.getMapperFactory(); + + ClassMapBuilder classMapBuilder = factory.classMap(PersonDTO.class, Person.class); + classMapBuilder.fieldMap("address").bInverse("person").add(); + factory.registerClassMap(classMapBuilder.byDefault().toClassMap()); + + BoundMapperFacade mapper = factory.getMapperFacade(Person.class, PersonDTO.class); + + AddressDTO addressDTO = new AddressDTO(); + addressDTO.setLine1("5 rue Blida"); + addressDTO.setLine2("20100 Casablanca"); + + PersonDTO personDTO = new PersonDTO(); + personDTO.setFirstName("Khalil"); + personDTO.setLastName("Gibran"); + personDTO.setAddress(addressDTO); + + Person person = mapper.mapReverse(personDTO); + + Assert.assertEquals(personDTO.getFirstName(), person.getFirstName()); + Assert.assertEquals(personDTO.getAddress().getLine1(), person.getAddress().getLine1()); + + Assert.assertTrue(person == person.getAddress().getPerson()); + } + + @Test + public void testInverseOneToManyMapping() { + MapperFactory factory = MappingUtil.getMapperFactory(); + + ClassMapBuilder classMapBuilder = factory.classMap(PublisherDTO.class, Publisher.class); + classMapBuilder.fieldMap("books").bInverse("publisher").add(); + factory.registerClassMap(classMapBuilder.byDefault().toClassMap()); + + + BoundMapperFacade mapper = factory.getMapperFacade(Publisher.class, PublisherDTO.class); + + BookDTO parisNoirDTO = new BookDTO(); + parisNoirDTO.setTitle("Paris Noir"); + + BookDTO chiensFousDTO = new BookDTO(); + chiensFousDTO.setTitle("Chiens Fous"); + + PublisherDTO publisherDTO = new PublisherDTO(); + publisherDTO.setName("Asphalte Editions"); + publisherDTO.getBooks().add(parisNoirDTO); + publisherDTO.getBooks().add(chiensFousDTO); + + Publisher publisher = mapper.mapReverse(publisherDTO); + + Assert.assertTrue(publisher == publisher.getBooks().iterator().next().getPublisher()); + } + + @Test + public void testInverseManyToOneMapping() { + MapperFactory factory = MappingUtil.getMapperFactory(); + + ClassMapBuilder classMapBuilder = factory.classMap(BookDTO.class, Book.class); + classMapBuilder.fieldMap("author").bInverse("books").add(); + factory.registerClassMap(classMapBuilder.byDefault().toClassMap()); + + /* + * Doesn't matter which direction you ask for the bound mapper; + */ + BoundMapperFacade mapper = factory.getMapperFacade(Book.class, BookDTO.class); + BoundMapperFacade mapper2 = factory.getMapperFacade(BookDTO.class, Book.class); + + AuthorDTO authorDTO = new AuthorDTO(); + authorDTO.setFirstName("Khalil"); + authorDTO.setLastName("Gibran"); + + BookDTO bookDTO = new BookDTO(); + bookDTO.setTitle("The Prophet"); + bookDTO.setAuthor(authorDTO); + + Book book = mapper.mapReverse(bookDTO); + Book book2 = mapper2.map(bookDTO); + + Assert.assertTrue(book.getAuthor().getBooks().contains(book)); + + Assert.assertTrue(book2.getAuthor().getBooks().contains(book2)); + } + + @Test + public void testInverseManyToManyMapping() { + MapperFactory factory = MappingUtil.getMapperFactory(); + + ClassMapBuilder classMapBuilder = factory.classMap(ReaderDTO.class, Reader.class); + classMapBuilder.fieldMap("books").bInverse("readers").add(); + factory.registerClassMap(classMapBuilder.byDefault().toClassMap()); + + BoundMapperFacade mapper = factory.getMapperFacade(Reader.class, ReaderDTO.class); + BoundMapperFacade mapper2 = factory.getMapperFacade(ReaderDTO.class, Reader.class); + + Set bookDTOs = new HashSet<>(); + BookDTO bookDTO = new BookDTO(); + bookDTO.setTitle("The Prophet"); + bookDTOs.add(bookDTO); + bookDTO = new BookDTO(); + bookDTO.setTitle("More Effective Java"); + bookDTOs.add(bookDTO); + + ReaderDTO readerDTO = new ReaderDTO(); + readerDTO.setFirstName("Jennifer"); + readerDTO.setLastName("Lopez"); + readerDTO.setBooks(bookDTOs); + + Reader reader = mapper.mapReverse(readerDTO); + Reader reader2 = mapper2.map(readerDTO); + + for (Book book : reader.getBooks()) { + Assert.assertTrue(book.getReaders().contains(reader)); + } + + for (Book book : reader2.getBooks()) { + Assert.assertTrue(book.getReaders().contains(reader2)); + } + } + + public static class Person { + + private String firstName; + + private String lastName; + + private Address address; + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public Address getAddress() { + return address; + } + + public void setAddress(Address address) { + this.address = address; + } + + } + + public static class Address { + + private String line1; + + private String line2; + + private Person person; + + public String getLine1() { + return line1; + } + + public void setLine1(String line1) { + this.line1 = line1; + } + + public String getLine2() { + return line2; + } + + public void setLine2(String line2) { + this.line2 = line2; + } + + public Person getPerson() { + return person; + } + + public void setPerson(Person person) { + this.person = person; + } + + } + + public static class Book { + + private String title; + + private Author author; + + private Publisher publisher; + + private Set readers; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public Author getAuthor() { + return author; + } + + public void setAuthor(Author author) { + this.author = author; + } + + public Publisher getPublisher() { + return publisher; + } + + public void setPublisher(Publisher publisher) { + this.publisher = publisher; + } + + public Set getReaders() { + return readers; + } + + public void setReaders(Set readers) { + this.readers = readers; + } + + } + + public static class Author extends Person { + + private Set books; + + public Set getBooks() { + return books; + } + + public void setBooks(Set books) { + this.books = books; + } + + } + + public static class Reader extends Person { + + private Set books; + + public Set getBooks() { + return books; + } + + public void setBooks(Set books) { + this.books = books; + } + + } + + public static class Publisher { + + private String name; + + private Set books; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Set getBooks() { + return books; + } + + public void setBooks(Set books) { + this.books = books; + } + + } + + public static class PersonDTO { + + private String firstName; + + private String lastName; + + private AddressDTO address; + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public AddressDTO getAddress() { + return address; + } + + public void setAddress(AddressDTO address) { + this.address = address; + } + + } + + public static class AddressDTO { + + private String line1; + + private String line2; + + public String getLine1() { + return line1; + } + + public void setLine1(String line1) { + this.line1 = line1; + } + + public String getLine2() { + return line2; + } + + public void setLine2(String line2) { + this.line2 = line2; + } + + } + + public static class BookDTO { + + private String title; + + private AuthorDTO author; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public AuthorDTO getAuthor() { + return author; + } + + public void setAuthor(AuthorDTO author) { + this.author = author; + } + + } + + public static class AuthorDTO extends PersonDTO { + + } + + public static class ReaderDTO extends PersonDTO { + + private Set books; + + public Set getBooks() { + return books; + } + + public void setBooks(Set books) { + this.books = books; + } + + } + + public static class PublisherDTO { + + private String name; + + private Set books = new HashSet<>(); + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Set getBooks() { + return books; + } + + public void setBooks(Set books) { + this.books = books; + } + + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/Issue207TestCase.java b/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/Issue207TestCase.java new file mode 100644 index 00000000..43f2bc12 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/Issue207TestCase.java @@ -0,0 +1,7 @@ +package ma.glasnost.orika.test.boundmapperfacade; + +/** + * Created by sidi on 10/04/17. + */ +public class Issue207TestCase { +} diff --git a/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/MapGenerationTestCase.java b/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/MapGenerationTestCase.java new file mode 100644 index 00000000..3e360e14 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/MapGenerationTestCase.java @@ -0,0 +1,552 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.boundmapperfacade; + +import ma.glasnost.orika.BoundMapperFacade; +import ma.glasnost.orika.CustomConverter; +import ma.glasnost.orika.MapEntry; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.impl.GeneratedObjectBase; +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.test.MappingUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +public class MapGenerationTestCase { + + @Test + public void testMapToMapGeneration() throws Exception { + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.registerClassMap(factory.classMap(MapWithSetter.class, MapWithSetterDto.class).field("testScores", "scores").byDefault()); + + BoundMapperFacade mapper = factory.getMapperFacade(MapWithSetter.class, MapWithSetterDto.class); + + MapWithSetter source = new MapWithSetter(); + Map testScores = new LinkedHashMap<>(); + + testScores.put("A", 90); + testScores.put("B", 80); + testScores.put("C", 70); + source.setTestScores(testScores); + + MapWithSetterDto result = mapper.map(source); + + Assert.assertNotNull(result); + Assert.assertNotNull(result.getScores()); + for (Entry entry : testScores.entrySet()) { + Assert.assertEquals(entry.getValue(), result.getScores().get(entry.getKey())); + } + + } + + @Test + public void testMapToMapGeneration_noSetter() throws Exception { + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.registerClassMap(factory.classMap(MapWithSetter.class, MapWithoutSetter.class).field("testScores", "scores").byDefault()); + + BoundMapperFacade mapper = factory.getMapperFacade(MapWithSetter.class, MapWithoutSetter.class); + + MapWithSetter source = new MapWithSetter(); + Map testScores = new LinkedHashMap<>(); + + testScores.put("A", 90); + testScores.put("B", 80); + testScores.put("C", 70); + source.setTestScores(testScores); + + MapWithoutSetter result = mapper.map(source); + + Assert.assertNotNull(result); + Assert.assertNotNull(result.getScores()); + for (Entry entry : testScores.entrySet()) { + Assert.assertEquals(entry.getValue().toString(), result.getScores().get(entry.getKey())); + } + + } + + @Test + public void testMapToArrayGeneration() throws Exception { + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.registerClassMap(factory.classMap(MapWithSetter.class, GenericDto.class).field("testScores", "stringArray").byDefault()); + + /* + * Tell Orika how we should convert the map entries to the result array + * component type (String) + */ + factory.getConverterFactory().registerConverter(new CustomConverter, String>() { + + public String convert(Map.Entry source, Type destinationType, MappingContext context) { + return source.getKey(); + } + }); + + BoundMapperFacade mapper = factory.getMapperFacade(MapWithSetter.class, GenericDto.class); + + MapWithSetter source = new MapWithSetter(); + Map testScores = new LinkedHashMap<>(); + + testScores.put("A", 90); + testScores.put("B", 80); + testScores.put("C", 70); + source.setTestScores(testScores); + + GenericDto result = mapper.map(source); + + Assert.assertNotNull(result.getStringArray()); + + } + + @Test + public void testMapToListGeneration() throws Exception { + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.registerClassMap(factory.classMap(MapWithSetter.class, GenericDto.class).field("testScores", "stringList").byDefault()); + + /* + * Tell Orika how we should convert the map entries to the result list + * element type (String) + */ + factory.getConverterFactory().registerConverter(new CustomConverter, String>() { + + public String convert(Map.Entry source, Type destinationType, MappingContext context) { + return source.getKey(); + } + }); + + BoundMapperFacade mapper = factory.getMapperFacade(MapWithSetter.class, GenericDto.class); + + MapWithSetter source = new MapWithSetter(); + Map testScores = new LinkedHashMap<>(); + + testScores.put("A", 90); + testScores.put("B", 80); + testScores.put("C", 70); + source.setTestScores(testScores); + + GenericDto result = mapper.map(source); + + Assert.assertNotNull(result.getStringList()); + + } + + @Test + public void testListToMapGeneration() throws Exception { + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.registerClassMap(factory.classMap(MapWithoutSetter.class, GenericDto.class).field("scores", "stringList").byDefault()); + + /* + * Tell Orika how we should convert the list element type to map entry + */ + factory.getConverterFactory().registerConverter(new CustomConverter>() { + + @SuppressWarnings("serial") + private final Map> testScores = new LinkedHashMap>() { + { + put("A", new MapEntry<>("A", 90)); + put("B", new MapEntry<>("B", 80)); + put("C", new MapEntry<>("C", 70)); + put("D", new MapEntry<>("D", 60)); + put("F", new MapEntry<>("F", 50)); + } + }; + + public Map.Entry convert(String source, Type> destinationType, + MappingContext context) { + return testScores.get(source); + } + }); + + BoundMapperFacade mapper = factory.getMapperFacade(GenericDto.class, MapWithoutSetter.class); + + GenericDto source = new GenericDto(); + List testScores = new ArrayList<>(); + + testScores.add("A"); + testScores.add("B"); + testScores.add("C"); + source.setStringList(testScores); + + MapWithoutSetter result = mapper.map(source); + + Assert.assertNotNull(result.getScores()); + + } + + @Test + public void testArrayToMapGeneration() throws Exception { + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.registerClassMap(factory.classMap(MapWithoutSetter.class, GenericDto.class).field("scores", "stringArray").byDefault()); + + /* + * Tell Orika how we should convert the list element type to map entry + */ + factory.getConverterFactory().registerConverter(new CustomConverter>() { + + @SuppressWarnings("serial") + private final Map> testScores = new LinkedHashMap>() { + { + put("A", new MyMapEntry<>("A", 90)); + put("B", new MapEntry<>("B", 80)); + put("C", new MapEntry<>("C", 70)); + put("D", new MapEntry<>("D", 60)); + put("F", new MapEntry<>("F", 50)); + } + }; + + public Map.Entry convert(String source, Type> destinationType, + MappingContext context) { + return testScores.get(source); + } + }); + + BoundMapperFacade mapper = factory.getMapperFacade(GenericDto.class, MapWithoutSetter.class); + + GenericDto source = new GenericDto(); + List testScores = new ArrayList<>(); + + testScores.add("A"); + testScores.add("B"); + testScores.add("C"); + source.setStringArray(testScores.toArray(new String[testScores.size()])); + + MapWithoutSetter result = mapper.map(source); + + Assert.assertNotNull(result.getScores()); + + } + + @Test + public void testNewSyntax_mapToArrays() throws Exception { + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.registerClassMap(factory.classMap(MapWithoutSetter.class, GenericDto.class) + .field("scores{key}", "stringArray{}") + .field("scores{value}", "intArray{}") + .byDefault()); + /* + * Tell Orika how we should convert the list element type to map entry + */ + BoundMapperFacade mapper = factory.getMapperFacade(GenericDto.class, MapWithoutSetter.class); + + GenericDto source = new GenericDto(); + List testScores = new ArrayList<>(); + List numericScores = new ArrayList<>(); + testScores.add("A"); + numericScores.add(90); + testScores.add("B"); + numericScores.add(80); + testScores.add("C"); + numericScores.add(70); + source.setStringArray(testScores.toArray(new String[testScores.size()])); + source.setIntArray(GeneratedObjectBase.intArray(numericScores)); + + MapWithoutSetter result = mapper.map(source); + + Assert.assertNotNull(result.getScores()); + + } + + @Test + public void testNewSyntax_mapToArraysWithUnequalSize() throws Exception { + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.registerClassMap(factory.classMap(MapWithoutSetter.class, GenericDto.class) + .field("scores{key}", "stringArray{}") + .field("scores{value}", "intArray{}") + .byDefault()); + + /* + * Tell Orika how we should convert the list element type to map entry + */ + BoundMapperFacade mapper = factory.getMapperFacade(GenericDto.class, MapWithoutSetter.class); + + GenericDto source = new GenericDto(); + List testScores = new ArrayList<>(); + List numericScores = new ArrayList<>(); + testScores.add("A"); + numericScores.add(90); + testScores.add("B"); + numericScores.add(80); + testScores.add("C"); + + source.setStringArray(testScores.toArray(new String[testScores.size()])); + source.setIntArray(GeneratedObjectBase.intArray(numericScores)); + + MapWithoutSetter result = mapper.map(source); + + Assert.assertNotNull(result.getScores()); + Assert.assertTrue("90".equals(result.getScores().get("A"))); + Assert.assertTrue("80".equals(result.getScores().get("B"))); + Assert.assertFalse(result.getScores().containsKey("C")); + } + + /** + * Demonstrates how a single field can be mapped to more than one + * destination, in both directions. + * + * @throws Exception + */ + @SuppressWarnings("serial") + @Test + public void testNewSyntax_multipleParallel() throws Exception { + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.registerClassMap(factory.classMap(MapWithoutSetter.class, GenericDto.class) + .field("scores{key}", "stringArray{}") + .field("scores{value}", "intArray{}") + .field("scores{key}", "gradeList{letterGrade}") + .field("scores{value}", "gradeList{minimumScore}") + .byDefault()); + + MapWithoutSetter source = new MapWithoutSetter(); + source.setScores(new LinkedHashMap() { + { + put("A", "90"); + put("B", "80"); + put("C", "70"); + put("D", "60"); + put("F", "50"); + } + }); + + /* + * Tell Orika how we should convert the list element type to map entry + */ + BoundMapperFacade mapper = factory.getMapperFacade(GenericDto.class, MapWithoutSetter.class); + + GenericDto result = mapper.mapReverse(source); + + Assert.assertNotNull(result.getGradeList()); + Assert.assertEquals(source.getScores().size(), result.getGradeList().size()); + for (Grade g : result.getGradeList()) { + Assert.assertTrue(source.getScores().containsKey("" + g.getLetterGrade())); + Assert.assertTrue(source.getScores().get("" + g.getLetterGrade()).equals("" + g.getMinimumScore())); + } + + MapWithoutSetter mapBack = mapper.map(result); + Assert.assertTrue(source.getScores().keySet().containsAll(mapBack.getScores().keySet())); + Assert.assertTrue(mapBack.getScores().keySet().containsAll(source.getScores().keySet())); + } + + public static class MyMapEntry implements Map.Entry { + + private final K key; + private V value; + + public MyMapEntry(K key, V value) { + this.key = key; + this.value = value; + } + + public K getKey() { + return key; + } + + public V getValue() { + return value; + } + + public V setValue(V value) { + V oldValue = this.value; + this.value = value; + return oldValue; + } + + } + + public static class MapWithSetter { + + private Map testScores; + + public Map getTestScores() { + return testScores; + } + + public void setTestScores(Map testScores) { + this.testScores = testScores; + } + } + + public static class MapWithSetterDto { + + private Map scores; + + public Map getScores() { + return scores; + } + + public void setScores(Map scores) { + this.scores = scores; + } + } + + public static class MapWithSetterDto2 { + + private Map scores; + + public Map getScores() { + return scores; + } + + public void setScores(Map scores) { + this.scores = scores; + } + } + + public static class MapWithoutSetter { + + private Map scores; + + public Map getScores() { + return scores; + } + + public void setScores(Map scores) { + this.scores = scores; + } + } + + public static class Grade { + int minimumScore; + Character letterGrade; + + public int getMinimumScore() { + return minimumScore; + } + + public void setMinimumScore(int minimumScore) { + this.minimumScore = minimumScore; + } + + public Character getLetterGrade() { + return letterGrade; + } + + public void setLetterGrade(Character letterGrade) { + this.letterGrade = letterGrade; + } + } + + public static class GenericDto { + + private String[] stringArray; + private List stringList; + private int[] intArray; + private long[] longArray; + private List gradeList; + private Grade[] gradeArray; + private Map gradesByLetter; + private Map gradesByMinScore; + private Map lettersByGrade; + private Map scoresByGrade; + + public String[] getStringArray() { + return stringArray; + } + + public void setStringArray(String[] stringArray) { + this.stringArray = stringArray; + } + + public List getStringList() { + return stringList; + } + + public void setStringList(List stringList) { + this.stringList = stringList; + } + + public int[] getIntArray() { + return intArray; + } + + public void setIntArray(int[] intArray) { + this.intArray = intArray; + } + + public long[] getLongArray() { + return longArray; + } + + public void setLongArray(long[] longArray) { + this.longArray = longArray; + } + + public List getGradeList() { + return gradeList; + } + + public void setGradeList(List gradeList) { + this.gradeList = gradeList; + } + + public Grade[] getGradeArray() { + return gradeArray; + } + + public void setGradeArray(Grade[] gradeArray) { + this.gradeArray = gradeArray; + } + + public Map getGradesByLetter() { + return gradesByLetter; + } + + public void setGradesByLetter(Map gradesByLetter) { + this.gradesByLetter = gradesByLetter; + } + + public Map getGradesByMinScore() { + return gradesByMinScore; + } + + public void setGradesByMinScore(Map gradesByMinScore) { + this.gradesByMinScore = gradesByMinScore; + } + + public Map getLettersByGrade() { + return lettersByGrade; + } + + public void setLettersByGrade(Map lettersByGrade) { + this.lettersByGrade = lettersByGrade; + } + + public Map getScoresByGrade() { + return scoresByGrade; + } + + public void setScoresByGrade(Map scoresByGrade) { + this.scoresByGrade = scoresByGrade; + } + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/NestedInheritanceTestCase.java b/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/NestedInheritanceTestCase.java new file mode 100644 index 00000000..f056a91c --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/NestedInheritanceTestCase.java @@ -0,0 +1,111 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.boundmapperfacade; + +import org.junit.Assert; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.test.MappingUtil; + +import org.junit.Test; + +public class NestedInheritanceTestCase { + + @Test + public void testNestedInheritance() { + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.registerClassMap(factory.classMap(Person.class, PersonDTO.class).byDefault()); + factory.registerClassMap(factory.classMap(Client.class, ClientDTO.class).byDefault()); + factory.registerClassMap(factory.classMap(Subscription.class, SubscriptionDTO.class).field("client", "person")); + + Client client = new Client(); + client.setName("Khalil Gebran"); + + Subscription subscription = new Subscription(); + subscription.setClient(client); + + SubscriptionDTO dto = factory.getMapperFacade(Subscription.class, SubscriptionDTO.class).map(subscription); + + Assert.assertNotNull(dto); + Assert.assertNotNull(dto.getPerson()); + Assert.assertEquals(client.getName(), dto.getPerson().getName()); + } + + public abstract static class Person { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + } + + public static class Client extends Person { + + } + + public static class Subscription { + + private Person client; + + public Person getClient() { + return client; + } + + public void setClient(Person client) { + this.client = client; + } + + } + + public static abstract class PersonDTO { + + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + } + + public static class ClientDTO extends PersonDTO { + + } + + public static class SubscriptionDTO { + private PersonDTO person; + + public PersonDTO getPerson() { + return person; + } + + public void setPerson(PersonDTO person) { + this.person = person; + } + + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/ObjectCollectionTestCase.java b/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/ObjectCollectionTestCase.java new file mode 100644 index 00000000..eece70e3 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/ObjectCollectionTestCase.java @@ -0,0 +1,194 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.boundmapperfacade; + +import ma.glasnost.orika.BoundMapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Objects; + +/** + * Simple test of maaping collection + * + * @author Dmitriy Khomyakov + */ +public class ObjectCollectionTestCase { + + @Test + public void testMapOfCollection() { + DefaultMapperFactory.Builder builder = new DefaultMapperFactory.Builder(); + MapperFactory factory = builder.build(); + + BoundMapperFacade mapperFacade = factory.getMapperFacade(DtoHolder.class, EntityHolder.class); + + List dtos = new ArrayList<>(); + + Dto dto = new Dto(); + dto.setId(1L); + dto.setName("A"); + dtos.add(dto); + + Dto dto2 = new Dto(); + dto2.setId(2L); + dto2.setName("B"); + dtos.add(dto2); + + dto = new Dto(); + dto.setId(3L); + dto.setName("C"); + dtos.add(dto); + + DtoHolder source = new DtoHolder(); + source.setEntities(dtos); + + final EntityHolder entities = mapperFacade.map(source); + + Assert.assertNotNull(entities); + Assert.assertEquals(3, entities.getEntities().size()); + + } + + public static class Entity { + + private Long id; + private String name; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public boolean isNew() { + return id == null; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof Entity)) { + return false; + } + + Entity entity = (Entity) o; + + if (!Objects.equals(id, entity.id)) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + return id != null ? id.hashCode() : 0; + } + } + + public static class EntityHolder { + + private Collection entityList; + + public Collection getEntities() { + return entityList; + } + + public void setEntities(Collection entityList) { + this.entityList = entityList; + } + + } + + public static class Dto { + private Long id; + private String name; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof Dto)) { + return false; + } + + Dto dto = (Dto) o; + + if (!Objects.equals(id, dto.id)) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + return id != null ? id.hashCode() : 0; + } + } + + public static class DtoHolder { + + private Collection dtoList; + + public Collection getEntities() { + return dtoList; + } + + public void setEntities(Collection dtoList) { + this.dtoList = dtoList; + } + + } + +} \ No newline at end of file diff --git a/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/PolicyElementsTestCase.java b/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/PolicyElementsTestCase.java new file mode 100644 index 00000000..0432a0c4 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/PolicyElementsTestCase.java @@ -0,0 +1,117 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.boundmapperfacade; + +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.test.MappingUtil; +import ma.glasnost.orika.test.crossfeatures.PolicyElementsTestCaseClasses.CustomerElement; +import ma.glasnost.orika.test.crossfeatures.PolicyElementsTestCaseClasses.CustomerElementDTO; +import ma.glasnost.orika.test.crossfeatures.PolicyElementsTestCaseClasses.OneOtherElement; +import ma.glasnost.orika.test.crossfeatures.PolicyElementsTestCaseClasses.OneOtherElementDTO; +import ma.glasnost.orika.test.crossfeatures.PolicyElementsTestCaseClasses.OtherElement; +import ma.glasnost.orika.test.crossfeatures.PolicyElementsTestCaseClasses.OtherElementDTO; +import ma.glasnost.orika.test.crossfeatures.PolicyElementsTestCaseClasses.Policy; +import ma.glasnost.orika.test.crossfeatures.PolicyElementsTestCaseClasses.PolicyDTO; +import ma.glasnost.orika.test.crossfeatures.PolicyElementsTestCaseClasses.PolicyElement; +import ma.glasnost.orika.test.crossfeatures.PolicyElementsTestCaseClasses.PolicyElementDTO; +import ma.glasnost.orika.test.crossfeatures.PolicyElementsTestCaseClasses.PolicyElementProxy; +import ma.glasnost.orika.test.crossfeatures.PolicyElementsTestCaseClasses.ProductElement; +import ma.glasnost.orika.test.crossfeatures.PolicyElementsTestCaseClasses.ProductElementDTO; +import ma.glasnost.orika.unenhance.UnenhanceStrategy; +import org.junit.Assert; +import org.junit.Test; + +import java.util.HashSet; +import java.util.Set; + +public class PolicyElementsTestCase { + + @Test + public void test() { + MapperFactory factory = MappingUtil.getMapperFactory(); + configureMapperFactory(factory); + + Policy policy = new Policy(); + Set elements = new HashSet<>(); + elements.add(new CustomerElement()); + elements.add(new ProductElement()); + elements.add(new OtherElement()); + elements.add(new OneOtherElement()); + + policy.setElements(elements); + + PolicyDTO dto = factory.getMapperFacade(Policy.class, PolicyDTO.class).map(policy); + + Assert.assertEquals(elements.size(), dto.getElements().size()); + } + + private void configureMapperFactory(MapperFactory factory) { + + factory.registerClassMap(factory.classMap(Policy.class, PolicyDTO.class).byDefault()); + factory.registerClassMap(factory.classMap(CustomerElement.class, CustomerElementDTO.class).byDefault()); + factory.registerClassMap(factory.classMap(ProductElement.class, ProductElementDTO.class).byDefault()); + factory.registerClassMap(factory.classMap(OtherElement.class, OtherElementDTO.class).byDefault()); + factory.registerClassMap(factory.classMap(OneOtherElement.class, OneOtherElementDTO.class).byDefault()); + } + + @Test + public void testHibernateProxyLike() { + MapperFactory factory = new DefaultMapperFactory.Builder().unenhanceStrategy(new UnenhanceStrategy() { + @SuppressWarnings("unchecked") + public Type unenhanceType(T object, Type type) { + if (object instanceof PolicyElementProxy) + return (Type) ((PolicyElementProxy) object).getTargetClass(); + return type; + } + + @SuppressWarnings("unchecked") + public T unenhanceObject(T object, Type type) { + if (object instanceof PolicyElementProxy) + return (T) ((PolicyElementProxy) object).getTarget(); + return object; + } + + }).build(); + configureMapperFactory(factory); + + Policy policy = new Policy(); + Set elements = new HashSet<>(); + CustomerElement target = new CustomerElement(); + target.setName("Adil"); + elements.add(new PolicyElementProxy(target)); + elements.add(new ProductElement()); + elements.add(new OtherElement()); + elements.add(new OneOtherElement()); + + policy.setElements(elements); + + PolicyDTO dto = factory.getMapperFacade(Policy.class, PolicyDTO.class).map(policy); + + Assert.assertEquals(elements.size(), dto.getElements().size()); + + for (PolicyElementDTO element: dto.getElements()) { + if (element instanceof CustomerElementDTO) { + Assert.assertEquals("Adil", ((CustomerElementDTO) element).getName()); + } + } + + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/ReuseMappersTestCase.java b/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/ReuseMappersTestCase.java new file mode 100644 index 00000000..327831c6 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/ReuseMappersTestCase.java @@ -0,0 +1,165 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.boundmapperfacade; + +import ma.glasnost.orika.BoundMapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.metadata.ClassMapBuilder; +import ma.glasnost.orika.test.MappingUtil; + +import org.junit.Assert; +import org.junit.Test; + +public class ReuseMappersTestCase { + + @Test + public void testReuse() { + + MapperFactory factory = MappingUtil.getMapperFactory(); + + { + ClassMapBuilder builder = factory.classMap(Location.class, LocationDTO.class); + builder.field("x", "coordinateX").field("y", "coordinateY"); + factory.registerClassMap(builder.toClassMap()); + + } + + { + ClassMapBuilder builder = factory.classMap(NamedLocation.class, NamedLocationDTO.class); + builder.use(Location.class, LocationDTO.class).field("name", "label"); + factory.registerClassMap(builder.toClassMap()); + } + + { + ClassMapBuilder builder = factory.classMap(City.class, CityDTO.class); + builder.use(NamedLocation.class, NamedLocationDTO.class).byDefault(); + factory.registerClassMap(builder.toClassMap()); + } + + + BoundMapperFacade mapper = factory.getMapperFacade(City.class, CityDTO.class); + + City city = new City(); + city.setX(5); + city.setY(7); + city.setZipCode("78951123"); + + CityDTO dto = mapper.map(city); + + Assert.assertEquals(city.getX(), dto.getCoordinateX()); + Assert.assertEquals(city.getY(), dto.getCoordinateY()); + Assert.assertEquals(city.getName(), dto.getLabel()); + Assert.assertEquals(city.getZipCode(), dto.getZipCode()); + + } + + public static abstract class Location { + private int x, y; + + public int getX() { + return x; + } + + public void setX(int x) { + this.x = x; + } + + public int getY() { + return y; + } + + public void setY(int y) { + this.y = y; + } + + } + + public static class NamedLocation extends Location { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + } + + public static class City extends NamedLocation { + private String zipCode; + + public String getZipCode() { + return zipCode; + } + + public void setZipCode(String zipCode) { + this.zipCode = zipCode; + } + + } + + public static abstract class LocationDTO { + private int coordinateX, coordinateY; + + public int getCoordinateX() { + return coordinateX; + } + + public void setCoordinateX(int x) { + this.coordinateX = x; + } + + public int getCoordinateY() { + return coordinateY; + } + + public void setCoordinateY(int y) { + this.coordinateY = y; + } + + } + + public static class NamedLocationDTO extends LocationDTO { + private String label; + + public String getLabel() { + return label; + } + + public void setLabel(String name) { + this.label = name; + } + + } + + public static class CityDTO extends NamedLocationDTO { + private String zipCode; + + public String getZipCode() { + return zipCode; + } + + public void setZipCode(String zipCode) { + this.zipCode = zipCode; + } + + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/SortedMapSetTestCase.java b/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/SortedMapSetTestCase.java new file mode 100644 index 00000000..d3ba75bc --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/SortedMapSetTestCase.java @@ -0,0 +1,148 @@ +package ma.glasnost.orika.test.boundmapperfacade; + +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.test.MappingUtil; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.Arrays; +import java.util.Iterator; +import java.util.SortedMap; +import java.util.SortedSet; +import java.util.TreeMap; +import java.util.TreeSet; + +/** + * @author: jad7 jad7kii@gmail.com + * @since: 11/8/14 + */ + +public class SortedMapSetTestCase { + + private MapperFactory mapperFactory; + private A a; + + public static class A { + private SortedSet integerSortedSet; + private SortedMap stringStringSortedMap; + + public SortedSet getIntegerSortedSet() { + return integerSortedSet; + } + + public void setIntegerSortedSet(SortedSet integerSortedSet) { + this.integerSortedSet = integerSortedSet; + } + + public SortedMap getStringStringSortedMap() { + return stringStringSortedMap; + } + + public void setStringStringSortedMap(SortedMap stringStringSortedMap) { + this.stringStringSortedMap = stringStringSortedMap; + } + } + + public static class B { + private SortedSet integerSortedSet; + private SortedMap stringStringSortedMap; + + public SortedSet getIntegerSortedSet() { + return integerSortedSet; + } + + public void setIntegerSortedSet(SortedSet integerSortedSet) { + this.integerSortedSet = integerSortedSet; + } + + public SortedMap getStringStringSortedMap() { + return stringStringSortedMap; + } + + public void setStringStringSortedMap(SortedMap stringStringSortedMap) { + this.stringStringSortedMap = stringStringSortedMap; + } + } + + public static class C { + public C(SortedSet integerSortedSet, SortedMap stringStringSortedMap) { + this.integerSortedSet = integerSortedSet; + this.stringStringSortedMap = stringStringSortedMap; + } + + private final SortedSet integerSortedSet; + private final SortedMap stringStringSortedMap; + + public SortedSet getIntegerSortedSet() { + return integerSortedSet; + } + + public SortedMap getStringStringSortedMap() { + return stringStringSortedMap; + } + } + + @Before + public void init() { + //System.setProperty(MappingUtil.DISABLE_DEBUG_MODE, "false"); + mapperFactory = MappingUtil.getMapperFactory(true); + a = new A(); + SortedSet sortedSet = new TreeSet<>(Arrays.asList(5, 7, 3, 4, 1)); + SortedMap sortedMap = new TreeMap<>(); + sortedMap.put("a", "a"); + sortedMap.put("e", "e"); + sortedMap.put("b", "b"); + sortedMap.put("r", "r"); + a.setIntegerSortedSet(sortedSet); + a.setStringStringSortedMap(sortedMap); + } + + @Test + public void sortedTest() { + mapperFactory.classMap(A.class, B.class).byDefault().register(); + + B b = mapperFactory.getMapperFacade(A.class, B.class).map(a); + SortedSet integerSortedSetResult = b.getIntegerSortedSet(); + SortedMap stringStringSortedMapResult = b.getStringStringSortedMap(); + checkMapping(integerSortedSetResult, stringStringSortedMapResult); + } + + + + @Test + public void sortedByConstructor() { + mapperFactory.classMap(A.class, C.class) + .constructorB("integerSortedSet", "stringStringSortedMap") + .fieldMap("integerSortedSet", "integerSortedSet").exclude().add() + .fieldMap("stringStringSortedMap", "stringStringSortedMap").exclude().add() + .register(); + + C map = mapperFactory.getMapperFacade(A.class, C.class).map(a); + checkMapping(map.getIntegerSortedSet(), map.getStringStringSortedMap()); + } + + private void checkMapping(SortedSet integerSortedSetResult, SortedMap stringStringSortedMapResult) { + Assert.assertFalse(integerSortedSetResult == a.getIntegerSortedSet()); + Assert.assertFalse(stringStringSortedMapResult == a.getStringStringSortedMap()); + + Assert.assertEquals(a.getIntegerSortedSet().size(), integerSortedSetResult.size()); + for (Iterator aSetIterator = a.getIntegerSortedSet().iterator(), + bSetIterator = integerSortedSetResult.iterator(); + aSetIterator.hasNext() && bSetIterator.hasNext(); ) { + Integer aInteger = aSetIterator.next(); + Integer bInteger = bSetIterator.next(); + + Assert.assertEquals(aInteger, bInteger); + } + + Assert.assertEquals(a.getStringStringSortedMap().size(), stringStringSortedMapResult.size()); + for (Iterator aMapIterator = a.getStringStringSortedMap().keySet().iterator(), + bMapIterator = stringStringSortedMapResult.keySet().iterator(); + aMapIterator.hasNext() && bMapIterator.hasNext(); ) { + String aString = aMapIterator.next(); + String bString = bMapIterator.next(); + Assert.assertEquals(aString, bString); + } + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/SuperTypeForGeneratedTestCase.java b/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/SuperTypeForGeneratedTestCase.java new file mode 100644 index 00000000..8c25d868 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/SuperTypeForGeneratedTestCase.java @@ -0,0 +1,92 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.boundmapperfacade; + +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.test.MappingUtil; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.Author; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.AuthorParent; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.Book; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.BookParent; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.Library; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.LibraryDTO; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.LibraryParent; +import org.easymock.EasyMock; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +public class SuperTypeForGeneratedTestCase { + + + private Author createAuthor() throws InstantiationException, IllegalAccessException { + + Author author = EasyMock.createNiceMock(AuthorParent.class); + EasyMock.expect(author.getName()).andReturn("Khalil Gebran").anyTimes(); + EasyMock.replay(author); + + return author; + } + + private Book createBook() throws InstantiationException, IllegalAccessException { + Book book = EasyMock.createNiceMock(BookParent.class); + EasyMock.expect(book.getTitle()).andReturn("The Prophet").anyTimes(); + Author author = createAuthor(); + EasyMock.expect(book.getAuthor()).andReturn(author).anyTimes(); + EasyMock.replay(book); + + return book; + } + + private Library createLibrary() throws InstantiationException, IllegalAccessException { + + Library lib = EasyMock.createNiceMock(LibraryParent.class); + EasyMock.expect(lib.getTitle()).andReturn("Test Library").anyTimes(); + List books = new ArrayList<>(); + Book book = createBook(); + books.add(book); + EasyMock.expect(lib.getBooks()).andReturn(books).anyTimes(); + + EasyMock.replay(lib); + + return lib; + } + + + @Test + public void testSuperTypeMappingForInaccessibleClasses() throws Exception { + + MapperFactory factory = MappingUtil.getMapperFactory(); + + Library lib = createLibrary(); + Book book = lib.getBooks().get(0); + + LibraryDTO mappedLib = factory.getMapperFacade(Library.class, LibraryDTO.class).map(lib); + + Assert.assertNotNull(mappedLib); + + Assert.assertEquals(lib.getTitle(),mappedLib.getTitle()); + Assert.assertEquals(book.getTitle(),mappedLib.getBooks().get(0).getTitle()); + Assert.assertEquals(book.getAuthor().getName(),mappedLib.getBooks().get(0).getAuthor().getName()); + + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/SuperTypeMappingTestCase.java b/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/SuperTypeMappingTestCase.java new file mode 100644 index 00000000..d67f9dd8 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/SuperTypeMappingTestCase.java @@ -0,0 +1,233 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.boundmapperfacade; + +import ma.glasnost.orika.BoundMapperFacade; +import ma.glasnost.orika.DefaultFieldMapper; +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.test.MappingUtil; +import ma.glasnost.orika.test.MavenProjectUtil; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.Author; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.AuthorChild; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.AuthorMyDTO; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.AuthorParent; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.Book; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.BookChild; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.BookMyDTO; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.BookParent; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.Library; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.LibraryChild; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.LibraryMyDTO; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.LibraryParent; +import org.junit.Assert; +import org.junit.Test; + +import javax.xml.datatype.XMLGregorianCalendar; +import java.io.File; +import java.util.Date; + +public class SuperTypeMappingTestCase { + + private Author createAuthor(Class type) throws InstantiationException, IllegalAccessException { + Author author = type.newInstance(); + author.setName("Khalil Gebran"); + + return author; + } + + private Book createBook(Class type) throws InstantiationException, IllegalAccessException { + Book book = type.newInstance(); + book.setTitle("The Prophet"); + + return book; + } + + private Library createLibrary(Class type) throws InstantiationException, IllegalAccessException { + Library lib = type.newInstance(); + lib.setTitle("Test Library"); + + return lib; + } + + @Test + public void testMappingInterfaceImplementationNoExistingMapping() throws Exception { + + MapperFacade mapper = MappingUtil.getMapperFactory().getMapperFacade(); + + Book book = createBook(BookChild.class); + book.setAuthor(createAuthor(AuthorChild.class)); + + BookMyDTO mappedBook = mapper.map(book, BookMyDTO.class); + + Assert.assertNotNull(mappedBook); + Assert.assertNull(mappedBook.getMyTitle()); + Assert.assertNull(mappedBook.getMyAuthor()); + } + + @Test + public void testMappingInterfaceImplementationWithExistingDirectMapping() throws Exception { + + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.registerClassMap(factory.classMap(Library.class, LibraryMyDTO.class) + .field("title", "myTitle") + .field("books", "myBooks") + .byDefault() + .toClassMap()); + + factory.registerClassMap(factory.classMap(Author.class, AuthorMyDTO.class).field("name", "myName").byDefault().toClassMap()); + factory.registerClassMap(factory.classMap(Book.class, BookMyDTO.class) + .field("title", "myTitle") + .field("author", "myAuthor") + .byDefault() + .toClassMap()); + + MapperFacade mapper = factory.getMapperFacade(); + + Book book = createBook(BookParent.class); + book.setAuthor(createAuthor(AuthorParent.class)); + Library lib = createLibrary(LibraryParent.class); + lib.getBooks().add(book); + + LibraryMyDTO mappedLib = mapper.map(lib, LibraryMyDTO.class); + + Assert.assertEquals(lib.getTitle(), mappedLib.getMyTitle()); + Assert.assertEquals(book.getTitle(), mappedLib.getMyBooks().get(0).getMyTitle()); + Assert.assertEquals(book.getAuthor().getName(), mappedLib.getMyBooks().get(0).getMyAuthor().getMyName()); + } + + @Test + public void testMappingInterfaceImplementationWithExistingInheritedMapping() throws Exception { + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.registerClassMap(factory.classMap(Library.class, LibraryMyDTO.class) + .field("title", "myTitle") + .field("books", "myBooks") + .byDefault() + .toClassMap()); + + factory.registerClassMap(factory.classMap(Author.class, AuthorMyDTO.class).field("name", "myName").byDefault().toClassMap()); + factory.registerClassMap(factory.classMap(Book.class, BookMyDTO.class) + .field("title", "myTitle") + .field("author", "myAuthor") + .byDefault() + .toClassMap()); + + MapperFacade mapper = factory.getMapperFacade(); + + // BookChild, AuthorChild, LibraryChild don't directly + // implement Book, Author and Library + Book book = createBook(BookChild.class); + book.setAuthor(createAuthor(AuthorChild.class)); + Library lib = createLibrary(LibraryChild.class); + lib.getBooks().add(book); + + LibraryMyDTO mappedLib = mapper.map(lib, LibraryMyDTO.class); + + Assert.assertEquals(lib.getTitle(), mappedLib.getMyTitle()); + Assert.assertEquals(book.getTitle(), mappedLib.getMyBooks().get(0).getMyTitle()); + Assert.assertEquals(book.getAuthor().getName(), mappedLib.getMyBooks().get(0).getMyAuthor().getMyName()); + } + + @Test + public void testMappingSubclassImplementationWithoutExistingMapping() throws Exception { + + MapperFactory factory = MappingUtil.getMapperFactory(); + DefaultFieldMapper myHint = + /** + * This sample hint converts "myProperty" to "property", and vis-versa. + */ + (fromProperty, fromPropertyType) -> { + if (fromProperty.startsWith("my")) { + return fromProperty.substring(2, 1).toLowerCase() + fromProperty.substring(3); + } else { + return "my" + fromProperty.substring(0, 1).toUpperCase() + fromProperty.substring(1); + } + }; + factory.registerDefaultFieldMapper(myHint); + + MapperFacade mapper = factory.getMapperFacade(); + + Book book = createBook(BookChild.class); + book.setAuthor(createAuthor(AuthorChild.class)); + + BookMyDTO mappedBook = mapper.map(book, BookMyDTO.class); + + Assert.assertEquals(book.getTitle(), mappedBook.getMyTitle()); + Assert.assertEquals(book.getAuthor().getName(), mappedBook.getMyAuthor().getMyName()); + } + + @Test + public void testMappingSubclassImplementationWithExistingMapping() throws Exception { + + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.registerClassMap(factory.classMap(AuthorParent.class, AuthorMyDTO.class) + .field("name", "myName") + .byDefault() + .toClassMap()); + factory.registerClassMap(factory.classMap(BookParent.class, BookMyDTO.class) + .field("title", "myTitle") + .field("author", "myAuthor") + .byDefault() + .toClassMap()); + + MapperFacade mapper = factory.getMapperFacade(); + + Book book = createBook(BookChild.class); + book.setAuthor(createAuthor(AuthorChild.class)); + + BookMyDTO mappedBook = mapper.map(book, BookMyDTO.class); + + Assert.assertEquals(book.getTitle(), mappedBook.getMyTitle()); + Assert.assertEquals(book.getAuthor().getName(), mappedBook.getMyAuthor().getMyName()); + } + + public static class A { + XMLGregorianCalendar time; + + public A() { + } + + public XMLGregorianCalendar getTime() { + return time; + } + + public void setTime(XMLGregorianCalendar time) { + this.time = time; + } + } + + public static class B { + Date time; + + public B() { + } + + public Date getTime() { + return time; + } + + public void setTime(Date time) { + this.time = time; + } + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/UsedMappersTestCase.java b/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/UsedMappersTestCase.java new file mode 100644 index 00000000..62a87bd9 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/UsedMappersTestCase.java @@ -0,0 +1,166 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.boundmapperfacade; + +import org.junit.Assert; +import ma.glasnost.orika.BoundMapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.metadata.ClassMapBuilder; +import ma.glasnost.orika.test.MappingUtil; + +import org.junit.Test; + +public class UsedMappersTestCase { + + @Test + public void testReuseOfMapper() { + MapperFactory factory = MappingUtil.getMapperFactory(); + { + ClassMapBuilder classMapBuilder = factory.classMap(A.class, C.class); + classMapBuilder.field("name", "nom"); + factory.registerClassMap(classMapBuilder.toClassMap()); + } + + { + ClassMapBuilder classMapBuilder = factory.classMap(B.class, D.class); + classMapBuilder.field("age", "ages").use(A.class, C.class); + factory.registerClassMap(classMapBuilder.toClassMap()); + } + + BoundMapperFacade mapperFacade = factory.getMapperFacade(B.class, D.class); + + B source = new B(); + source.setName("Israfil"); + source.setAge(1000); + + D target = mapperFacade.map(source); + + Assert.assertEquals(source.getName(), target.getNom()); + Assert.assertEquals(source.getAge(), target.getAges()); + + } + + @Test + public void testOneCallOfFieldMapping() { + MapperFactory factory = MappingUtil.getMapperFactory(); + { + ClassMapBuilder classMapBuilder = factory.classMap(A.class, E.class); + factory.registerClassMap(classMapBuilder.byDefault().toClassMap()); + } + { + ClassMapBuilder classMapBuilder = factory.classMap(B.class, F.class); + classMapBuilder.byDefault().use(A.class, E.class); + factory.registerClassMap(classMapBuilder.toClassMap()); + } + + BoundMapperFacade mapperFacade = factory.getMapperFacade(B.class, F.class); + + B source = new B(); + source.setName("Israfil"); + source.setAge(1000); + + F target = mapperFacade.map(source); + + Assert.assertEquals(source.getName(), target.getName()); + Assert.assertEquals(source.getAge(), target.getAge()); + Assert.assertEquals(1, target.getNameCalls()); + } + + public static abstract class A { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + public static class B extends A { + private int age; + + public int getAge() { + return age; + } + + public void setAge(int ages) { + this.age = ages; + } + + } + + public static abstract class C { + private String nom; + + public String getNom() { + return nom; + } + + public void setNom(String nom) { + this.nom = nom; + } + + } + + public static class D extends C { + private int ages; + + public int getAges() { + return ages; + } + + public void setAges(int age) { + this.ages = age; + } + } + + public static abstract class E { + private String name; + private int nameCalls; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + nameCalls++; + } + + public int getNameCalls() { + return nameCalls; + } + + } + + public static class F extends E { + private int age; + + public int getAge() { + return age; + } + + public void setAge(int ages) { + this.age = ages; + } + + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/UserProvidedInheritanceTestCase.java b/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/UserProvidedInheritanceTestCase.java new file mode 100644 index 00000000..9cfbfeb9 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/boundmapperfacade/UserProvidedInheritanceTestCase.java @@ -0,0 +1,102 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.boundmapperfacade; + +import ma.glasnost.orika.CustomMapper; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.impl.DefaultMapperFactory; + +import org.junit.Assert; +import org.junit.Test; + +public class UserProvidedInheritanceTestCase { + + @Test + public void testFail() { + MapperFactory factory = new DefaultMapperFactory.Builder().build(); + + factory.registerClassMap(factory.classMap(Base.class, BaseDto.class).customize(new CustomMapper() { + @Override + public void mapAtoB(Base base, BaseDto baseDto, MappingContext context) { + baseDto.setBaseField(base.getBaseTrickField()); + } + }).toClassMap()); + factory.registerClassMap(factory.classMap(Child.class, ChildDto.class).byDefault().toClassMap()); + + Child child = new Child(); + child.setChildField("CHILD FIELD"); + child.setBaseTrickField("BASE FIELD"); + + ChildDto dto = factory.getMapperFacade(Child.class, ChildDto.class).map(child); + + Assert.assertNotNull(dto); + Assert.assertEquals(child.getChildField(), dto.getChildField()); + Assert.assertEquals(child.getBaseTrickField(), dto.getBaseField()); + + } + + public static class Base { + private String baseTrickField; + + public String getBaseTrickField() { + return baseTrickField; + } + + public void setBaseTrickField(String baseTrickField) { + this.baseTrickField = baseTrickField; + } + } + + public static class BaseDto { + private String baseField; + + public String getBaseField() { + return baseField; + } + + public void setBaseField(String baseField) { + this.baseField = baseField; + } + } + + public static class Child extends Base { + private String childField; + + public String getChildField() { + return childField; + } + + public void setChildField(String childField) { + this.childField = childField; + } + } + + public static class ChildDto extends BaseDto { + private String childField; + + public String getChildField() { + return childField; + } + + public void setChildField(String childField) { + this.childField = childField; + } + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/capturefieldcontext/FieldContextWithFiltersTestCase.java b/core/src/test/java/ma/glasnost/orika/test/capturefieldcontext/FieldContextWithFiltersTestCase.java new file mode 100644 index 00000000..543b21c5 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/capturefieldcontext/FieldContextWithFiltersTestCase.java @@ -0,0 +1,156 @@ +package ma.glasnost.orika.test.capturefieldcontext; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.NullFilter; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.metadata.Type; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class FieldContextWithFiltersTestCase { + + public static class Person { + public Name name; + public Address address; + public List contacts; + } + + public static class Name { + public String first; + public String middle; + public String last; + } + + public static class PersonDto { + public NameDto name; + public AddressDto address; + public List contacts; + } + + public static class NameDto { + public String first; + public String middle; + public String last; + } + + public static class Address { + public String street; + public String city; + public String state; + public String postalCode; + public String country; + } + + public static class AddressDto { + public String street; + public String city; + public String state; + public String zipCode; + public String country; + } + + /** + * In this test, we demonstrate that the fully-qualified source path + * can be referenced to make a filtering decision + */ + @Test + public void referenceFieldContextInFilters() throws Throwable { + + MapperFactory factory = new DefaultMapperFactory.Builder() + .captureFieldContext(true) + .build(); + + factory.classMap(Person.class, PersonDto.class) + .byDefault() + .register(); + + factory.classMap(Address.class, AddressDto.class) + .field("postalCode", "zipCode") + .byDefault() + .register(); + + factory.registerFilter(new AddressDepthFilter()); + + Person source = new Person(); + source.name = new Name(); + source.address = new Address(); + source.contacts = new ArrayList<>(); + source.name.first = "Kermit"; + source.name.middle = "The"; + source.name.last = "Frog"; + source.address.street = "123 Sesame St."; + source.address.city = "Manhattan"; + source.address.state = "NY"; + source.address.country = "USA"; + source.address.postalCode = "10023"; + + Person oscar = new Person(); + oscar.name = new Name(); + oscar.name.first = "Oscar"; + oscar.name.middle = "The"; + oscar.name.last = "Grouch"; + oscar.address = new Address(); + oscar.address.street = "123 Sesame St."; + oscar.address.city = "Manhattan"; + oscar.address.state = "NY"; + oscar.address.country = "USA"; + oscar.address.postalCode = "10023"; + source.contacts.add(oscar); + + Person bigbird = new Person(); + bigbird.name = new Name(); + bigbird.name.first = "Oscar"; + bigbird.name.middle = "The"; + bigbird.name.last = "Grouch"; + bigbird.address = new Address(); + bigbird.address.street = "123 Sesame St."; + bigbird.address.city = "Manhattan"; + bigbird.address.state = "NY"; + bigbird.address.country = "USA"; + bigbird.address.postalCode = "10023"; + source.contacts.add(bigbird); + + + MapperFacade mapper = factory.getMapperFacade(); + + PersonDto dest = mapper.map(source, PersonDto.class); + Assert.assertEquals(source.name.first, dest.name.first); + Assert.assertEquals(source.name.middle, dest.name.middle); + Assert.assertEquals(source.name.last, dest.name.last); + Assert.assertEquals(source.address.city, dest.address.city); + Assert.assertEquals(source.address.state, dest.address.state); + Assert.assertEquals(source.address.postalCode, dest.address.zipCode); + Assert.assertEquals(source.address.street, dest.address.street); + Assert.assertEquals(source.address.country, dest.address.country); + + Assert.assertNotNull(dest.contacts.get(0)); + Assert.assertNotNull(dest.contacts.get(0).name); + Assert.assertNull(dest.contacts.get(0).address); + + Assert.assertNotNull(dest.contacts.get(1)); + Assert.assertNotNull(dest.contacts.get(1).name); + Assert.assertNull(dest.contacts.get(1).address); + + } + + public static class AddressDepthFilter extends NullFilter { + + public boolean shouldMap(final Type sourceType, final String sourceName, final S source, final Type destType, final String destName, + final D dest, final MappingContext mappingContext) { + /* + * Don't map nested addresses + */ + if ("postalCode".equals(sourceName)) { + Assert.assertTrue(Arrays.equals(mappingContext.getDestinationExpressionPaths(), new String[]{"address", "zipCode"})); + } + return !"address".equals(sourceName) || + "source.address".equals(mappingContext.getFullyQualifiedSourcePath()); + } + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/collection/CollectionTestCase.java b/core/src/test/java/ma/glasnost/orika/test/collection/CollectionTestCase.java new file mode 100644 index 00000000..cc5f983e --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/collection/CollectionTestCase.java @@ -0,0 +1,242 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.collection; + +import ma.glasnost.orika.test.MappingUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class CollectionTestCase { + + @Test + public void testStringToString() { + D source = new D(); + source.setTags(Arrays.asList("soa", "java", "rest")); + + A destination = MappingUtil.getMapperFactory().getMapperFacade().map(source, A.class); + + Assert.assertNotNull(destination.getTags()); + Assert.assertEquals(3, destination.getTags().size()); + + Set sourceSet = new HashSet<>(source.getTags()); + Set destSet = new HashSet<>(destination.getTags()); + Assert.assertEquals(sourceSet, destSet); + } + + @Test + public void testListToSet() { + A source = new A(); + source.setTags(new HashSet<>(Arrays.asList("soa", "java", "rest"))); + + D destination = MappingUtil.getMapperFactory().getMapperFacade().map(source, D.class); + + Assert.assertNotNull(destination.getTags()); + Assert.assertEquals(3, destination.getTags().size()); + + Set sourceSet = new HashSet<>(source.getTags()); + Set destSet = new HashSet<>(destination.getTags()); + Assert.assertEquals(sourceSet, destSet); + } + + @Test + public void testStringToStringWithGetterOnlyCollection() { + D source = new D(); + source.setTags(Arrays.asList("soa", "java", "rest")); + + B destination = MappingUtil.getMapperFactory().getMapperFacade().map(source, B.class); + + Assert.assertNotNull(destination.getTags()); + Assert.assertEquals(3, destination.getTags().size()); + + Set sourceSet = new HashSet<>(source.getTags()); + Set destSet = new HashSet<>(destination.getTags()); + Assert.assertEquals(sourceSet, destSet); + } + + @Test + public void nullSourceCollection_toCollection() { + Source source = new Source(); + + Destination destination = MappingUtil.getMapperFactory().getMapperFacade().map(source, Destination.class); + + Assert.assertNull(destination.getNames()); + } + + @Test + public void nullSourceCollection_toArray() { + Source source = new Source(); + + Destination2 destination = MappingUtil.getMapperFactory().getMapperFacade().map(source, Destination2.class); + + Assert.assertNull(destination.getNames()); + } + + @Test + public void unmodifiableCollection() { + Source3 source = new Source3(); + source.setNames(Arrays.asList("soa", "java", "rest")); + + Destination3 destination = MappingUtil.getMapperFactory().getMapperFacade().map(source, Destination3.class); + + Assert.assertNotNull(destination.getNames()); + Assert.assertEquals(3, destination.getNames().size()); + } + + + static public class A { + private Set tags; + + public Set getTags() { + return tags; + } + + public void setTags(Set tags) { + this.tags = tags; + } + } + + public static class D { + private List tags; + + public List getTags() { + return tags; + } + + public void setTags(List tags) { + this.tags = tags; + } + } + + public static class B { + + private List tags; + + // Collection as typically generated by JAXB + public List getTags() { + if (tags==null) { + tags = new ArrayList<>(); + } + return tags; + } + + } + + public static class Name { + public String first; + public String last; + } + + public static class Source { + private List names; + + /** + * @return the names + */ + public List getNames() { + return names; + } + + /** + * @param names the names to set + */ + public void setNames(List names) { + this.names = names; + } + } + + public static class Destination { + private List names; + + /** + * @return the names + */ + public List getNames() { + return names; + } + + /** + * @param names the names to set + */ + public void setNames(List names) { + this.names = names; + } + } + + public static class Destination2 { + private Name[] names; + + /** + * @return the names + */ + public Name[] getNames() { + return names; + } + + /** + * @param names the names to set + */ + public void setNames(Name[] names) { + this.names = names; + } + } + + public static class Source3 { + private List names; + + /** + * @return the names + */ + public List getNames() { + return Collections.unmodifiableList(names); + } + + /** + * @param names the names to set + */ + public void setNames(List names) { + this.names = names; + } + } + + public static class Destination3 { + private List names; + + /** + * @return the names + */ + public List getNames() { + return Collections.unmodifiableList(names); + } + + /** + * @param names the names to set + */ + public void setNames(List names) { + this.names = names; + } + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/collection/ExplicitCollectionTestCase.java b/core/src/test/java/ma/glasnost/orika/test/collection/ExplicitCollectionTestCase.java new file mode 100644 index 00000000..f17460ce --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/collection/ExplicitCollectionTestCase.java @@ -0,0 +1,92 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.collection; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +import ma.glasnost.orika.test.MappingUtil; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Test a class that User: kenton Date: 12/7/12 Time: 10:50 AM + */ +public class ExplicitCollectionTestCase { + + @Test + public void testStringToStringWithSpecifiedGenericType() { + ExplicitSet set = new ExplicitSet(); + set.add("1"); + set.add("2"); + A source = new A(); + source.setStrings(set); + + B destination = MappingUtil.getMapperFactory().getMapperFacade().map(source, B.class); + + Assert.assertNotNull(destination.getStrings()); + Assert.assertEquals(set.size(), destination.getStrings().size()); + } + + public static class A { + private ExplicitSet strings; + + public ExplicitSet getStrings() { + return strings; + } + + public void setStrings(ExplicitSet strings) { + this.strings = strings; + } + } + + public static class B { + private Set strings; + + public Set getStrings() { + return strings; + } + + public void setStrings(Set strings) { + this.strings = strings; + } + } + + public static class ExplicitSet extends HashSet { + + private static final long serialVersionUID = 1L; + + public ExplicitSet(int i) { + super(i); + } + + public ExplicitSet(int i, float v) { + super(i, v); + } + + public ExplicitSet(Collection strings) { + super(strings); + } + + public ExplicitSet() { + } + } +} \ No newline at end of file diff --git a/core/src/test/java/ma/glasnost/orika/test/collection/ObjectCollectionTestCase.java b/core/src/test/java/ma/glasnost/orika/test/collection/ObjectCollectionTestCase.java new file mode 100644 index 00000000..33d6a446 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/collection/ObjectCollectionTestCase.java @@ -0,0 +1,194 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.collection; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Objects; + +/** + * Simple test of maaping collection + * + * @author Dmitriy Khomyakov + */ +public class ObjectCollectionTestCase { + + @Test + public void testMapOfCollection() { + DefaultMapperFactory.Builder builder = new DefaultMapperFactory.Builder(); + MapperFactory factory = builder.build(); + + MapperFacade mapperFacade = factory.getMapperFacade(); + + List dtos = new ArrayList<>(); + + Dto dto = new Dto(); + dto.setId(1L); + dto.setName("A"); + dtos.add(dto); + + Dto dto2 = new Dto(); + dto2.setId(2L); + dto2.setName("B"); + dtos.add(dto2); + + dto = new Dto(); + dto.setId(3L); + dto.setName("C"); + dtos.add(dto); + + DtoHolder source = new DtoHolder(); + source.setEntities(dtos); + + final EntityHolder entities = mapperFacade.map(source, EntityHolder.class); + + Assert.assertNotNull(entities); + Assert.assertEquals(3, entities.getEntities().size()); + + } + + public static class Entity { + + private Long id; + private String name; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public boolean isNew() { + return id == null; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof Entity)) { + return false; + } + + Entity entity = (Entity) o; + + if (!Objects.equals(id, entity.id)) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + return id != null ? id.hashCode() : 0; + } + } + + public static class EntityHolder { + + private Collection entityList; + + public Collection getEntities() { + return entityList; + } + + public void setEntities(Collection entityList) { + this.entityList = entityList; + } + + } + + public static class Dto { + private Long id; + private String name; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof Dto)) { + return false; + } + + Dto dto = (Dto) o; + + if (!Objects.equals(id, dto.id)) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + return id != null ? id.hashCode() : 0; + } + } + + public static class DtoHolder { + + private Collection dtoList; + + public Collection getEntities() { + return dtoList; + } + + public void setEntities(Collection dtoList) { + this.dtoList = dtoList; + } + + } + +} \ No newline at end of file diff --git a/core/src/test/java/ma/glasnost/orika/test/common/types/TestCaseClasses.java b/core/src/test/java/ma/glasnost/orika/test/common/types/TestCaseClasses.java new file mode 100644 index 00000000..1a3f2425 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/common/types/TestCaseClasses.java @@ -0,0 +1,934 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.common.types; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +public interface TestCaseClasses { + + class PrimitiveHolder { + private final short shortValue; + private final int intValue; + private final long longValue; + private final float floatValue; + private final double doubleValue; + private final char charValue; + private final boolean booleanValue; + private final byte byteValue; + + public PrimitiveHolder(short shortValue, int intValue, long longValue, + float floatValue, double doubleValue, char charValue, boolean booleanValue, byte byteValue) { + super(); + this.shortValue = shortValue; + this.intValue = intValue; + this.longValue = longValue; + this.floatValue = floatValue; + this.doubleValue = doubleValue; + this.charValue = charValue; + this.booleanValue = booleanValue; + this.byteValue = byteValue; + } + + public short getShortValue() { + return shortValue; + } + + public int getIntValue() { + return intValue; + } + + public long getLongValue() { + return longValue; + } + + public float getFloatValue() { + return floatValue; + } + + public double getDoubleValue() { + return doubleValue; + } + + public char getCharValue() { + return charValue; + } + + public boolean isBooleanValue() { + return booleanValue; + } + + public byte getByteValue() { + return byteValue; + } + + @Override + public String toString() { + return "PrimitiveHolder [shortValue=" + shortValue + ", intValue=" + intValue + ", longValue=" + longValue + + ", floatValue=" + floatValue + ", doubleValue=" + doubleValue + ", charValue=" + charValue + + ", booleanValue=" + booleanValue + ", byteValue=" + byteValue + "]"; + } + + @Override + public boolean equals(final Object other) { + if (!(other instanceof PrimitiveHolder)) { + return false; + } + PrimitiveHolder castOther = (PrimitiveHolder) other; + return Objects.equals(shortValue, castOther.shortValue) && Objects.equals(intValue, castOther.intValue) + && Objects.equals(longValue, castOther.longValue) + && Objects.equals(floatValue, castOther.floatValue) + && Objects.equals(doubleValue, castOther.doubleValue) + && Objects.equals(charValue, castOther.charValue) + && Objects.equals(booleanValue, castOther.booleanValue) + && Objects.equals(byteValue, castOther.byteValue); + } + + @Override + public int hashCode() { + return Objects.hash(shortValue, intValue, longValue, floatValue, doubleValue, charValue, booleanValue, + byteValue); + } + } + + class PrimitiveHolderDTO { + private short shortValue; + private int intValue; + private long longValue; + private float floatValue; + private double doubleValue; + private char charValue; + private boolean booleanValue; + private byte byteValue; + + public short getShortValue() { + return shortValue; + } + public void setShortValue(short shortValue) { + this.shortValue = shortValue; + } + public int getIntValue() { + return intValue; + } + public void setIntValue(int intValue) { + this.intValue = intValue; + } + public long getLongValue() { + return longValue; + } + public void setLongValue(long longValue) { + this.longValue = longValue; + } + public float getFloatValue() { + return floatValue; + } + public void setFloatValue(float floatValue) { + this.floatValue = floatValue; + } + public double getDoubleValue() { + return doubleValue; + } + public void setDoubleValue(double doubleValue) { + this.doubleValue = doubleValue; + } + public char getCharValue() { + return charValue; + } + public void setCharValue(char charValue) { + this.charValue = charValue; + } + public boolean isBooleanValue() { + return booleanValue; + } + public void setBooleanValue(boolean booleanValue) { + this.booleanValue = booleanValue; + } + public byte getByteValue() { + return byteValue; + } + public void setByteValue(byte byteValue) { + this.byteValue = byteValue; + } + @Override + public String toString() { + return "PrimitiveHolderDTO [shortValue=" + shortValue + ", intValue=" + intValue + ", longValue=" + + longValue + ", floatValue=" + floatValue + ", doubleValue=" + doubleValue + ", charValue=" + + charValue + ", booleanValue=" + booleanValue + ", byteValue=" + byteValue + "]"; + } + @Override + public boolean equals(final Object other) { + if (!(other instanceof PrimitiveHolderDTO)) { + return false; + } + PrimitiveHolderDTO castOther = (PrimitiveHolderDTO) other; + return Objects.equals(shortValue, castOther.shortValue) && Objects.equals(intValue, castOther.intValue) + && Objects.equals(longValue, castOther.longValue) + && Objects.equals(floatValue, castOther.floatValue) + && Objects.equals(doubleValue, castOther.doubleValue) + && Objects.equals(charValue, castOther.charValue) + && Objects.equals(booleanValue, castOther.booleanValue) + && Objects.equals(byteValue, castOther.byteValue); + } + @Override + public int hashCode() { + return Objects.hash(shortValue, intValue, longValue, floatValue, doubleValue, charValue, booleanValue, + byteValue); + } + } + + class PrimitiveWrapperHolder { + private final Short shortValue; + private final Integer intValue; + private final Long longValue; + private final Float floatValue; + private final Double doubleValue; + private final Character charValue; + private final Boolean booleanValue; + private final Byte byteValue; + + public PrimitiveWrapperHolder(Short shortValue, Integer intValue, + Long longValue, Float floatValue, Double doubleValue, + Character charValue, Boolean booleanValue, Byte byteValue) { + super(); + this.shortValue = shortValue; + this.intValue = intValue; + this.longValue = longValue; + this.floatValue = floatValue; + this.doubleValue = doubleValue; + this.charValue = charValue; + this.booleanValue = booleanValue; + this.byteValue = byteValue; + } + + public Short getShortValue() { + return shortValue; + } + + public Integer getIntValue() { + return intValue; + } + + public Long getLongValue() { + return longValue; + } + + public Float getFloatValue() { + return floatValue; + } + + public Double getDoubleValue() { + return doubleValue; + } + + public Character getCharValue() { + return charValue; + } + + public Boolean getBooleanValue() { + return booleanValue; + } + + public Byte getByteValue() { + return byteValue; + } + + @Override + public String toString() { + return "PrimitiveWrapperHolder [shortValue=" + shortValue + ", intValue=" + intValue + ", longValue=" + + longValue + ", floatValue=" + floatValue + ", doubleValue=" + doubleValue + ", charValue=" + + charValue + ", booleanValue=" + booleanValue + ", byteValue=" + byteValue + "]"; + } + + @Override + public boolean equals(final Object other) { + if (!(other instanceof PrimitiveWrapperHolder)) { + return false; + } + PrimitiveWrapperHolder castOther = (PrimitiveWrapperHolder) other; + return Objects.equals(shortValue, castOther.shortValue) && Objects.equals(intValue, castOther.intValue) + && Objects.equals(longValue, castOther.longValue) + && Objects.equals(floatValue, castOther.floatValue) + && Objects.equals(doubleValue, castOther.doubleValue) + && Objects.equals(charValue, castOther.charValue) + && Objects.equals(booleanValue, castOther.booleanValue) + && Objects.equals(byteValue, castOther.byteValue); + } + + @Override + public int hashCode() { + return Objects.hash(shortValue, intValue, longValue, floatValue, doubleValue, charValue, booleanValue, + byteValue); + } + } + + class PrimitiveWrapperHolderDTO { + private Short shortValue; + private Integer intValue; + private Long longValue; + private Float floatValue; + private Double doubleValue; + private Character charValue; + private Boolean booleanValue; + private Byte byteValue; + + public Short getShortValue() { + return shortValue; + } + public void setShortValue(Short shortValue) { + this.shortValue = shortValue; + } + public Integer getIntValue() { + return intValue; + } + public void setIntValue(Integer intValue) { + this.intValue = intValue; + } + public Long getLongValue() { + return longValue; + } + public void setLongValue(Long longValue) { + this.longValue = longValue; + } + public Float getFloatValue() { + return floatValue; + } + public void setFloatValue(Float floatValue) { + this.floatValue = floatValue; + } + public Double getDoubleValue() { + return doubleValue; + } + public void setDoubleValue(Double doubleValue) { + this.doubleValue = doubleValue; + } + public Character getCharValue() { + return charValue; + } + public void setCharValue(Character charValue) { + this.charValue = charValue; + } + public Boolean getBooleanValue() { + return booleanValue; + } + public void setBooleanValue(Boolean booleanValue) { + this.booleanValue = booleanValue; + } + + public Byte getByteValue() { + return byteValue; + } + public void setByteValue(Byte byteValue) { + this.byteValue = byteValue; + } + @Override + public String toString() { + return "PrimitiveWrapperHolderDTO [shortValue=" + shortValue + ", intValue=" + intValue + ", longValue=" + + longValue + ", floatValue=" + floatValue + ", doubleValue=" + doubleValue + ", charValue=" + + charValue + ", booleanValue=" + booleanValue + ", byteValue=" + byteValue + "]"; + } + @Override + public boolean equals(final Object other) { + if (!(other instanceof PrimitiveWrapperHolderDTO)) { + return false; + } + PrimitiveWrapperHolderDTO castOther = (PrimitiveWrapperHolderDTO) other; + return Objects.equals(shortValue, castOther.shortValue) && Objects.equals(intValue, castOther.intValue) + && Objects.equals(longValue, castOther.longValue) + && Objects.equals(floatValue, castOther.floatValue) + && Objects.equals(doubleValue, castOther.doubleValue) + && Objects.equals(charValue, castOther.charValue) + && Objects.equals(booleanValue, castOther.booleanValue) + && Objects.equals(byteValue, castOther.byteValue); + } + @Override + public int hashCode() { + return Objects.hash(shortValue, intValue, longValue, floatValue, doubleValue, charValue, booleanValue, + byteValue); + } + } + + interface Book { + + String getTitle(); + Author getAuthor(); + + } + + interface Author { + + String getName(); + + } + + interface Library { + + String getTitle(); + List getBooks(); + } + + class BookImpl implements Book { + + private final String title; + private final Author author; + + public BookImpl(String title, Author author) { + this.title = title; + this.author = author; + } + + public String getTitle() { + return title; + } + + public Author getAuthor() { + return author; + } + + @Override + public String toString() { + return "BookImpl [title=" + title + ", author=" + author + "]"; + } + + @Override + public boolean equals(final Object other) { + if (!(other instanceof BookImpl)) { + return false; + } + BookImpl castOther = (BookImpl) other; + return Objects.equals(title, castOther.title) && Objects.equals(author, castOther.author); + } + + @Override + public int hashCode() { + return Objects.hash(title, author); + } + } + + class AuthorImpl implements Author { + + private final String name; + + public AuthorImpl(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + @Override + public String toString() { + return "AuthorImpl [name=" + name + "]"; + } + + @Override + public boolean equals(final Object other) { + if (!(other instanceof AuthorImpl)) { + return false; + } + AuthorImpl castOther = (AuthorImpl) other; + return Objects.equals(name, castOther.name); + } + + @Override + public int hashCode() { + return Objects.hash(name); + } + } + + class AuthorNested { + + private final Name name; + + public AuthorNested(Name name) { + this.name = name; + } + + public Name getName() { + + return name; + } + @Override + public String toString() { + return "AuthorNested [name=" + name + "]"; + } + + @Override + public boolean equals(final Object other) { + if (!(other instanceof AuthorNested)) { + return false; + } + AuthorNested castOther = (AuthorNested) other; + return Objects.equals(name, castOther.name); + } + + @Override + public int hashCode() { + return Objects.hash(name); + } + } + + class Name { + private final String firstName; + private final String lastName; + + public Name(String firstName, String lastName) { + this.firstName = firstName; + this.lastName = lastName; + } + + public String getFirstName() { + return firstName; + } + + public String getLastName() { + return lastName; + } + + public String getFullName() { + return firstName + " " + lastName; + } + @Override + public String toString() { + return "Name [firstName=" + firstName + ", lastName=" + lastName + "]"; + } + + @Override + public boolean equals(final Object other) { + if (!(other instanceof Name)) { + return false; + } + Name castOther = (Name) other; + return Objects.equals(firstName, castOther.firstName) && Objects.equals(lastName, castOther.lastName); + } + + @Override + public int hashCode() { + return Objects.hash(firstName, lastName); + } + } + + class LibraryNested { + + private final String title; + private final List books; + + + public LibraryNested(String title, List books) { + super(); + this.title = title; + this.books = books; + } + + public String getTitle() { + return title; + } + + public List getBooks() { + return books; + } + @Override + public String toString() { + return "LibraryNested [title=" + title + ", books=" + books + "]"; + } + + @Override + public boolean equals(final Object other) { + if (!(other instanceof LibraryNested)) { + return false; + } + LibraryNested castOther = (LibraryNested) other; + return Objects.equals(title, castOther.title) && Objects.equals(books, castOther.books); + } + + @Override + public int hashCode() { + return Objects.hash(title, books); + } + } + + class BookNested { + private final String title; + private final AuthorNested author; + + public BookNested(String title, AuthorNested author) { + super(); + this.title = title; + this.author = author; + } + + public String getTitle() { + return title; + } + + public AuthorNested getAuthor() { + return author; + } + @Override + public String toString() { + return "BookNested [title=" + title + ", author=" + author + "]"; + } + + @Override + public boolean equals(final Object other) { + if (!(other instanceof BookNested)) { + return false; + } + BookNested castOther = (BookNested) other; + return Objects.equals(title, castOther.title) && Objects.equals(author, castOther.author); + } + + @Override + public int hashCode() { + return Objects.hash(title, author); + } + + } + + class LibraryImpl implements Library { + + private final String title; + private List books; + + public LibraryImpl(String title, List books) { + super(); + this.title = title; + this.books = books; + } + + public String getTitle() { + return title; + } + + public List getBooks() { + if (books==null) { + books = new ArrayList<>(); + } + return books; + } + + @Override + public String toString() { + return "LibraryImpl [title=" + title + ", books=" + books + "]"; + } + + @Override + public boolean equals(final Object other) { + if (!(other instanceof LibraryImpl)) { + return false; + } + LibraryImpl castOther = (LibraryImpl) other; + return Objects.equals(title, castOther.title) && Objects.equals(books, castOther.books); + } + + @Override + public int hashCode() { + return Objects.hash(title, books); + } + + } + + + + class AuthorDTO { + + private String name; + private String additionalValue; + + public String getAdditionalValue() { + return additionalValue; + } + + public void setAdditionalValue(String additionalValue) { + this.additionalValue = additionalValue; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public String toString() { + return "AuthorDTO [name=" + name + ", additionalValue=" + additionalValue + "]"; + } + + @Override + public boolean equals(final Object other) { + if (!(other instanceof AuthorDTO)) { + return false; + } + AuthorDTO castOther = (AuthorDTO) other; + return Objects.equals(name, castOther.name) && Objects.equals(additionalValue, castOther.additionalValue); + } + + @Override + public int hashCode() { + return Objects.hash(name, additionalValue); + } + } + + class BookDTO { + + private String title; + private AuthorDTO author; + private String additionalValue; + + public String getAdditionalValue() { + return additionalValue; + } + + public void setAdditionalValue(String additionalValue) { + this.additionalValue = additionalValue; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public AuthorDTO getAuthor() { + return author; + } + + public void setAuthor(AuthorDTO author) { + this.author = author; + } + + @Override + public String toString() { + return "BookDTO [title=" + title + ", author=" + author + ", additionalValue=" + additionalValue + "]"; + } + + @Override + public boolean equals(final Object other) { + if (!(other instanceof BookDTO)) { + return false; + } + BookDTO castOther = (BookDTO) other; + return Objects.equals(title, castOther.title) && Objects.equals(author, castOther.author) + && Objects.equals(additionalValue, castOther.additionalValue); + } + + @Override + public int hashCode() { + return Objects.hash(title, author, additionalValue); + } + } + + class LibraryDTO { + + private String title; + private List books; + private String additionalValue; + + public String getAdditionalValue() { + return additionalValue; + } + + public void setAdditionalValue(String additionalValue) { + this.additionalValue = additionalValue; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public List getBooks() { + if (books==null) { + books = new ArrayList<>(); + } + return books; + } + + @Override + public String toString() { + return "LibraryDTO [title=" + title + ", books=" + books + ", additionalValue=" + additionalValue + "]"; + } + + @Override + public boolean equals(final Object other) { + if (!(other instanceof LibraryDTO)) { + return false; + } + LibraryDTO castOther = (LibraryDTO) other; + return Objects.equals(title, castOther.title) && Objects.equals(books, castOther.books) + && Objects.equals(additionalValue, castOther.additionalValue); + } + + @Override + public int hashCode() { + return Objects.hash(title, books, additionalValue); + } + } + + + class AuthorMyDTO { + + private String name; + private String additionalValue; + + public String getMyAdditionalValue() { + return additionalValue; + } + + public void setMyAdditionalValue(String additionalValue) { + this.additionalValue = additionalValue; + } + + public String getMyName() { + return name; + } + + public void setMyName(String name) { + this.name = name; + } + + @Override + public String toString() { + return "AuthorMyDTO [name=" + name + ", additionalValue=" + additionalValue + "]"; + } + + @Override + public boolean equals(final Object other) { + if (!(other instanceof AuthorMyDTO)) { + return false; + } + AuthorMyDTO castOther = (AuthorMyDTO) other; + return Objects.equals(name, castOther.name) && Objects.equals(additionalValue, castOther.additionalValue); + } + + @Override + public int hashCode() { + return Objects.hash(name, additionalValue); + } + } + + class BookMyDTO { + + private String title; + private AuthorMyDTO author; + private String additionalValue; + + public String getMyAdditionalValue() { + return additionalValue; + } + + public void setMyAdditionalValue(String additionalValue) { + this.additionalValue = additionalValue; + } + + public String getMyTitle() { + return title; + } + + public void setMyTitle(String title) { + this.title = title; + } + + public AuthorMyDTO getMyAuthor() { + return author; + } + + public void setMyAuthor(AuthorMyDTO author) { + this.author = author; + } + + @Override + public String toString() { + return "BookMyDTO [title=" + title + ", author=" + author + ", additionalValue=" + additionalValue + "]"; + } + + @Override + public boolean equals(final Object other) { + if (!(other instanceof BookMyDTO)) { + return false; + } + BookMyDTO castOther = (BookMyDTO) other; + return Objects.equals(title, castOther.title) && Objects.equals(author, castOther.author) + && Objects.equals(additionalValue, castOther.additionalValue); + } + + @Override + public int hashCode() { + return Objects.hash(title, author, additionalValue); + } + } + + class LibraryMyDTO { + + private String title; + private List books; + private String additionalValue; + + public String getMyAdditionalValue() { + return additionalValue; + } + + public void setMyAdditionalValue(String additionalValue) { + this.additionalValue = additionalValue; + } + + public String getMyTitle() { + return title; + } + + public void setMyTitle(String title) { + this.title = title; + } + + public List getMyBooks() { + if (books==null) { + books = new ArrayList<>(); + } + return books; + } + + @Override + public String toString() { + return "LibraryMyDTO [title=" + title + ", books=" + books + ", additionalValue=" + additionalValue + "]"; + } + + @Override + public boolean equals(final Object other) { + if (!(other instanceof LibraryMyDTO)) { + return false; + } + LibraryMyDTO castOther = (LibraryMyDTO) other; + return Objects.equals(title, castOther.title) && Objects.equals(books, castOther.books) + && Objects.equals(additionalValue, castOther.additionalValue); + } + + @Override + public int hashCode() { + return Objects.hash(title, books, additionalValue); + } + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/common/types/Validations.java b/core/src/test/java/ma/glasnost/orika/test/common/types/Validations.java new file mode 100644 index 00000000..5b0903fd --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/common/types/Validations.java @@ -0,0 +1,143 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.common.types; + +import ma.glasnost.orika.test.common.types.TestCaseClasses.Author; +import ma.glasnost.orika.test.common.types.TestCaseClasses.AuthorDTO; +import ma.glasnost.orika.test.common.types.TestCaseClasses.AuthorNested; +import ma.glasnost.orika.test.common.types.TestCaseClasses.Book; +import ma.glasnost.orika.test.common.types.TestCaseClasses.BookDTO; +import ma.glasnost.orika.test.common.types.TestCaseClasses.BookNested; +import ma.glasnost.orika.test.common.types.TestCaseClasses.Library; +import ma.glasnost.orika.test.common.types.TestCaseClasses.LibraryDTO; +import ma.glasnost.orika.test.common.types.TestCaseClasses.LibraryNested; +import ma.glasnost.orika.test.common.types.TestCaseClasses.PrimitiveHolder; +import ma.glasnost.orika.test.common.types.TestCaseClasses.PrimitiveHolderDTO; +import ma.glasnost.orika.test.common.types.TestCaseClasses.PrimitiveWrapperHolder; +import ma.glasnost.orika.test.common.types.TestCaseClasses.PrimitiveWrapperHolderDTO; + +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +public class Validations { + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Common mapping validations + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + public static void assertValidMapping(PrimitiveHolder primitiveHolder, PrimitiveHolderDTO dto) { + assertEquals(primitiveHolder.getShortValue(), dto.getShortValue()); + assertEquals(primitiveHolder.getIntValue(), dto.getIntValue()); + assertEquals(primitiveHolder.getLongValue(), dto.getLongValue()); + assertEquals(primitiveHolder.getFloatValue(), dto.getFloatValue(), 1.0f); + assertEquals(primitiveHolder.getDoubleValue(), dto.getDoubleValue(), 1.0d); + assertEquals(primitiveHolder.getCharValue(), dto.getCharValue()); + assertEquals(primitiveHolder.isBooleanValue(), dto.isBooleanValue()); + } + + public static void assertValidMapping(PrimitiveWrapperHolder primitiveHolder, PrimitiveWrapperHolderDTO dto) { + assertEquals(primitiveHolder.getShortValue(), dto.getShortValue()); + assertEquals(primitiveHolder.getIntValue(), dto.getIntValue()); + assertEquals(primitiveHolder.getLongValue(), dto.getLongValue()); + assertEquals(primitiveHolder.getFloatValue(), dto.getFloatValue(), 1.0f); + assertEquals(primitiveHolder.getDoubleValue(), dto.getDoubleValue(), 1.0d); + assertEquals(primitiveHolder.getCharValue(), dto.getCharValue()); + assertEquals(primitiveHolder.getBooleanValue(), dto.getBooleanValue()); + } + + public static void assertValidMapping(PrimitiveWrapperHolder wrappers, PrimitiveHolder primitives) { + assertEquals(wrappers.getShortValue().shortValue(), primitives.getShortValue()); + assertEquals(wrappers.getIntValue().intValue(), primitives.getIntValue()); + assertEquals(wrappers.getLongValue().longValue(), primitives.getLongValue()); + assertEquals(wrappers.getFloatValue(), primitives.getFloatValue(), 1.0f); + assertEquals(wrappers.getDoubleValue(), primitives.getDoubleValue(), 1.0d); + assertEquals(wrappers.getCharValue().charValue(), primitives.getCharValue()); + assertEquals(wrappers.getBooleanValue(), primitives.isBooleanValue()); + } + + + public static void assertValidMapping(Library library, LibraryDTO dto) { + + assertNotNull(library); + assertNotNull(dto); + + assertNotNull(library.getBooks()); + assertNotNull(dto.getBooks()); + + List sortedBooks = library.getBooks(); + + List sortedDTOs = dto.getBooks(); + + assertEquals(sortedBooks.size(), sortedDTOs.size()); + + for (int i = 0, count=sortedBooks.size(); i < count; ++i) { + Book book = sortedBooks.get(i); + BookDTO bookDto = sortedDTOs.get(i); + assertValidMapping(book,bookDto); + } + } + + public static void assertValidMapping(LibraryNested library, LibraryDTO dto) { + + assertNotNull(library); + assertNotNull(dto); + + assertNotNull(library.getBooks()); + assertNotNull(dto.getBooks()); + + List sortedBooks = library.getBooks(); + + List sortedDTOs = dto.getBooks(); + + assertEquals(sortedBooks.size(), sortedDTOs.size()); + + for (int i = 0, count=sortedBooks.size(); i < count; ++i) { + BookNested book = sortedBooks.get(i); + BookDTO bookDto = sortedDTOs.get(i); + assertValidMapping(book,bookDto); + } + } + + public static void assertValidMapping(Book book, BookDTO dto) { + assertNotNull(book); + assertNotNull(dto); + assertEquals(book.getTitle(), dto.getTitle()); + assertValidMapping(book.getAuthor(), dto.getAuthor()); + } + + public static void assertValidMapping(BookNested book, BookDTO dto) { + assertNotNull(book); + assertNotNull(dto); + assertEquals(book.getTitle(), dto.getTitle()); + assertValidMapping(book.getAuthor(), dto.getAuthor()); + } + + public static void assertValidMapping(Author author, AuthorDTO authorDTO) { + assertNotNull(author); + assertNotNull(authorDTO); + assertEquals(author.getName(),authorDTO.getName()); + } + + public static void assertValidMapping(AuthorNested author, AuthorDTO authorDTO) { + assertNotNull(author); + assertNotNull(authorDTO); + assertEquals(author.getName().getFullName(),authorDTO.getName()); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/AutomaticStringConversionTestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/AutomaticStringConversionTestCase.java new file mode 100644 index 00000000..9a9fdeec --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/AutomaticStringConversionTestCase.java @@ -0,0 +1,140 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import java.io.Serializable; + +import org.junit.Assert; +import org.junit.Test; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; + +public class AutomaticStringConversionTestCase { + + public static class CamposEntrada implements Serializable { + + private static final long serialVersionUID = -1751914753847603413L; + + private int numero; + private String prefijo; + private String orden; + private int id; + + public int getNumero() { + return numero; + } + + public void setNumero(int numero) { + this.numero = numero; + } + + public String getPrefijo() { + return prefijo; + } + + public void setPrefijo(String prefijo) { + this.prefijo = prefijo; + } + + public String getOrden() { + return orden; + } + + public void setOrden(String orden) { + this.orden = orden; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + } + + public static class CamposSalida implements Serializable { + + private static final long serialVersionUID = -1775063854225489603L; + + private String numero; + private int prefijo; + private String orden; + private int id; + + public String getNumero() { + return numero; + } + + public void setNumero(String numero) { + this.numero = numero; + } + + public int getPrefijo() { + return prefijo; + } + + public void setPrefijo(int prefijo) { + this.prefijo = prefijo; + } + + public String getOrden() { + return orden; + } + + public void setOrden(String orden) { + this.orden = orden; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + } + + @Test + public void testMapCamposEntradaToCamposSalida() throws Exception { + + CamposEntrada source = new CamposEntrada(); + source.setId(5); + source.setNumero(77); + source.setOrden("ASC"); + source.setPrefijo("2"); + + MapperFactory factory = new DefaultMapperFactory.Builder().build(); + factory.classMap(CamposEntrada.class, CamposSalida.class) + .byDefault() + .register(); + + MapperFacade facade = factory.getMapperFacade(); + + CamposSalida result = facade.map(source, CamposSalida.class); + + Assert.assertEquals(result.getId(), source.getId()); + Assert.assertEquals(result.getNumero(), ""+source.getNumero()); + Assert.assertEquals(result.getOrden(), source.getOrden()); + Assert.assertEquals(""+result.getPrefijo(), source.getPrefijo()); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/CheckedExceptionTest.java b/core/src/test/java/ma/glasnost/orika/test/community/CheckedExceptionTest.java new file mode 100644 index 00000000..6bb032d5 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/CheckedExceptionTest.java @@ -0,0 +1,45 @@ +package ma.glasnost.orika.test.community; + +import java.io.IOException; + +import org.junit.Assert; +import org.junit.Test; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.test.MappingUtil; + +public class CheckedExceptionTest { + + @Test + public void test() throws Throwable { + MapperFactory factory = MappingUtil.getMapperFactory(); + factory + .classMap(Source.class, Destination.class) + .byDefault() + .register(); + + MapperFacade mapper = factory.getMapperFacade(); + + Destination dest = mapper.map(new Source(), Destination.class); + Assert.assertEquals("value", dest.getValue()); + } + + public static class Source { + public String getValue() throws IOException { + return "value"; + } + } + + public static class Destination { + public String value; + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/CustomMergerTest.java b/core/src/test/java/ma/glasnost/orika/test/community/CustomMergerTest.java new file mode 100644 index 00000000..ca9b2f4f --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/CustomMergerTest.java @@ -0,0 +1,394 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import ma.glasnost.orika.CustomMapper; +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.impl.UtilityResolver; +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.metadata.TypeBuilder; +import ma.glasnost.orika.metadata.TypeFactory; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Objects; +import java.util.Set; + +/** + * @author matt.deboer@gmail.com + */ +public class CustomMergerTest { + + @Test + public void testMergingWithCustomMapper() { + MapperFacade mapper = createMapperFacade(); + + List dtos = new ArrayList<>(); + + Dto dto = new Dto(); + dto.setId(1L); + dto.setName("A"); + dtos.add(dto); + + Dto dto2 = new Dto(); + dto2.setId(2L); + dto2.setName("B"); + dtos.add(dto2); + + dto = new Dto(); + dto.setId(3L); + dto.setName("C"); + dtos.add(dto); + + DtoHolder source = new DtoHolder(); + source.setEntities(dtos); + + Type typeOf_DtoHolder = TypeFactory.valueOf(DtoHolder.class); + UtilityResolver.getDefaultPropertyResolverStrategy().getProperties(typeOf_DtoHolder); + + final EntityHolder entities = mapper.map(source, EntityHolder.class); + + Assert.assertNotNull(entities); + Assert.assertEquals(3, entities.getEntities().size()); + + final EntityHolder originalEntities = entities; + source.getEntities().remove(dto2); + dto2.setName("B-Changed"); + source.getEntities().add(dto2); + + mapper.map(source, entities); + + Assert.assertEquals(entities.getEntities().size(), originalEntities.getEntities().size()); + + Iterator entitiesIter = entities.getEntities().iterator(); + Iterator originalIter = originalEntities.getEntities().iterator(); + while (entitiesIter.hasNext()) { + Entity e = entitiesIter.next(); + Entity o = originalIter.next(); + Assert.assertSame(e, o); + } + } + + private static MapperFacade createMapperFacade() { + DefaultMapperFactory.Builder builder = new DefaultMapperFactory.Builder(); + MapperFactory factory = builder.build(); + + factory.registerMapper(new MergingMapper()); + factory.registerConcreteType(new TypeBuilder>() {}.build(), new TypeBuilder>() {}.build()); + return factory.getMapperFacade(); + } + + @Test + public void testMergingWithCustomMapperForChildrenSetToSet() { + MapperFacade mapper = createMapperFacade(); + + Set dtos = new HashSet<>(); + + ChildDto dto = new ChildDto(); + dto.setId(1L); + dto.setName("A"); + dtos.add(dto); + + ChildDto dto2 = new ChildDto(); + dto2.setId(2L); + dto2.setName("B"); + dtos.add(dto2); + + dto = new ChildDto(); + dto.setId(3L); + dto.setName("C"); + dtos.add(dto); + + AnotherDtoHolder dtoHolder = new AnotherDtoHolder(); + dtoHolder.setEntities(dtos); + + final AnotherEntityHolder entityHolder = mapper.map(dtoHolder, AnotherEntityHolder.class); + ChildEntity next = entityHolder.getEntities().iterator().next(); + Assert.assertEquals(next.getClass(), ChildEntity.class); + + Assert.assertNotNull(entityHolder); + Assert.assertEquals(3, entityHolder.getEntities().size()); + + final AnotherEntityHolder originalEntity = entityHolder; + Collection originalEntities = originalEntity.getEntities(); + dtoHolder.getEntities().remove(dto2); + dto2.setName("B-Changed"); + dtoHolder.getEntities().add(dto2); + + mapper.map(dtoHolder, entityHolder); + + Assert.assertSame(originalEntities, entityHolder.getEntities()); + Assert.assertEquals(entityHolder.getEntities().size(), originalEntity.getEntities().size()); + + Iterator entitiesIter = entityHolder.getEntities().iterator(); + Iterator originalIter = originalEntity.getEntities().iterator(); + while (entitiesIter.hasNext()) { + Entity e = entitiesIter.next(); + Entity o = originalIter.next(); + Assert.assertSame(e, o); + } + } + + public static class MergingMapper extends CustomMapper, Collection> { + + public void mapAtoB(Collection a, Collection b, MappingContext context) { + merge(a, b, context); + } + + private Collection merge(Collection srcDtos, Collection dstEntities, MappingContext context) { + + Set ids = new HashSet<>(srcDtos.size()); + + Type sourceType = context.getResolvedSourceType().getNestedType(0); + Type destinationType = context.getResolvedDestinationType().getNestedType(0); + + for (Dto memberDto : srcDtos) { + Entity memberEntity = findEntity(dstEntities, memberDto.getId()); + if (memberEntity == null) { + dstEntities.add((Entity) mapperFacade.map(memberDto, sourceType, destinationType, context)); + } else { + mapperFacade.map(memberDto, memberEntity); + } + ids.add(memberDto.getId()); + } + + dstEntities.removeIf(dstEntity -> !dstEntity.isNew() && !ids.contains(dstEntity.getId())); + + return dstEntities; + + } + + private Entity findEntity(Collection dstEntities, Long id) { + for (Entity dstEntity : dstEntities) { + if (id.equals(dstEntity.getId())) { + return dstEntity; + } + } + return null; + } + + } + + public static class EntityHolder { + + private Collection entityList; + + public Collection getEntities() { + return entityList; + } + + public void setEntities(Collection entityList) { + this.entityList = entityList; + } + + } + + public static class DtoHolder { + + private Collection dtoList; + + public Collection getEntities() { + return dtoList; + } + + public void setEntities(Collection dtoList) { + this.dtoList = dtoList; + } + + } + + public static class AnotherEntityHolder { + private Set entityList; + + public Set getEntities() { + return entityList; + } + + public void setEntities(Set entityList) { + this.entityList = entityList; + } + + } + + public static class AnotherDtoHolder { + private Set dtoList; + + public Set getEntities() { + return dtoList; + } + + public void setEntities(Set dtoList) { + this.dtoList = dtoList; + } + + } + + public static class Entity { + + private Long id; + private String name; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public boolean isNew() { + return id == null; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof Entity)) { + return false; + } + + Entity entity = (Entity) o; + + if (!Objects.equals(id, entity.id)) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + return id != null ? id.hashCode() : 0; + } + } + + public static class ChildEntity extends Entity { + + } + + public static class Dto { + private Long id; + private String name; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof Dto)) { + return false; + } + + Dto dto = (Dto) o; + + if (!Objects.equals(id, dto.id)) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + return id != null ? id.hashCode() : 0; + } + } + + public static class ChildDto extends Dto { + + } + + public static class DesiredMergingMapper extends CustomMapper + + { + + public void mapAtoB(Collection srcDtos, Collection dstEntities, Class srcDtoClass, + Class dstEntityClass, MappingContext context) { + merge(srcDtos, dstEntities, srcDtoClass, dstEntityClass); + } + + private Collection merge(Collection srcDtos, Collection dstEntities, Class srcDtoClass, + Class dstEntityClass) { + + Set ids = new HashSet<>(srcDtos.size()); + for (Object srcDto : srcDtos) { + Dto memberDto = (Dto) srcDto; + + Entity memberEntity = findEntity(dstEntities, memberDto.getId()); + if (memberEntity == null) { + Entity newEntity = mapperFacade.map(memberDto, dstEntityClass); + dstEntities.add(newEntity); + } else { + mapperFacade.map(memberEntity, memberDto); + } + ids.add(memberDto.getId()); + } + + dstEntities.removeIf(dstEntity -> !dstEntity.isNew() && !ids.contains(dstEntity.getId())); + + return dstEntities; + + } + + private Entity findEntity(Collection dstEntities, Long id) { + for (Object entity : dstEntities) { + Entity dstEntity = (Entity) entity; + if (id.equals(dstEntity.getId())) { + return dstEntity; + } + } + return null; + } + + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue102TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue102TestCase.java new file mode 100644 index 00000000..08134cc3 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue102TestCase.java @@ -0,0 +1,158 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +import org.junit.Assert; +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; + +import org.junit.Test; + +/** + * I'm not able to set map type using orika. + *

+ * + * @see https://code.google.com/archive/p/orika/ + * + */ +public class Issue102TestCase { + + @Test + public void testWithoutGenerics() { + Product p = new Product(); + p.setAvailability(true); + p.setProductDescription("hi product description"); + p.setProductName("product class 1"); + Map map = new HashMap(); + map.put(1, "kiran"); + map.put(2, "pandu"); + map.put(3, "varsha"); + p.setMap(map); + + + MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build(); + mapperFactory.classMap(Product.class, ProductDto.class) + .field("productDescription", "description") + .field("map", "map") + .byDefault() + .register(); + MapperFacade mapper = mapperFactory.getMapperFacade(); + ProductDto pd = mapper.map(p, ProductDto.class); + + Assert.assertNotNull(pd.getMap()); + Assert.assertEquals(p.getMap().size(), pd.getMap().size()); + for (Object e: p.getMap().entrySet()) { + Entry entry = (Entry)e; + Assert.assertEquals(entry.getValue(), pd.getMap().get(entry.getKey())); + } + + } + + public static class Product { + private String productName; + + private String productDescription; + + private Map map; + + + private Boolean availability; + + public Map getMap() { + return map; + } + + public void setMap(Map map) { + this.map = map; + } + + public String getProductDescription() { + return productDescription; + } + + public void setProductDescription(String productDescription) { + this.productDescription = productDescription; + } + + public String getProductName() { + return productName; + } + + public void setProductName(String productName) { + this.productName = productName; + } + + public Boolean getAvailability() { + return availability; + } + + public void setAvailability(Boolean availability) { + this.availability = availability; + } + + } + + public static class ProductDto { + + private String productName; + + private String description; + Map map; + + public Map getMap() { + return map; + } + + public void setMap(Map map) { + this.map = map; + } + + private Boolean availability; + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Boolean getAvailability() { + return availability; + } + + public void setAvailability(Boolean availability) { + this.availability = availability; + } + + public String getProductName() { + return productName; + } + + public void setProductName(String productName) { + this.productName = productName; + } + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue105TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue105TestCase.java new file mode 100644 index 00000000..6d3e0265 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue105TestCase.java @@ -0,0 +1,101 @@ +package ma.glasnost.orika.test.community; + +import org.junit.Assert; +import org.junit.Test; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; + +/** + * Circular reference mapping with classes that extend an abstract class fail. + *

+ * + * @see https://code.google.com/archive/p/orika/ + * @see https://github.com/orika-mapper/orika/issues + */ +public class Issue105TestCase { + @Test + public void test() { + MapperFactory factory = new DefaultMapperFactory.Builder().build(); + + factory.classMap(Entity.class, BaseEntity.class).field("anotherEntity", "anotherBaseEntity").register(); + factory.classMap(AnotherEntity.class, AnotherBaseEntity.class).field("abstractEntity", "abstractBaseEntity").register(); + + MapperFacade mapperFacade = factory.getMapperFacade(); + + Entity entity = new Entity(); + + AnotherEntity anotherEntity = new AnotherEntity(); + anotherEntity.setAbstractEntity(entity); + + entity.setAnotherEntity(anotherEntity); + + + AnotherBaseEntity anotherBaseEntity = mapperFacade.map(anotherEntity, AnotherBaseEntity.class); + Assert.assertEquals(anotherEntity, ((Entity) anotherEntity.getAbstractEntity()).getAnotherEntity()); + Assert.assertEquals(anotherBaseEntity, ((BaseEntity) anotherBaseEntity.getAbstractBaseEntity()).getAnotherBaseEntity()); + + BaseEntity baseEntity1 = mapperFacade.map(entity, BaseEntity.class); + Assert.assertEquals(entity, entity.getAnotherEntity().getAbstractEntity()); + Assert.assertEquals(baseEntity1, baseEntity1.getAnotherBaseEntity().getAbstractBaseEntity()); + + BaseEntity baseEntity2 = (BaseEntity) mapperFacade.map(entity, AbstractBaseEntity.class); + Assert.assertEquals(entity, entity.getAnotherEntity().getAbstractEntity()); + Assert.assertEquals(baseEntity2, baseEntity2.getAnotherBaseEntity().getAbstractBaseEntity()); + } + + public static abstract class AbstractEntity { + AnotherEntity anotherEntity; + + public AnotherEntity getAnotherEntity() { + return this.anotherEntity; + } + + public void setAnotherEntity(AnotherEntity anotherEntity) { + this.anotherEntity = anotherEntity; + } + } + + public static class Entity extends AbstractEntity { + } + + public static class AnotherEntity { + AbstractEntity abstractEntity; + + public AbstractEntity getAbstractEntity() { + return this.abstractEntity; + } + + public void setAbstractEntity(AbstractEntity abstractEntity) { + this.abstractEntity = abstractEntity; + } + } + + public static class AbstractBaseEntity { + AnotherBaseEntity anotherBaseEntity; + + public AnotherBaseEntity getAnotherBaseEntity() { + return this.anotherBaseEntity; + } + + public void setAnotherBaseEntity(AnotherBaseEntity anotherBaseEntity) { + this.anotherBaseEntity = anotherBaseEntity; + } + } + + public static class BaseEntity extends AbstractBaseEntity { + } + + public static class AnotherBaseEntity { + AbstractBaseEntity abstractBaseEntity; + + public AbstractBaseEntity getAbstractBaseEntity() { + return this.abstractBaseEntity; + } + + public void setAbstractBaseEntity(AbstractBaseEntity abstractBaseEntity) { + this.abstractBaseEntity = abstractBaseEntity; + } + } +} \ No newline at end of file diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue109TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue109TestCase.java new file mode 100644 index 00000000..5297d959 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue109TestCase.java @@ -0,0 +1,82 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.test.MappingUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +/** + * Mapping for multi-occurrence elements doesn't trigger auto-generated mappings. + *

+ * + * @see https://code.google.com/archive/p/orika/ + */ +public class Issue109TestCase { + + public static class Element { + public int id; + public String name; + } + + public static class ElementDto { + public int id; + public String name; + } + + public static class Base { + public List elements; + public String name; + } + + public static class BaseDto { + public ElementDto element; + public String name; + } + + @Test + public void testOrderingOfClassMaps() { + + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.classMap(Base.class, BaseDto.class) + .fieldAToB("elements[0]", "element") + .byDefault().register(); + + + MapperFacade mapper = factory.getMapperFacade(); + + Base source = new Base(); + source.name = "source1"; + source.elements = new ArrayList<>(); + Element el = new Element(); + el.id = 1; + el.name = "element1"; + source.elements.add(el); + + BaseDto dest = mapper.map(source, BaseDto.class); + + Assert.assertEquals(source.elements.get(0).id, dest.element.id); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue112TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue112TestCase.java new file mode 100644 index 00000000..d1957445 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue112TestCase.java @@ -0,0 +1,147 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import ma.glasnost.orika.BoundMapperFacade; +import ma.glasnost.orika.impl.DefaultMapperFactory; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Class cast exception to MapEntry. + *

+ * + * @see https://code.google.com/archive/p/orika/ + * @author: ikrokhmalyov@griddynamics.com + * @since: 7/1/13 + */ +public class Issue112TestCase { + + @Test + public void test() { + + DefaultMapperFactory mapperFactory= new DefaultMapperFactory.Builder().build(); + mapperFactory.classMap(Class$1.class, Class$1Binding.class) + .field("list{name}","list{key}") + .field("list{strings}", "list{value}") + .byDefault() + .register(); + + BoundMapperFacade mapper = mapperFactory.getMapperFacade(Class$1.class, Class$1Binding.class); + Class$1 inst = new Class$1(Arrays.asList(new Class_2("abc", Arrays.asList("qwe","wer")), new Class_2("dfg", Arrays.asList("sdf","cvb")))); + + Class$1Binding result = mapper.map(inst); + + Assert.assertNotNull(result); + Assert.assertNotNull(result.getList()); + + } + + // Class$1, originally + public static class Class$1 { + + public Class$1() { + } + + public Class$1(List list) { + this.list = list; + } + + private List list; + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } + + @Override + public String toString() { + return "Class$1{" + + "list=" + list + + '}'; + } + } + + // Class$2, originally + public static class Class_2 { + + public Class_2() { + } + + public Class_2(String name, List strings) { + this.name = name; + this.strings = strings; + } + + private String name; + private List strings; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getStrings() { + return strings; + } + + public void setStrings(List strings) { + this.strings = strings; + } + + @Override + public String toString() { + return "Class$2{" + + "name='" + name + '\'' + + ", strings=" + strings + + '}'; + } + } + + // Class$1Binding, originally + public static class Class$1Binding { + private Map list; + + public Map getList() { + return list; + } + + public void setList(Map list) { + this.list = list; + } + + @Override + public String toString() { + return "Class$1Binding{" + + "list=" + list + + '}'; + } + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue113TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue113TestCase.java new file mode 100644 index 00000000..9a3b9969 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue113TestCase.java @@ -0,0 +1,95 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.metadata.TypeBuilder; +import ma.glasnost.orika.metadata.TypeFactory; +import ma.glasnost.orika.test.MappingUtil; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Cannot find a mapper when a child bean infers a generic type of its parent bean. + *

+ * + * @see https://code.google.com/archive/p/orika/ + * @author Arnaud Jasselette + * + */ +public final class Issue113TestCase { + + @Test + public void testIsAssignable() { + + Type> sourceType = new TypeBuilder>() { + }.build(); + + Type destType = TypeFactory.valueOf(ChildSourceBean.class); + + Assert.assertTrue(sourceType.isAssignableFrom(destType)); + + } + + @Test + public void testMapping() { + + // create a factory without the auto mapping + MapperFactory factory = MappingUtil.getMapperFactory(); + + // register a class map + // This generates a , TargetBean> mapper + factory.classMap(SourceBean.class, TargetBean.class).field("a", "b").register(); + MapperFacade mapper = factory.getMapperFacade(); + ChildSourceBean childSourceBean = new ChildSourceBean(); + // Orika doesn't use the , TargetBean> mapper because + // ChildSourceBean 'hides' its generic type in its signature. + TargetBean targetBean = mapper.map(childSourceBean, TargetBean.class); + Assert.assertNotNull(targetBean); + Assert.assertEquals(childSourceBean.a, targetBean.b); + } + + /** + * A source bean with a generic type + */ + public static class SourceBean { + public int a = 2; + } + + /** + * A child of the SourceBean that defines the generic type of its parent + */ + public static class ChildSourceBean extends SourceBean { + } + + /* + * This would work public static class ChildSourceBean extends + * SourceBean {} + */ + + /** + * A simple target bean + */ + public static class TargetBean { + public int b; + } +} \ No newline at end of file diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue114TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue114TestCase.java new file mode 100644 index 00000000..dd5af63a --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue114TestCase.java @@ -0,0 +1,91 @@ +package ma.glasnost.orika.test.community; + +import java.util.List; + +import ma.glasnost.orika.impl.DefaultMapperFactory; + +import org.junit.Test; + +/** + * NPE on mapNulls in 1.4.3. + *

+ * + * @see https://code.google.com/archive/p/orika/ + */ +public class Issue114TestCase { + + + public static class Class1 { + private List longs; + + public List getLongs() { + return longs; + } + + public void setLongs(List longs) { + this.longs = longs; + } + } + + public static class Class1Binding { + private Class2Binding class2; + + public Class2Binding getClass2() { + return class2; + } + + public void setClass2(Class2Binding class2) { + this.class2 = class2; + } + + @Override + public String toString() { + return "Class1Binding{" + + "class2=" + class2 + + '}'; + } + } + + public static class Class2Binding { + private List longs; + + public List getLongs() { + return longs; + } + + public void setLongs(List longs) { + this.longs = longs; + } + + @Override + public String toString() { + return "Class2Binding{" + + "longs=" + longs + + '}'; + } + } + + @Test + public void test() { + + DefaultMapperFactory mapperFactory = + new DefaultMapperFactory.Builder() + .build(); + + mapperFactory.classMap(Class1.class, Class1Binding.class) + .field("longs","class2.longs") + .byDefault() + .register(); + + Class1 class1 = new Class1(); + Class1Binding class1Binding = mapperFactory.getMapperFacade(Class1.class, Class1Binding.class).map(class1); + + System.out.println(class1Binding); + try { + Thread.sleep(10); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue119TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue119TestCase.java new file mode 100644 index 00000000..ce5be038 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue119TestCase.java @@ -0,0 +1,53 @@ +package ma.glasnost.orika.test.community; + +import java.util.List; + +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.test.MappingUtil; + +import org.junit.Test; + +/** + * NPE on mapping nested field with collection. + *

+ * + * @see https://code.google.com/archive/p/orika/ + */ +public class Issue119TestCase { + + public static class Source { + public String id; + public SourceRef ref; + } + + public static class SourceRef { + public List identities; + } + + public static class Dest { + public String id; + public List references; + } + + public static class DestReference { + public String identity; + } + + @Test + public void test() { + + MapperFactory factory = MappingUtil.getMapperFactory(true); + + factory.classMap(Source.class, Dest.class) + .mapNulls(false) + .fieldAToB("id", "id") + .fieldAToB("ref.identities{}", "references{identity}") + .register(); + + Source src = new Source(); + src.id = "myId"; + + Dest dest = factory.getMapperFacade().map(src, Dest.class); + + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue126TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue126TestCase.java new file mode 100644 index 00000000..49456643 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue126TestCase.java @@ -0,0 +1,83 @@ +package ma.glasnost.orika.test.community; + +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.test.MappingUtil; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Exclude() does not work if the field is not present in both classes. + *

+ * + * @see https://code.google.com/archive/p/orika/ + */ +public class Issue126TestCase { + + public static class A { + public String id; + public MyField unmappedField; + public String fieldA; + public String fieldB; + } + + public static class MyField { + public String value = "default"; + + public MyField(String blah) { + this.value = blah; + } + } + + + public static class B { + public String id; + public String fieldA; + public String fieldB; + } + + + @Test + public void testExclude() { + + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.classMap(A.class, B.class) + .field("id", "id") + .exclude("unmappedField") + .byDefault() + .register(); + + A source = new A(); + source.id = "a"; + source.fieldA = "a"; + source.fieldB = "b"; + source.unmappedField = new MyField("myField"); + + B dest = factory.getMapperFacade().map(source, B.class); + Assert.assertNotNull(dest); + + } + + @Test + public void testByDefault() { + + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.classMap(A.class, B.class) + //.field("id", "id") + .byDefault() + .register(); + + A source = new A(); + source.id = "a"; + source.fieldA = "a"; + source.fieldB = "b"; + source.unmappedField = new MyField("myField"); + + B dest = factory.getMapperFacade().map(source, B.class); + Assert.assertNotNull(dest); + + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue128TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue128TestCase.java new file mode 100644 index 00000000..2faf8c38 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue128TestCase.java @@ -0,0 +1,72 @@ +package ma.glasnost.orika.test.community; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.test.MappingUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Mapping to Map<String, List<String>> only maps keys. Map<String, ArrayList<String>> works.. + *

+ * + * @see https://code.google.com/archive/p/orika/ + */ +public class Issue128TestCase { + + public static class A { + public Map> x; + } + + public static class B1 { + public Map> x; + } + + public static class B2 { + public Map> x; + } + + private A createA() { + A a = new A(); + a.x = new HashMap<>(); + a.x.put("key1", new ArrayList<>()); + a.x.get("key1").add("value1a"); + a.x.get("key1").add("value1b"); + a.x.get("key1").add("value1c"); + a.x.put("key2", new ArrayList<>()); + a.x.get("key2").add("value2a"); + a.x.get("key2").add("value2b"); + a.x.get("key2").add("value2c"); + return a; + } + + @Test + public void testGenericList() { + + MapperFactory factory = MappingUtil.getMapperFactory(true); + MapperFacade mapper = factory.getMapperFacade(); + + A a = createA(); + + B1 b1 = mapper.map(a, B1.class); + Assert.assertEquals(a.x, b1.x); + } + + @Test + public void testConcreteList() { + + MapperFactory factory = MappingUtil.getMapperFactory(true); + MapperFacade mapper = factory.getMapperFacade(); + + A a = createA(); + + B2 b2 = mapper.map(a, B2.class); + Assert.assertEquals(a.x, b2.x); + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue129TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue129TestCase.java new file mode 100644 index 00000000..4afe7025 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue129TestCase.java @@ -0,0 +1,35 @@ +package ma.glasnost.orika.test.community; + +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.converter.BidirectionalConverter; +import ma.glasnost.orika.metadata.Type; +import org.junit.Test; + +/** + * problem generic types when subclassing. + *

+ * + * @see https://github.com/orika-mapper/orika/issues + */ +public class Issue129TestCase { + + @Test + public void testCustomMapperOneParameter() { + new StringConverter(); + } + +} +abstract class AbstractStringConverter extends BidirectionalConverter {} + +class StringConverter extends AbstractStringConverter { + + @Override + public String convertTo(String source, Type destinationType, MappingContext mappingContext) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @Override + public String convertFrom(String source, Type destinationType, MappingContext mappingContext) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } +} \ No newline at end of file diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue132TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue132TestCase.java new file mode 100644 index 00000000..0a693336 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue132TestCase.java @@ -0,0 +1,88 @@ +package ma.glasnost.orika.test.community; + +import static org.junit.Assert.assertEquals; +import ma.glasnost.orika.BoundMapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingException; +import ma.glasnost.orika.impl.DefaultMapperFactory; + +import org.junit.Test; + +/** + * Usage of .constructorA/B results in NullPointerException. + *

+ * + * @see https://code.google.com/archive/p/orika/ + */ +public class Issue132TestCase { + + @Test(expected=MappingException.class) + public void test() { + MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build(); + mapperFactory.classMap(Person1.class, Person2.class) + .constructorB("fn") + .field("firstname", "forename") + .register(); + + BoundMapperFacade mapperFacade = mapperFactory.getMapperFacade(Person1.class, Person2.class); + Person1 otto1 = new Person1("Otto"); + Person2 otto2 = mapperFacade.map(otto1); + + assertEquals(otto1.getFirstname(), otto2.getForename()); + } + + @Test + public void testMappedNamesWithSpecifiedConstructor() { + MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build(); + mapperFactory.classMap(Person1.class, Person2.class) + .constructorB("fn") + .fieldAToB("firstname", "fn") + .fieldBToA("forename","firstname") + .register(); + + BoundMapperFacade mapperFacade = mapperFactory.getMapperFacade(Person1.class, Person2.class); + Person1 otto1 = new Person1("Otto"); + Person2 otto2 = mapperFacade.map(otto1); + + assertEquals(otto1.getFirstname(), otto2.getForename()); + } + + @Test + public void testMappedNamesWithoutSpecifiedConstructor() { + MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build(); + mapperFactory.classMap(Person1.class, Person2.class) + .fieldAToB("firstname", "fn") + .fieldBToA("forename","firstname") + .register(); + + BoundMapperFacade mapperFacade = mapperFactory.getMapperFacade(Person1.class, Person2.class); + Person1 otto1 = new Person1("Otto"); + Person2 otto2 = mapperFacade.map(otto1); + + assertEquals(otto1.getFirstname(), otto2.getForename()); + } + + public static class Person1 { + private final String firstname; + + public Person1(String firstname) { + this.firstname = firstname; + } + + public String getFirstname() { + return firstname; + } + } + + public static class Person2 { + private final String forename; + + public Person2(String fn) { + this.forename = fn; + } + + public String getForename() { + return forename; + } + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue138TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue138TestCase.java new file mode 100644 index 00000000..71c38d67 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue138TestCase.java @@ -0,0 +1,187 @@ +package ma.glasnost.orika.test.community; + +import ma.glasnost.orika.BoundMapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.test.MappingUtil; +import org.junit.Test; + +import java.util.ArrayList; + +import static org.junit.Assert.assertEquals; + +/** + * Mapping of Lists are not functioning correctly with fieldAToB. + *

+ * + * @see https://code.google.com/archive/p/orika/ + */ +public class Issue138TestCase { + + @Test + public void test() { + MapperFactory mapperFactory = MappingUtil.getMapperFactory(true); + mapperFactory.classMap(Person1.class, Person2.class) + .field("firstname", "forename").fieldAToB("lastname", "backname").fieldAToB("phones{number}", "phoneNumbers{}") + .register(); + + BoundMapperFacade mapperFacade = mapperFactory.getMapperFacade(Person1.class, Person2.class); + + + // Test A to B + Person1 otto1 = new Person1(); + otto1.setFirstname("Otto"); + otto1.setLastname("McAllen"); + + ArrayList phones = new ArrayList<>(); + phones.add(new Phone((long) 15468)); + phones.add(new Phone((long) 99999)); + otto1.setPhones(phones); + + Person2 otto2 = mapperFacade.map(otto1); + assertEquals(otto1.getFirstname(), otto2.getForename()); + assertEquals(otto1.getLastname(), otto2.getBackname()); + assertEquals(otto1.getPhones().get(0).getNumber(), otto2.getPhoneNumbers().get(0)); + + + // Test B to A + Person2 otto3 = new Person2(); + otto3.setForename("FreshOtto"); + otto3.setBackname("McFresh"); + ArrayList phoneNumbers = new ArrayList<>(); + phoneNumbers.add((long)11111); + phoneNumbers.add((long)22222); + otto3.setPhoneNumbers(phoneNumbers); + + Person1 otto4 = mapperFacade.mapReverse(otto3); + + assertEquals(otto3.getForename(), otto4.getFirstname()); + assertEquals(null, otto4.getLastname()); + assertEquals(null, otto4.getPhones()); + } + + @Test + public void testBidirectional() { + MapperFactory mapperFactory = MappingUtil.getMapperFactory(true); + mapperFactory.classMap(Person1.class, Person2.class) + .field("firstname", "forename").field("lastname", "backname").field("phones{number}", "phoneNumbers{}") + .register(); + + BoundMapperFacade mapperFacade = mapperFactory.getMapperFacade(Person1.class, Person2.class); + + + // Test A to B + Person1 otto1 = new Person1(); + otto1.setFirstname("Otto"); + otto1.setLastname("McAllen"); + + ArrayList phones = new ArrayList<>(); + phones.add(new Phone((long) 15468)); + phones.add(new Phone((long) 99999)); + otto1.setPhones(phones); + + Person2 otto2 = mapperFacade.map(otto1); + assertEquals(otto1.getFirstname(), otto2.getForename()); + assertEquals(otto1.getLastname(), otto2.getBackname()); + assertEquals(otto1.getPhones().get(0).getNumber(), otto2.getPhoneNumbers().get(0)); + + + // Test B to A + Person2 otto3 = new Person2(); + otto3.setForename("FreshOtto"); + otto3.setBackname("McFresh"); + ArrayList phoneNumbers = new ArrayList<>(); + phoneNumbers.add((long)11111); + phoneNumbers.add((long)22222); + otto3.setPhoneNumbers(phoneNumbers); + + Person1 otto4 = mapperFacade.mapReverse(otto3); + + assertEquals(otto3.getForename(), otto4.getFirstname()); + assertEquals(otto3.getBackname(), otto4.getLastname()); + phoneNumbers = new ArrayList<>(); + for (Phone phone: otto4.getPhones()) { + phoneNumbers.add(phone.getNumber()); + } + assertEquals(otto3.getPhoneNumbers(), phoneNumbers); + } + + public static class Person1 { + private String firstname; + + private String lastname; + + private ArrayList phones; + + public String getFirstname() { + return firstname; + } + + public void setFirstname(String firstname){ + this.firstname = firstname; + } + + public String getLastname() { + return lastname; + } + + public void setLastname(String lastname) { + this.lastname = lastname; + } + + public void setPhones(ArrayList phones){ + this.phones = phones; + } + + public ArrayList getPhones() { + return this.phones; + } + } + + public static class Phone { + private Long number; + + public Phone(Long number){ + this.number = number; + } + + public void setNumber(Long number){ + this.number = number; + } + + public Long getNumber(){ + return number; + } + } + + public static class Person2 { + private String forename; + + private String backname; + + private ArrayList phoneNumbers; + + public String getForename() { + return forename; + } + + public void setForename(String forename){ + this.forename = forename; + } + + public String getBackname() { + return backname; + } + + public void setBackname(String backname) { + this.backname = backname; + } + + public ArrayList getPhoneNumbers() { + return phoneNumbers; + } + + public void setPhoneNumbers(ArrayList phoneNumbers){ + this.phoneNumbers = phoneNumbers; + } + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue140TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue140TestCase.java new file mode 100644 index 00000000..8e63ab38 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue140TestCase.java @@ -0,0 +1,81 @@ +package ma.glasnost.orika.test.community; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.metadata.TypeBuilder; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * mapAsMap breaks Object graphs. + *

+ * + * @see https://code.google.com/archive/p/orika/ + */ +public class Issue140TestCase { + public static class ParentA { + public ChildA child; + } + + public static class ParentB { + public ChildB child; + } + + public static class ChildA { + public ParentA parent; + } + + public static class ChildB { + public ParentB parent; + } + + @Test + public void test() { + MapperFactory OMF = new DefaultMapperFactory.Builder().build(); + OMF.classMap(ParentA.class, ParentB.class).byDefault().register(); + OMF.classMap(ChildA.class, ChildB.class).byDefault().register(); + + ParentA a = new ParentA(); + a.child = new ChildA(); + a.child.parent = a; + + Map m = new HashMap<>(); + m.put("p", a); + m.put("c", a.child); + + MapperFacade mapper = OMF.getMapperFacade(); + + ParentB b1 = mapper.map(a, ParentB.class); + + ma.glasnost.orika.metadata.Type> mapType = new TypeBuilder>() { + }.build(); + Map m2 = mapper.mapAsMap(m, mapType, mapType); + + ParentB b2 = (ParentB) m2.get("p"); + /* + * Issue here is that the object graph is not respected when the object is + * contained within a Map type...; + * the parent's child's parent is not identical, but when the types are mapped + * directly, it is identical. + */ + Assert.assertSame(b1, b1.child.parent); + Assert.assertSame(b2, b2.child.parent); + + List l = new ArrayList<>(); + l.add(a.child); + l.add(a); + + ma.glasnost.orika.metadata.Type listType = new TypeBuilder() { + }.build(); + List l2 = mapper.mapAsList(l, listType, listType); + b2 = (ParentB) l2.get(1); + Assert.assertSame(b2, b2.child.parent); + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue141TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue141TestCase.java new file mode 100644 index 00000000..7c415da6 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue141TestCase.java @@ -0,0 +1,158 @@ +package ma.glasnost.orika.test.community; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.metadata.CaseInsensitiveClassMapBuilder; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Compilation Error when referencing collection on class property. + *

+ * + * @see https://code.google.com/archive/p/orika/ + */ +public class Issue141TestCase { + + public static class Clazz { + private SubClass subClass; + + public SubClass getSubClass() { + return subClass; + } + + public void setSubClass(SubClass subClass) { + this.subClass = subClass; + } + } + + public static class SubClass { + private List strings; + + public List getStrings() { + return strings; + } + + public void setStrings(List strings) { + this.strings = strings; + } + } + + public static class Clazz2 { + private String string; + + public String getString() { + return string; + } + + public void setString(String string) { + this.string = string; + } + } + + public static class A { + private B b = new B(); + + public B getB() { + return b; + } + + public void setB(B b) { + this.b = b; + } + } + + public static class B { + private List c = new ArrayList<>(); + + public List getC() { + return c; + } + + public void setC(List c) { + this.c = c; + } + } + + public static class C { + private D d = new D(); + + public D getD() { + return d; + } + + public void setD(D d) { + this.d = d; + } + } + + public static class D { + private List data = new ArrayList<>(); + + public List getData() { + return data; + } + + public void setData(List data) { + this.data = data; + } + } + + public static class TheBean { + private String data; + + public String getData() { + return data; + } + + public void setData(String data) { + this.data = data; + } + } + + @Test + public void test() { + SubClass subClass = new SubClass(); + subClass.setStrings(new ArrayList<>(Arrays.asList("abc@mail.com"))); + + Clazz clazz = new Clazz(); + clazz.setSubClass(subClass); + + Clazz2 clazz2 = new Clazz2(); + + MapperFactory mapperFactory = new DefaultMapperFactory.Builder() + .classMapBuilderFactory(new CaseInsensitiveClassMapBuilder.Factory()) + .build(); + mapperFactory.classMap(Clazz.class, Clazz2.class) + .field("subClass.strings[0]", "string").register(); + + + + MapperFacade mapper = mapperFactory.getMapperFacade(); + mapper.map(clazz, clazz2); + } + + @Test + public void test2() throws Throwable { + + MapperFactory mapperFactory = new DefaultMapperFactory.Builder() + .useAutoMapping(false) + .mapNulls(false) + .build(); + + mapperFactory.classMap(TheBean.class, A.class) + .field("data", "b.c[0].d.data[0]").register(); + + MapperFacade mapper = mapperFactory.getMapperFacade(); + + TheBean theBean = new TheBean(); + theBean.setData("TEST"); + + A a = mapper.map(theBean, A.class); + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue148TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue148TestCase.java new file mode 100644 index 00000000..e84c195f --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue148TestCase.java @@ -0,0 +1,187 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import ma.glasnost.orika.CustomConverter; +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.metadata.Type; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +/** + * Orika fails to map converter result to string (double cast). + *

+ * I am trying to map an object to a string via a custom converter, with the converter returning null (e.g. because the source object is + * null) + * + * @see https://code.google.com/archive/p/orika/ + * @author dbb + * @since 07.03.14 + */ +public class Issue148TestCase { + + // one class has a simple string property + public static class A { + private String code; + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + } + + // the other class has the same string property, wrapped in an object + public static class B { + private WrapperObject code; + + public WrapperObject getCode() { + return code; + } + + public void setCode(WrapperObject code) { + this.code = code; + } + } + + private static MapperFacade mapper; + + @BeforeClass + public static void init() { + + DefaultMapperFactory.Builder factoryBuilder = new DefaultMapperFactory.Builder(); + MapperFactory factory = factoryBuilder.build(); + + factory.getConverterFactory().registerConverter(new Converter.Object2String()); + factory.getConverterFactory().registerConverter(new Converter.String2Object()); + + mapper = factory.getMapperFacade(); + } + + @Test + // map string to wrapper object. expectation: wrapper object should contain + // string + public void testA2BwithValue() { + A a = new A(); + a.code = "x"; + + B b = mapper.map(a, B.class); + + Assert.assertNotNull(b); + Assert.assertEquals(a.code, b.code.getId()); + } + + @Test + // map wrapper object to string. expectation: string should contain content + // of wrapper object + public void testB2AwithValue() { + B b = new B(); + b.code = new WrapperObject(); + b.code.setId("x"); + + A a = mapper.map(b, A.class); + + Assert.assertNotNull(a); + Assert.assertEquals(b.code.getId(), a.code); + } + + @Test + // map null string to wrapper object. expectation: wrapper object should be + // null + public void testA2BwithNullValue() { + B b = new B(); + b.code = new WrapperObject(); + b.code.setId(null); + + A a = mapper.map(b, A.class); + + Assert.assertNotNull(a); + Assert.assertNull(a.code); + } + + @Test + // map null wrapper object to string. expectation: string should be null + public void testB2AwithNullWrapper() { + B b = new B(); + b.code = null; + + A a = mapper.map(b, A.class); + + Assert.assertNotNull(a); + Assert.assertNull(a.code); + } + + @Test + // map wrapper object with null content to string. expectation: string + // should be null + public void testB2AwithNullValue() { + B b = new B(); + b.code = new WrapperObject(); + b.code.setId(null); + + A a = mapper.map(b, A.class); + + Assert.assertNotNull(a); + Assert.assertNull(a.code); + } + + public static class Converter { + + public static class String2Object extends CustomConverter { + public WrapperObject convert(String source, Type destinationType, MappingContext context) { + if (source == null) { + return null; + } else { + WrapperObject result = new WrapperObject(); + result.setId(source); + return result; + } + } + } + + public static class Object2String extends CustomConverter { + public String convert(WrapperObject source, Type destinationType, MappingContext context) { + if (source == null) { + return null; + } else { + return source.getId(); + } + } + } + } + + public static class WrapperObject { + private String id; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue14TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue14TestCase.java new file mode 100644 index 00000000..2718d93e --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue14TestCase.java @@ -0,0 +1,112 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import java.util.Calendar; +import java.util.Date; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.converter.BidirectionalConverter; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.test.MappingUtil; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Calendar as destination throwing exception. + *

+ * + * @see https://code.google.com/archive/p/orika/ + */ +public class Issue14TestCase { + + public static class Product { + + private Date tempCal; + + public Date getTempCal() { + return tempCal; + } + + public void setTempCal(Date tempCal) { + this.tempCal = tempCal; + } + + } + + public static class ProductDTO { + + private Calendar tempCal; + + public Calendar getTempCal() { + return tempCal; + } + + public void setTempCal(Calendar tempCal) { + this.tempCal = tempCal; + } + + } + + @Test + public void testMapDateToCalendar() { + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(new BidirectionalConverter() { + + @Override + public Calendar convertTo(Date source, Type destinationType, MappingContext context) { + Calendar cal = Calendar.getInstance(); + cal.setTime(source); + return cal; + } + + @Override + public Date convertFrom(Calendar source, Type destinationType, MappingContext context) { + return source.getTime(); + } + + }); + MapperFacade mapper = factory.getMapperFacade(); + + Product p = new Product(); + p.setTempCal(new Date()); + + ProductDTO result = mapper.map(p, ProductDTO.class); + + Assert.assertEquals(p.getTempCal(), result.getTempCal().getTime()); + } + + @Test + public void testMapDateToCalendar_usingBuiltinConverters() { + MapperFactory factory = new DefaultMapperFactory.Builder().useBuiltinConverters(true).build(); + MapperFacade mapper = factory.getMapperFacade(); + + Product p = new Product(); + p.setTempCal(new Date()); + + ProductDTO result = mapper.map(p, ProductDTO.class); + + Assert.assertEquals(p.getTempCal(), result.getTempCal().getTime()); + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue160TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue160TestCase.java new file mode 100644 index 00000000..9e45afb1 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue160TestCase.java @@ -0,0 +1,165 @@ +package ma.glasnost.orika.test.community; + +import ma.glasnost.orika.BoundMapperFacade; +import ma.glasnost.orika.CustomMapper; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; + +/** + * MapperFacade.map does not map into destination instance when context has already mapped the source Object. + *

+ * + * @see https://github.com/orika-mapper/orika/issues + */ +public class Issue160TestCase { + + @Test + public void testIssue160() { + final MapperFactory factory = new DefaultMapperFactory.Builder().build(); + factory.classMap(A.class, X.class) + .customize(new CustomMapper() { + + @Override + public void mapAtoB(A a, X b, MappingContext context) { + factory.getMapperFacade().map(a, b.getY1(), context); + factory.getMapperFacade().map(a, b.getY2(), context); + } + }) + .byDefault() + .register(); + + A a = new A(); + a.setValue1("testValue1"); + a.setValue2("testValue2"); + + BoundMapperFacade mapperFacade = factory.getMapperFacade(A.class, X.class); + X mappedX = mapperFacade.map(a); + + assertThat(mappedX.getValue1(), is("testValue1")); + assertThat(mappedX.getY1().getValue2(), is("testValue2")); + assertThat(mappedX.getY2().getValue2(), is("testValue2")); + } + + @Test + public void testIssue160WithCycle() { + + final MapperFactory factory = new DefaultMapperFactory.Builder().build(); + factory.classMap(A.class, ZCycle.class) + .customize(new CustomMapper() { + + @Override + public void mapAtoB(A a, ZCycle b, MappingContext context) { + factory.getMapperFacade().map(a, b.getZcycle(), context); + } + }) + .byDefault() + .register(); + + A a = new A(); + a.setValue1("testValue1"); + a.setValue2("testValue2"); + + BoundMapperFacade mapperFacade = factory.getMapperFacade(A.class, ZCycle.class); + ZCycle mappedZ = mapperFacade.map(a); + + assertThat(mappedZ.getValue1(), is("testValue1")); + assertThat(mappedZ.getValue2(), is("testValue2")); + assertThat(mappedZ.getZcycle().getValue1(), is("testValue1")); + assertThat(mappedZ.getZcycle().getValue2(), is("testValue2")); + assertThat(mappedZ.getZcycle().getZcycle().getValue1(), is("testValue1")); + assertThat(mappedZ.getZcycle().getZcycle().getValue2(), is("testValue2")); + } + public static class A { + private String value1; + private String value2; + + public String getValue1() { + return value1; + } + + public void setValue1(String value1) { + this.value1 = value1; + } + + public String getValue2() { + return value2; + } + + public void setValue2(String value2) { + this.value2 = value2; + } + + } + + public static class X { + private String value1; + private final Y y1 = new Y(); + private final Y y2 = new Y(); + + public String getValue1() { + return value1; + } + + public void setValue1(String value1) { + this.value1 = value1; + } + + public Y getY1() { + return y1; + } + + public Y getY2() { + return y2; + } + + } + + public static class Y { + private String value2; + + public String getValue2() { + return value2; + } + + public void setValue2(String value2) { + this.value2 = value2; + } + + } + + public static class ZCycle { + private String value1; + private String value2; + + private ZCycle zcycle; + + public String getValue1() { + return value1; + } + + public void setValue1(String value1) { + this.value1 = value1; + } + + public String getValue2() { + return value2; + } + + public void setValue2(String value2) { + this.value2 = value2; + } + + public ZCycle getZcycle() { + if (zcycle == null) { + zcycle = this; + } + return zcycle; + } + + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue161TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue161TestCase.java new file mode 100644 index 00000000..8065bde3 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue161TestCase.java @@ -0,0 +1,36 @@ +package ma.glasnost.orika.test.community; + +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; + +import org.junit.Test; + +/** + * Unable to map class with self-referencing generics and Comparable return type. + *

+ * + * @see https://code.google.com/archive/p/orika/ + */ +public class Issue161TestCase { + + public static class Optional { + } + + public static class Range> { + } + + public static class SelfReferencingGenericType> { + public Optional> getOptionalStringRange() { + return null; + } + } + + public static class Foo extends SelfReferencingGenericType { + } + + @Test + public void mapSelfReferencingGenericType() { + MapperFactory factory = new DefaultMapperFactory.Builder().build(); + factory.classMap(Foo.class, String.class).byDefault().register(); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue166TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue166TestCase.java new file mode 100644 index 00000000..466f671f --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue166TestCase.java @@ -0,0 +1,102 @@ +package ma.glasnost.orika.test.community; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.CoreMatchers.is; + +import java.io.Serializable; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; + +import org.junit.Assert; +import org.junit.Test; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.metadata.TypeFactory; + +/** + * StackOverflowError exception when mapping enum. + *

+ * + * @see https://github.com/orika-mapper/orika/issues + */ +public class Issue166TestCase { + + @Test + public void testIssue166() throws Exception { + + MapperFactory factory = new DefaultMapperFactory.Builder().build(); + MapperFacade beanMapper = factory.getMapperFacade(); + + SimpleBeanResource sbr = beanMapper.map(SimpleEnumBean.E1, SimpleBeanResource.class); + Assert.assertEquals(sbr.getName(), SimpleEnumBean.E1.getName()); + } + + @Test + public void testCaseSimplification_withTypeFactoryResolveValueOf() throws Exception { + + // readMethod = public final java.lang.Class java.lang.Enum.getDeclaringClass() + Method readMethod = SimpleEnumBean.class.getMethod("getDeclaringClass"); + // parameterized return type = Class + ParameterizedType parameterizedType = (ParameterizedType) readMethod.getGenericReturnType(); + + // start Test + Type type = TypeFactory.resolveValueOf(parameterizedType, TypeFactory.valueOf(SimpleEnumBean.class)); + + // validate + assertThat(type.toString(), is("Class")); + + } + + public static class SimpleBeanResource implements Serializable { + private static final long serialVersionUID = 1894987353201458022L; + + private String code; + private String name; + + public SimpleBeanResource(String code, String name) { + this.code = code; + this.name = name; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + public static enum SimpleEnumBean { + E1("code_e1", "name_e1"); + + SimpleEnumBean(String code, String name) { + this.code = code; + this.name = name; + } + + private final String code; + + private final String name; + + public String getCode() { + return code; + } + + public String getName() { + return name; + } + } + +} \ No newline at end of file diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue167TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue167TestCase.java new file mode 100644 index 00000000..b3780f2e --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue167TestCase.java @@ -0,0 +1,104 @@ +package ma.glasnost.orika.test.community; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.metadata.TypeFactory; +import ma.glasnost.orika.property.IntrospectorPropertyResolver; +import ma.glasnost.orika.property.PropertyResolver; +import org.junit.Test; + +import java.lang.reflect.Method; +import java.util.HashSet; +import java.util.Set; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.collection.IsCollectionWithSize.hasSize; + +/** + * DefaultMapperFactory.classMap got in infinity loop when using F-bounded polymorphism. + *

+ * + * @see https://github.com/orika-mapper/orika/issues + */ +public class Issue167TestCase { + + @Test + public void testIssue167() throws Exception { + + MapperFactory factory = new DefaultMapperFactory.Builder().build(); + + // this is the test where the code was broken + factory.classMap(ChildInterface.class, ChildInterface.class) + .byDefault() + .register(); + + // validate result by mapping a ChildInterfaceImpl instance: + MapperFacade beanMapper = factory.getMapperFacade(); + Foo foo = new Foo("test-Foo"); + ChildInterfaceImpl childInterface = new ChildInterfaceImpl(); + childInterface.getSet().add(foo); + + ChildInterfaceImpl newChild = beanMapper.map(childInterface, ChildInterfaceImpl.class); + + assertThat(newChild.getSet(), hasSize(1)); + assertThat(newChild.getSet().iterator().next(), is(not(foo))); // must be a new mapped instance... + assertThat(newChild.getSet().iterator().next().getName(), is("test-Foo")); // with the same value. + + } + + @Test + public void testCaseSimplified_withPropertyResolverResolvePropertyType() throws Exception { + + PropertyResolver propRes = new IntrospectorPropertyResolver(); + + // readMethod = Set ChildInterface.getSet() + Method readMethod = ChildInterface.class.getMethod("getSet"); + @SuppressWarnings("rawtypes") + Class rawType = Set.class; + Class owningType = ChildInterface.class; + Type referenceType = TypeFactory.valueOf(ChildInterface.class); + + // run test: + Type resolvedPropertyType = propRes.resolvePropertyType(readMethod, rawType, owningType, referenceType); + + // validate result + assertThat(resolvedPropertyType.toString(), is("Set")); + + } + + @SuppressWarnings("unused") + public interface BaseInterface { + // test generic interface. + } + + public interface ChildInterface extends BaseInterface { + Set getSet(); + } + + public static class ChildInterfaceImpl implements ChildInterface { + private final Set set = new HashSet<>(); + + public Set getSet() { + return set; + } + } + + public static class Foo { + private final String name; + + public Foo(String name) { + super(); + this.name = name; + } + + public String getName() { + return name; + } + + } + +} \ No newline at end of file diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue175Test.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue175Test.java new file mode 100644 index 00000000..1c6b719a --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue175Test.java @@ -0,0 +1,135 @@ +package ma.glasnost.orika.test.community; + +import static org.junit.Assert.assertEquals; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; + +import org.junit.Test; + +import ma.glasnost.orika.OrikaSystemProperties; +import ma.glasnost.orika.impl.DefaultMapperFactory; + +public class Issue175Test { + + @Test + public void maps_one_value_to_all_elements_in_collection_and_back() { + System.setProperty(OrikaSystemProperties.WRITE_SOURCE_FILES,"true"); + DefaultMapperFactory mapper = new DefaultMapperFactory.Builder().build(); + + mapper.classMap(Source.class, Destination.class) + .field("nested", "nested") + .field("value", "nested{value}") + .byDefault() + .register(); + + Source source = new Source(); + source.setValue("some data"); + source.setNested(Arrays.asList( + aNestedSource("one"), + aNestedSource("two"), + aNestedSource("three") + )); + + Destination destination = mapper.getMapperFacade().map(source, Destination.class); + + assertEquals("some data", destination.getNested().get(0).getValue()); + assertEquals("one", destination.getNested().get(0).getId()); + assertEquals("some data", destination.getNested().get(1).getValue()); + assertEquals("two", destination.getNested().get(1).getId()); + assertEquals("some data", destination.getNested().get(2).getValue()); + assertEquals("three", destination.getNested().get(2).getId()); + + Source newSource = mapper.getMapperFacade().map(destination, Source.class); + + assertEquals(source, newSource); + } + + private NestedSource aNestedSource(String id) { + NestedSource nested = new NestedSource(); + nested.setId(id); + return nested; + } + + public static class Source { + + private String value; + private List nested = new ArrayList<>(); + + public void setValue(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + public void setNested(List nested) { + this.nested = nested; + } + + public List getNested() { + return nested; + } + + @Override + public boolean equals(Object obj) { + return Objects.equals(value, ((Source) obj).value) && + Objects.equals(nested, ((Source) obj).nested); + } + } + + public static class Destination { + + private List nested; + + public List getNested() { + return nested; + } + + public void setNested(List nested) { + this.nested = nested; + } + } + + public static class NestedSource { + + private String id; + + public void setId(String id) { + this.id = id; + } + + public String getId() { + return id; + } + + @Override + public boolean equals(Object obj) { + return Objects.equals(id, ((NestedSource) obj).id); + } + } + + public static class NestedDestination { + private String id; + private String value; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue176TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue176TestCase.java new file mode 100644 index 00000000..18986690 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue176TestCase.java @@ -0,0 +1,178 @@ +package ma.glasnost.orika.test.community; + +import ma.glasnost.orika.CustomConverter; +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.metadata.TypeFactory; +import org.junit.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.is; + +/** + * Support for mapping one type to many. + *

+ * + * @see https://github.com/orika-mapper/orika/issues + */ +public class Issue176TestCase { + + @Test + public void testIssue176() throws Exception { + + final MapperFactory factory = new DefaultMapperFactory.Builder().build(); + + factory.registerObjectFactory((source, mappingContext) -> { + A a = (A) source; + final B b; + if (a.getType().equals("1")) { + b = new B1(); + } else if (a.getType().equals("2")) { + b = new B2(); + } else { + throw new IllegalArgumentException("type not supported: " + a.getType()); + } + return b; + }, TypeFactory.valueOf(B.class), TypeFactory.valueOf(A.class)); + + factory.classMap(A.class, B1.class) + .field("x", "x1") + .byDefault() + .register(); + + factory.classMap(A.class, B2.class) + .field("x", "x2") + .byDefault() + .register(); + + // run the Test + runTest(factory.getMapperFacade()); + + } + + @Test + public void testIssue176_Workaround() throws Exception { + + final MapperFactory factory = new DefaultMapperFactory.Builder().build(); + + factory.getConverterFactory().registerConverter(new CustomConverter() { + + public B convert(A a, Type destType, MappingContext mappingContext) { + B cachedObject = mappingContext.getMappedObject(a, destType); + if (cachedObject != null) { + return cachedObject; + } + final B b; + if (a.getType().equals("1")) { + b = new B1(); + } else if (a.getType().equals("2")) { + b = new B2(); + } else { + throw new IllegalArgumentException("type not supported: " + a.getType()); + } + + mappingContext.cacheMappedObject(a, (Type) destType, b); + + mappingContext.beginMapping(sourceType, a, destType, b); + try { + factory.getMapperFacade().map(a, b, mappingContext); + } finally { + mappingContext.endMapping(); + } + + return b; + } + + }); + factory.classMap(A.class, B1.class) + .field("x", "x1") + .byDefault() + .register(); + + factory.classMap(A.class, B2.class) + .field("x", "x2") + .byDefault() + .register(); + + // run the Test + runTest(factory.getMapperFacade()); + + } + + private void runTest(final MapperFacade mapper) { + + A a1 = new A(); + a1.setType("1"); + a1.setX(11); + A a2 = new A(); + a2.setType("2"); + a2.setX(22); + + // run test + B b1 = mapper.map(a1, B.class); + B b2 = mapper.map(a2, B.class); + + // validate result + assertThat(b1, is(instanceOf(B1.class))); + assertThat(((B1) b1).getX1(), is(11)); + assertThat(b2, is(instanceOf(B2.class))); + assertThat(((B2) b2).getX2(), is(22)); + } + + public static class A { + private String type; + private int x; + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public int getX() { + return x; + } + + public void setX(int x) { + this.x = x; + } + + } + + public interface B { + // marker interface + } + + public static class B1 implements B { + private int x1; + + public int getX1() { + return x1; + } + + public void setX1(int x1) { + this.x1 = x1; + } + + } + + public static class B2 implements B { + private int x2; + + public int getX2() { + return x2; + } + + public void setX2(int x2) { + this.x2 = x2; + } + + } + +} \ No newline at end of file diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue176WithInterfacesTestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue176WithInterfacesTestCase.java new file mode 100644 index 00000000..e574a11b --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue176WithInterfacesTestCase.java @@ -0,0 +1,227 @@ +package ma.glasnost.orika.test.community; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.metadata.TypeFactory; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.is; + +/** + * Support for mapping one type to many. + *

+ * + * @see https://github.com/orika-mapper/orika/issues + */ +public class Issue176WithInterfacesTestCase { + + @Test + public void testIssue176_withInterfaces() throws Exception { + + final MapperFactory factory = new DefaultMapperFactory.Builder().build(); + + factory.registerObjectFactory((source, mappingContext) -> { + A a = (A) source; + final B b; + if (a.type.equals("1")) { + b = new B1(); + } else if (a.type.equals("2")) { + b = new B2(); + } else { + throw new IllegalArgumentException("type not supported: " + a.type); + } + return b; + }, TypeFactory.valueOf(B.class), TypeFactory.valueOf(A.class)); + + factory.classMap(A.class, B1.class) + .field("x", "x1") + .byDefault() + .register(); + + factory.classMap(A.class, B2.class) + .field("x", "x2") + .byDefault() + .register(); + + // run the Test + MapperFacade mapper = factory.getMapperFacade(); + A a1 = new A(); + a1.type = "1"; + a1.x = 11; + A a2 = new A(); + a2.type = "2"; + a2.x = 22; + + // run test + B b1 = mapper.map(a1, B.class); + B b2 = mapper.map(a2, B.class); + + // validate result + assertThat(b1, is(instanceOf(B1.class))); + assertThat(((B1) b1).x1, is(11)); + assertThat(b2, is(instanceOf(B2.class))); + assertThat(((B2) b2).x2, is(22)); + + } + + @Test + public void testIssue176_compinationOfInterfaceHirarchyAndObjectFactory() throws Exception { + + final MapperFactory factory = new DefaultMapperFactory.Builder().build(); + + factory.registerObjectFactory((source, mappingContext) -> { + A a = (A) source; + final B b; + if (a.type.equals("1")) { + b = new B1(); + } else if (a.type.equals("2")) { + b = new B2(); + } else { + throw new IllegalArgumentException("type not supported: " + a.type); + } + return b; + }, TypeFactory.valueOf(B.class), TypeFactory.valueOf(A.class)); + + factory.classMap(A.class, B1.class) + .field("x", "x1") + .byDefault() + .register(); + + factory.classMap(A.class, B2.class) + .field("x", "x2") + .byDefault() + .register(); + + factory.classMap(AX.class, BX.class) + .field("y", "x3") + .byDefault() + .register(); + + factory.classMap(ASuper.class, BSuper.class) + .byDefault() + .register(); + + // run the Test + A a1 = new A(); + a1.type = "1"; + a1.x = 11; + A a2 = new A(); + a2.type = "2"; + a2.x = 22; + AX aX = new AX(); + aX.y = 33; + + ASuperContainer container = new ASuperContainer(); + container.elelemts.add(a1); + container.elelemts.add(a2); + container.elelemts.add(aX); + + // run test + MapperFacade mapper = factory.getMapperFacade(); + + BSuperContainer bContainer = mapper.map(container, BSuperContainer.class); + BSuper b1 = bContainer.elelemts.get(0); + BSuper b2 = bContainer.elelemts.get(1); + BSuper b3 = bContainer.elelemts.get(2); + + // validate result + assertThat(b1, is(instanceOf(B1.class))); + assertThat(((B1) b1).x1, is(11)); + assertThat(b2, is(instanceOf(B2.class))); + assertThat(((B2) b2).x2, is(22)); + assertThat(b3, is(instanceOf(BX.class))); + assertThat(((BX) b3).x3, is(33)); + + } + + @Test + public void testIssue176_hirarchyOnly() throws Exception { + + final MapperFactory factory = new DefaultMapperFactory.Builder().build(); + + factory.classMap(A.class, B1.class) + .field("x", "x1") + .byDefault() + .register(); + + factory.classMap(AX.class, BX.class) + .field("y", "x3") + .byDefault() + .register(); + + factory.classMap(ASuper.class, BSuper.class) + .byDefault() + .register(); + + // run the Test + A a1 = new A(); + a1.x = 11; + AX aX = new AX(); + aX.y = 33; + + // run test + MapperFacade mapper = factory.getMapperFacade(); + + BSuper b1 = mapper.map(a1, BSuper.class); + BSuper b3 = mapper.map(aX, BSuper.class); + + // validate result + assertThat(b1, is(instanceOf(B1.class))); + assertThat(((B1) b1).x1, is(11)); + assertThat(b3, is(instanceOf(BX.class))); + assertThat(((BX) b3).x3, is(33)); + + } + + // A-Hierarchy: + public static class ASuperContainer { + public List elelemts = new ArrayList<>(); + } + + public interface ASuper { + // marker interface + } + + public static class A implements ASuper { + public String type; + public int x; + + } + + public static class AX implements ASuper { + public int y; + } + + // B-Hierarchy: + public static class BSuperContainer { + public List elelemts = new ArrayList<>(); + } + + public interface BSuper { + // marker interface + } + + public interface B extends BSuper { + // marker interface + } + + public static class B1 implements B { + public int x1; + } + + public static class B2 implements B { + public int x2; + } + + public static class BX implements BSuper { + public int x3; + + } + +} \ No newline at end of file diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue176WithSuperClassesTestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue176WithSuperClassesTestCase.java new file mode 100644 index 00000000..2c896e81 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue176WithSuperClassesTestCase.java @@ -0,0 +1,296 @@ +package ma.glasnost.orika.test.community; + +import ma.glasnost.orika.CustomMapper; +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.ObjectFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.metadata.TypeFactory; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.is; + +/** + * Support for mapping one type to many. + *

+ * + * @see https://github.com/orika-mapper/orika/issues + */ +public class Issue176WithSuperClassesTestCase { + + private static final ObjectFactory OBJECT_FACTORY = (source, mappingContext) -> { + A a = (A) source; + final B b; + if ("1".equals(a.type)) { + b = new B1(); + } else if ("2".equals(a.type)) { + b = new B2(); + } else if (a.type == null || a.type.isEmpty()) { + b = new B(); + } else { + throw new IllegalArgumentException("type not supported: " + a.type); + } + return b; + }; + + @Test + public void testIssue176_withSuperClasses() throws Exception { + + final MapperFactory factory = new DefaultMapperFactory.Builder().build(); + + factory.registerObjectFactory(OBJECT_FACTORY, TypeFactory.valueOf(B.class), TypeFactory.valueOf(A.class)); + + factory.classMap(A.class, B1.class) + .field("x", "x1") + .customize(new CustomMapper() { + // custom reverse mapping + @Override + public void mapBtoA(B1 b, A a, MappingContext context) { + a.type = "1"; + } + }) + .byDefault() + .register(); + + factory.classMap(A.class, B2.class) + .field("x", "x2") + .customize(new CustomMapper() { + // custom reverse mapping + @Override + public void mapBtoA(B2 b, A a, MappingContext context) { + a.type = "2"; + } + }) + .byDefault() + .register(); + + // testing auto generation of Mapper (A.class, B.class) + + // run the Test + MapperFacade mapper = factory.getMapperFacade(); + A a0 = new A(); + A a1 = new A(); + a1.type = "1"; + a1.x = 11; + A a2 = new A(); + a2.type = "2"; + a2.x = 22; + + // run test + B b0 = mapper.map(a0, B.class); + B b1 = mapper.map(a1, B.class); + B b2 = mapper.map(a2, B.class); + + // validate result + assertThat(b0, is(instanceOf(B.class))); + assertThat(b1, is(instanceOf(B1.class))); + assertThat(((B1) b1).x1, is(11)); + assertThat(b2, is(instanceOf(B2.class))); + assertThat(((B2) b2).x2, is(22)); + + // run test reverse mapping + A aMapped0 = mapper.map(b0, A.class); + A aMapped1 = mapper.map(b1, A.class); + A aMapped2 = mapper.map(b2, A.class); + + // validate result + assertThat(aMapped0, is(instanceOf(A.class))); + assertThat(aMapped1, is(instanceOf(A.class))); + assertThat(aMapped1.x, is(11)); + assertThat(aMapped1.type, is("1")); + assertThat(aMapped2, is(instanceOf(A.class))); + assertThat(aMapped2.x, is(22)); + assertThat(aMapped2.type, is("2")); + } + + @Test + public void testIssue176_compinationOfSuperClassHirarchyAndObjectFactory() throws Exception { + + final MapperFactory factory = new DefaultMapperFactory.Builder().build(); + + factory.registerObjectFactory(OBJECT_FACTORY, TypeFactory.valueOf(B.class), TypeFactory.valueOf(A.class)); + + factory.classMap(A.class, B1.class) + .field("x", "x1") + .customize(new CustomMapper() { + // custom reverse mapping + @Override + public void mapBtoA(B1 b, A a, MappingContext context) { + a.type = "1"; + } + }) + .byDefault() + .register(); + + factory.classMap(A.class, B2.class) + .field("x", "x2") + .customize(new CustomMapper() { + // custom reverse mapping + @Override + public void mapBtoA(B2 b, A a, MappingContext context) { + a.type = "2"; + } + }) + .byDefault() + .register(); + + factory.classMap(AX.class, BX.class) + .field("y", "x3") + .byDefault() + .register(); + + factory.classMap(A.class, B.class) + .byDefault() + .register(); + + factory.classMap(ASuper.class, BSuper.class) + .byDefault() + .register(); + + // run the Test + A a0 = new A(); + a0.type = ""; + A a1 = new A(); + a1.type = "1"; + a1.x = 11; + A a2 = new A(); + a2.type = "2"; + a2.x = 22; + AX aX = new AX(); + aX.y = 33; + + ASuperContainer container = new ASuperContainer(); + container.elelemts.add(a0); + container.elelemts.add(a1); + container.elelemts.add(a2); + container.elelemts.add(aX); + + // run test + MapperFacade mapper = factory.getMapperFacade(); + + BSuperContainer bContainer = mapper.map(container, BSuperContainer.class); + BSuper b0 = bContainer.elelemts.get(0); + BSuper b1 = bContainer.elelemts.get(1); + BSuper b2 = bContainer.elelemts.get(2); + BSuper b3 = bContainer.elelemts.get(3); + + // validate result + assertThat(b0, is(instanceOf(B.class))); + assertThat(b1, is(instanceOf(B1.class))); + assertThat(((B1) b1).x1, is(11)); + assertThat(b2, is(instanceOf(B2.class))); + assertThat(((B2) b2).x2, is(22)); + assertThat(b3, is(instanceOf(BX.class))); + assertThat(((BX) b3).x3, is(33)); + + // run test reverse mapping + + ASuperContainer mappedAContainer = mapper.map(bContainer, ASuperContainer.class); + ASuper aMapped0 = mappedAContainer.elelemts.get(0); + ASuper aMapped1 = mappedAContainer.elelemts.get(1); + ASuper aMapped2 = mappedAContainer.elelemts.get(2); + ASuper aMapped3 = mappedAContainer.elelemts.get(3); + + // validate result + assertThat(aMapped0, is(instanceOf(A.class))); + assertThat(aMapped1, is(instanceOf(A.class))); + assertThat(((A) aMapped1).x, is(11)); + assertThat(((A) aMapped1).type, is("1")); + assertThat(aMapped2, is(instanceOf(A.class))); + assertThat(((A) aMapped2).x, is(22)); + assertThat(((A) aMapped2).type, is("2")); + assertThat(aMapped3, is(instanceOf(AX.class))); + assertThat(((AX) aMapped3).y, is(33)); + } + + @Test + public void testIssue176_withSuperClassHirarchyOnly() throws Exception { + + final MapperFactory factory = new DefaultMapperFactory.Builder().build(); + + factory.classMap(A.class, B1.class) + .field("x", "x1") + .byDefault() + .register(); + + factory.classMap(AX.class, BX.class) + .field("y", "x3") + .byDefault() + .register(); + + factory.classMap(ASuper.class, BSuper.class) + .byDefault() + .register(); + + // run the Test + A a1 = new A(); + a1.x = 11; + AX aX = new AX(); + aX.y = 33; + + // run test + MapperFacade mapper = factory.getMapperFacade(); + + BSuper b1 = mapper.map(a1, BSuper.class); + BSuper b3 = mapper.map(aX, BSuper.class); + + // validate result + assertThat(b1, is(instanceOf(B1.class))); + assertThat(((B1) b1).x1, is(11)); + assertThat(b3, is(instanceOf(BX.class))); + assertThat(((BX) b3).x3, is(33)); + + } + + // A-Hierarchy: + public static class ASuperContainer { + public List elelemts = new ArrayList<>(); + } + + public static class ASuper { + // marker interface + } + + public static class A extends ASuper { + public String type; + public int x; + + } + + public static class AX extends ASuper { + public int y; + } + + // B-Hierarchy: + public static class BSuperContainer { + public List elelemts = new ArrayList<>(); + } + + public static class BSuper { + // marker interface + } + + public static class B extends BSuper { + // marker interface + } + + public static class B1 extends B { + public int x1; + } + + public static class B2 extends B { + public int x2; + } + + public static class BX extends BSuper { + public int x3; + + } + +} \ No newline at end of file diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue17TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue17TestCase.java new file mode 100644 index 00000000..ded79798 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue17TestCase.java @@ -0,0 +1,226 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.converter.BidirectionalConverter; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.metadata.ClassMapBuilder; +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.test.MappingUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; + +/** + * Mapping for Collection<String> --> String[] is not working. + *

+ * + * @see https://code.google.com/archive/p/orika/ + * + */ +public class Issue17TestCase { + + public static class A { + private Collection list; + + public void setList(final Collection list) { + this.list = list; + } + + public Collection getList() { + return list; + } + } + + public static class B { + private String[] list; + + public void setList(final String[] list) { + this.list = list; + } + + public String[] getList() { + return list; + } + } + + public static class C { + private int[] list; + + public int[] getList() { + return list; + } + + public void setList(int[] list) { + this.list = list; + } + } + + public static class D { + private List list; + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } + } + + @Test + public void testMappingToStringArray() { + final MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build(); + mapperFactory.classMap(A.class, B.class).byDefault().register(); + + final MapperFacade facade = mapperFactory.getMapperFacade(); + + final A a = new A(); + a.setList(Arrays.asList("One", "Two", "Three")); + final B converted = facade.map(a, B.class); + + Assert.assertNotNull(converted); + Assert.assertNotNull(converted.getList()); + List convertedList = Arrays.asList(converted.getList()); + assertThat(convertedList, contains("One", "Two", "Three")); + } + + @Test + public void testMappingToStringArray_empty() { + final MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build(); + final ClassMapBuilder builder = mapperFactory.classMap(A.class, B.class); + + mapperFactory.registerClassMap(builder.byDefault().toClassMap()); + + final MapperFacade facade = mapperFactory.getMapperFacade(); + + final A a = new A(); + final B converted = facade.map(a, B.class); + + Assert.assertNotNull(converted); + Assert.assertNull(converted.getList()); + } + + @Test + public void testMappingToStringToPrimitiveArray() { + + final MapperFactory mapperFactory = MappingUtil.getMapperFactory(); + + /* + * Note: this conversion works if we register a special converter; TODO: + * we should probably consider built-in converters for this sort of + * thing... + */ + mapperFactory.getConverterFactory().registerConverter(new BidirectionalConverter() { + + @Override + public String convertTo(Integer source, Type destinationType, MappingContext context) { + return "" + source; + } + + @Override + public Integer convertFrom(String source, Type destinationType, MappingContext context) { + return source != null ? Integer.parseInt(source) : 0; + } + }); + + final ClassMapBuilder builder = mapperFactory.classMap(A.class, C.class); + + mapperFactory.registerClassMap(builder.byDefault().toClassMap()); + + final MapperFacade facade = mapperFactory.getMapperFacade(); + + final A a = new A(); + a.setList(Arrays.asList("1", "2", "3")); + final C converted = facade.map(a, C.class); + + Assert.assertNotNull(converted); + Assert.assertNotNull(converted.getList()); + for (int item : converted.getList()) { + Assert.assertTrue(a.getList().contains("" + item)); + } + + } + + @Test + public void testMappingToStringToPrimitiveArray_empty() { + final MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build(); + final ClassMapBuilder builder = mapperFactory.classMap(A.class, C.class); + + mapperFactory.registerClassMap(builder.byDefault().toClassMap()); + + final MapperFacade facade = mapperFactory.getMapperFacade(); + + final A a = new A(); + final C converted = facade.map(a, C.class); + + Assert.assertNotNull(converted); + Assert.assertNull(converted.getList()); + } + + @Test + public void testMappingToPrimitiveArray() { + + final MapperFactory mapperFactory = MappingUtil.getMapperFactory(); + + /* + * Note: this conversion works if we register a special converter; TODO: + * we should probably consider built-in converters for this sort of + * thing... + */ + mapperFactory.getConverterFactory().registerConverter(new BidirectionalConverter() { + + @Override + public String convertTo(Integer source, Type destinationType, MappingContext context) { + return "" + source; + } + + @Override + public Integer convertFrom(String source, Type destinationType, MappingContext context) { + return source != null ? Integer.parseInt(source) : 0; + } + }); + + final ClassMapBuilder builder = mapperFactory.classMap(D.class, C.class); + + mapperFactory.registerClassMap(builder.byDefault().toClassMap()); + + final MapperFacade facade = mapperFactory.getMapperFacade(); + + final D a = new D(); + a.setList(Arrays.asList(1, 2, 3)); + final C converted = facade.map(a, C.class); + + Assert.assertNotNull(converted); + Assert.assertNotNull(converted.getList()); + for (int item : converted.getList()) { + Assert.assertTrue(a.getList().contains(item)); + } + + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue188TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue188TestCase.java new file mode 100644 index 00000000..702b42fc --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue188TestCase.java @@ -0,0 +1,67 @@ +package ma.glasnost.orika.test.community; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +import java.util.Date; +import java.util.Map; + +import org.junit.Test; + +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.metadata.TypeBuilder; +import ma.glasnost.orika.metadata.TypeFactory; + +public class Issue188TestCase { + + @Test + public void testCase() throws Exception { + Type type = TypeFactory.valueOf(Interface1.class); + assertThat(type.toString(), is("Interface1>")); + } + + @Test + public void testCase2() throws Exception { + Type type = new TypeBuilder>>() {}.build(); + assertThat(type.toString(), is("Map>")); + } + + @Test + public void testCase3() throws Exception { + Type type = TypeFactory.valueOf(Interface3.class); + assertThat(type.toString(), is("Interface3, Interface3>")); + } + + @Test + public void testCase5() throws Exception { + Type type = new TypeBuilder>>>>>() {}.build(); + assertThat(type.toString(), is("Interface5>>>>")); + } + + @Test + public void testCase7() throws Exception { + Type type = TypeFactory.valueOf(Interface7.class); + assertThat(type.toString(), is("Interface7>>>")); + } + + public interface Interface1> { + } + + public interface Interface2> { + } + + public interface Interface3, U extends Interface3> { + } + + public interface Interface4, U extends Interface4> { + } + + public interface Interface5 { + } + + public interface Interface6 { + } + + public interface Interface7>> { + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue18TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue18TestCase.java new file mode 100644 index 00000000..a7a7c20f --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue18TestCase.java @@ -0,0 +1,55 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.metadata.ClassMapBuilder; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.is; + +/** + * NoSuchElementException mapping empty lists. + *

+ * + * @see https://code.google.com/archive/p/orika/ + * + */ +public class Issue18TestCase { + + + @SuppressWarnings("deprecation") + @Test + public void testMappingEmptyArray() { + + MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build(); + mapperFactory.registerClassMap(ClassMapBuilder.map(Object.class,Object.class).byDefault().toClassMap()); + List listA = new ArrayList<>(); + List listB = mapperFactory.getMapperFacade().mapAsList(listA, Object.class); + + Assert.assertNotNull(listB); + Assert.assertThat(listB, is(empty())); + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue19TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue19TestCase.java new file mode 100644 index 00000000..dc4e9f5e --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue19TestCase.java @@ -0,0 +1,74 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import org.junit.Assert; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; + +import org.junit.Test; + +/** + * Copying objects works only first time. + *

+ * + * @see https://code.google.com/archive/p/orika/ + * + */ +public class Issue19TestCase { + + @Test + public void test() { + MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build(); + + A a = new A(); + a.setAttribute("attribute"); + + B b = new B(); + mapperFactory.getMapperFacade().map(a, b); + Assert.assertEquals(a.getAttribute(),b.getAttribute()); + + B b1 = new B(); + mapperFactory.getMapperFacade().map(a, b1); + Assert.assertEquals(a.getAttribute(),b1.getAttribute()); + } + + static public class A { + private String attribute; + + public String getAttribute() { + return attribute; + } + + public void setAttribute(String attribute) { + this.attribute = attribute; + } + } + + static public class B { + private String attribute; + + public String getAttribute() { + return attribute; + } + + public void setAttribute(String attribute) { + this.attribute = attribute; + } + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue20TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue20TestCase.java new file mode 100644 index 00000000..71771e94 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue20TestCase.java @@ -0,0 +1,102 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.io.Serializable; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.test.community.issue20.User; +import ma.glasnost.orika.test.community.issue20.UserDto; +import ma.glasnost.orika.test.community.issue20.UsrGroup; +import ma.glasnost.orika.unenhance.HibernateUnenhanceStrategy; + +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.transaction.annotation.Transactional; + +/** + * StackOverflowError mapping hibernate4 proxy. + *

+ * + * @see https://code.google.com/archive/p/orika/ + * + * @author Dmitriy Khomyakov + * @author matt.deboer@gmail.com + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = "classpath:Issue20TestCase-context.xml") +@Transactional +@DirtiesContext +public class Issue20TestCase { + + @Autowired + private SessionFactory sessionFactory; + + private Serializable user1Id; + private MapperFacade mapperFacade; + + protected Session getSession() { + return sessionFactory.getCurrentSession(); + } + + @Before + public void init() { + UsrGroup group = new UsrGroup("main"); + getSession().save(group); + + User user1 = new User("User1"); + user1Id = getSession().save(user1); + + User user2 = new User("user2"); + getSession().save(user2); + + group.addUser(user1); + group.addUser(user2); + + DefaultMapperFactory.Builder builder = new DefaultMapperFactory.Builder(); + builder.unenhanceStrategy(new HibernateUnenhanceStrategy()); + MapperFactory factory = builder.build(); + mapperFacade = factory.getMapperFacade(); + + getSession().flush(); + getSession().clear(); + } + + @Test + public void testMapUser() { + User user1 = (User) getSession().load(User.class, user1Id); + assertNotNull(user1); + for (int i = 0; i < 100; i++) { + UserDto userDto = mapperFacade.map(user1, UserDto.class); + assertEquals(userDto.getName(), user1.getName()); + } + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue21TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue21TestCase.java new file mode 100644 index 00000000..7cd2cdf2 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue21TestCase.java @@ -0,0 +1,234 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import static org.junit.Assert.*; + +import java.io.Serializable; + +import org.junit.Assert; +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.metadata.TypeFactory; +import ma.glasnost.orika.test.community.issue21.Authority; +import ma.glasnost.orika.test.community.issue21.AuthorityDto; +import ma.glasnost.orika.test.community.issue21.User; +import ma.glasnost.orika.test.community.issue21.UserDto; +import ma.glasnost.orika.test.community.issue21.UserGroup; +import ma.glasnost.orika.test.community.issue21.UserGroupDto; +import ma.glasnost.orika.unenhance.HibernateUnenhanceStrategy; + +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.transaction.annotation.Transactional; +/** + * NPE when collection is changed. + *

+ * + * @see https://code.google.com/archive/p/orika/ + * + * @author Dmitriy Khomyakov + * @author matt.deboer@gmail.com + * + * TODO: this particular test case is imported AS-IS, but should probably + * be trimmed down to the specific issue of concern here which is: + * + * Reuse of the same MappingStrategy over map(source) and map(source, dest) + * is not valid, since the mapping strategy implementations are distinguished + * by whether or not they instantiate or map in place (among other things). + * This means that the MappingStrategyKey needs to reflect whether or not + * the destination object is provided, since a different strategy must be + * used... + * + * + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = "classpath:Issue21TestCase-context.xml") +@Transactional +@DirtiesContext +public class Issue21TestCase { + + @Autowired + private SessionFactory sessionFactory; + private Serializable user1Id; + private Serializable user2Id; + private MapperFacade mapperFacade; + private Serializable groupId; + private Serializable adminAuthotityId; + + private final Logger log = LoggerFactory.getLogger(Issue21TestCase.class); + + protected Session getSession() { + return sessionFactory.getCurrentSession(); + } + + @Before + public void init() { + UserGroup group = new UserGroup("main"); + groupId = getSession().save(group); + + User user1 = new User("User1"); + user1Id = getSession().save(user1); + + User user2 = new User("user2"); + user2Id = getSession().save(user2); + + group.addUser(user1); + group.addUser(user2); + + Authority adminAuthority = new Authority("admin"); + adminAuthotityId = getSession().save(adminAuthority); + + DefaultMapperFactory.Builder builder = new DefaultMapperFactory.Builder(); + builder.unenhanceStrategy(new HibernateUnenhanceStrategy()); + MapperFactory factory = builder.build(); + mapperFacade = factory.getMapperFacade(); + + getSession().flush(); + getSession().clear(); + } + + @Test + public void testMapUser() { + User user1 = (User) getSession().load(User.class, user1Id); + User user2 = (User) getSession().load(User.class, user2Id); + assertNotNull(user1); + for (int i = 0; i < 100; i++) { + UserDto userDto1 = mapperFacade.map(user1, UserDto.class); + assertEquals(userDto1.getName(), user1.getName()); + + UserDto userDto2 = mapperFacade.map(user2, UserDto.class); + assertEquals(userDto2.getName(), user2.getName()); + + assertTrue(user1.getGroup().getUsers().contains(user2)); + } + } + + @Test + public void testChangeAuthoritiesOfUser() { + addAuthority(); + getSession().flush(); + getSession().clear(); + removeAuthority(); + } + + private void addAuthority() { + User user1 = (User) getSession().load(User.class, user1Id); + UserDto userDto1 = mapperFacade.map(user1, UserDto.class); + + log.debug("\n\n old userTO = " + userDto1); + + Authority authority = (Authority) getSession().load(Authority.class, + adminAuthotityId); + AuthorityDto authorityDto = mapperFacade.map(authority, + AuthorityDto.class); + assertFalse(userDto1.getAuthorities().contains(authorityDto)); + + userDto1.getAuthorities().add(authorityDto); + Assert.assertNotNull(user1); + mapperFacade.map(userDto1, user1, TypeFactory.valueOf(UserDto.class), + TypeFactory.valueOf(User.class)); + + assertTrue(user1.getAuthorities().contains(authority)); + } + + private void removeAuthority() { + User user1 = (User) getSession().load(User.class, user1Id); + UserDto userDto1 = mapperFacade.map(user1, UserDto.class); + + log.debug("\n\n old userTO = " + userDto1); + + Authority authority = (Authority) getSession().load(Authority.class, + adminAuthotityId); + AuthorityDto authorityDto = mapperFacade.map(authority, + AuthorityDto.class); + assertTrue(userDto1.getAuthorities().contains(authorityDto)); + + userDto1.getAuthorities().remove(authorityDto); + Assert.assertNotNull(user1); + mapperFacade.map(userDto1, user1, TypeFactory.valueOf(UserDto.class), + TypeFactory.valueOf(User.class)); + + assertFalse(user1.getAuthorities().contains(authority)); + } + + @Test + public void testChangeGroup() { + removeGroup(); + + getSession().flush(); + getSession().clear(); + + revertGroup(); + + getSession().flush(); + getSession().clear(); + + } + + private void removeGroup() { + UserGroup group = (UserGroup) getSession().load(UserGroup.class, + groupId); + + User user1 = (User) getSession().load(User.class, user1Id); + + assertTrue(group.getUsers().contains(user1)); + + UserDto userDto1 = mapperFacade.map(user1, UserDto.class); + + UserGroupDto groupDto = mapperFacade.map(group, UserGroupDto.class); + groupDto.removeUser(userDto1); + + mapperFacade.map(groupDto, group, + TypeFactory.valueOf(UserGroupDto.class), + TypeFactory.valueOf(UserGroup.class)); + + assertFalse(group.getUsers().contains(user1)); + } + + private void revertGroup() { + UserGroup group = (UserGroup) getSession().load(UserGroup.class, + groupId); + + User user1 = (User) getSession().load(User.class, user1Id); + + assertFalse(group.getUsers().contains(user1)); + + UserDto userDto1 = mapperFacade.map(user1, UserDto.class); + + UserGroupDto groupDto = mapperFacade.map(group, UserGroupDto.class); + groupDto.addUser(userDto1); + + mapperFacade.map(groupDto, group, + TypeFactory.valueOf(UserGroupDto.class), + TypeFactory.valueOf(UserGroup.class)); + + assertTrue(group.getUsers().contains(user1)); + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue232Test.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue232Test.java new file mode 100644 index 00000000..6f9b6895 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue232Test.java @@ -0,0 +1,64 @@ +package ma.glasnost.orika.test.community; + +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.NullFilter; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import org.junit.Before; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +public class Issue232Test { + + private MapperFactory mapperFactory; + + @Before + public void setUp() throws Exception { + mapperFactory = new DefaultMapperFactory.Builder().build(); + mapperFactory.registerFilter(new NullFilter()); + mapperFactory.classMap(FirstClassWithMap.class, SecondClassWithMap.class).byDefault().register(); + } + + @Test + public void test_map_to_map_with_filter() { + FirstClassWithMap firstMap = new FirstClassWithMap(); + firstMap.setMap(new HashMap<>()); + firstMap.getMap().put("A", "1"); + + SecondClassWithMap transformed = mapperFactory.getMapperFacade().map(firstMap, SecondClassWithMap.class); + + assertNotNull(transformed); + assertNotNull(transformed.getMap()); + assertEquals("1", transformed.getMap().get("A")); + } + + public static class FirstClassWithMap { + + private Map map; + + public Map getMap() { + return map; + } + + public void setMap(Map map) { + this.map = map; + } + } + + public static class SecondClassWithMap { + + private Map map; + + public Map getMap() { + return map; + } + + public void setMap(Map map) { + this.map = map; + } + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue24TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue24TestCase.java new file mode 100644 index 00000000..e651a504 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue24TestCase.java @@ -0,0 +1,71 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import org.junit.Assert; +import org.junit.Test; + +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.metadata.TypeFactory; +import ma.glasnost.orika.test.MappingUtil; + +/** + * lookupConcreteDestinationType should return the most specific type, not the first that is assignable. + *

+ * + * @see https://code.google.com/archive/p/orika/ + * @author mattdeboer + * + */ +public class Issue24TestCase { + + @Test + public void testLookupDestinationGetsMostSpecific() { + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.registerClassMap(factory.classMap(A.class, BSub.class).byDefault().toClassMap()); + factory.registerClassMap(factory.classMap(A.class, B.class).byDefault().toClassMap()); + factory.registerClassMap(factory.classMap(A.class, BSuper.class).byDefault().toClassMap()); + factory.getMapperFacade(); + + Type bsuper = factory.lookupConcreteDestinationType(TypeFactory.valueOf(A.class), TypeFactory.valueOf(BSuper.class), null); + Assert.assertEquals(BSuper.class, bsuper.getRawType()); + Type b = factory.lookupConcreteDestinationType(TypeFactory.valueOf(A.class), TypeFactory.valueOf(B.class), null); + Assert.assertEquals(B.class, b.getRawType()); + Type bsub = factory.lookupConcreteDestinationType(TypeFactory.valueOf(A.class), TypeFactory.valueOf(BSub.class), null); + Assert.assertEquals(BSub.class, bsub.getRawType()); + } + + public static class A { + + } + + public static class BSuper extends B { + + } + + public static class B extends BSub { + + } + + public static class BSub { + + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue25TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue25TestCase.java new file mode 100644 index 00000000..ff79746c --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue25TestCase.java @@ -0,0 +1,439 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import ma.glasnost.orika.CustomMapper; +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.OrikaSystemProperties; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.impl.UtilityResolver; +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.metadata.TypeFactory; +import ma.glasnost.orika.test.community.issue25.BaseManufacturingFacilityTest; +import ma.glasnost.orika.test.community.issue25.CustomOrikaMapper; +import ma.glasnost.orika.test.community.issue25.modelA.Address; +import ma.glasnost.orika.test.community.issue25.modelA.ManufacturingFacility; +import ma.glasnost.orika.test.community.issue25.modelB.AddressDTO; +import ma.glasnost.orika.test.community.issue25.modelB.ManufacturingFacilityDTS; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + + +/** + * Add customization of collection mapping. + *

+ * + * @see https://code.google.com/archive/p/orika/ + * + */ +public class Issue25TestCase extends BaseManufacturingFacilityTest{ + + private MapperFacade mapper = null; + + public Issue25TestCase() { + } + + @Before + public void setUp() throws Exception { + mapper = new CustomOrikaMapper(); + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testMapManufacuringFacilityToDTS() { + Map betriebsstaetteMap = + getManufacturingFacility(1L,"First"); + + ManufacturingFacility manufacturingFacility = (ManufacturingFacility)betriebsstaetteMap.get(BaseManufacturingFacilityTest.MANUFACTURINGFACILITY_KEY); + ManufacturingFacilityDTS manufacturingFacilityDTS = (ManufacturingFacilityDTS)betriebsstaetteMap.get(BaseManufacturingFacilityTest.MANUFACTURINGFACILITYDTS_KEY); + + addAddressToManufacturingFacility(betriebsstaetteMap, 1L, "Beispielstra�e 2", 815L, "This is a comment.", 'D'); + + ManufacturingFacilityDTS betriebsstaetteDTSMapped = mapper.map(manufacturingFacility, ManufacturingFacilityDTS.class); + ManufacturingFacility betriebsstaetteMappedBack = mapper.map(betriebsstaetteDTSMapped, ManufacturingFacility.class); + assertThat(manufacturingFacility, is(betriebsstaetteMappedBack)); + } + + @Test + public void testMapManufacuringFacilityToDTSNullValues() { + Map betriebsstaetteMap = + getManufacturingFacility(2L,"Second"); + + ManufacturingFacility manufacturingFacility = (ManufacturingFacility)betriebsstaetteMap.get(BaseManufacturingFacilityTest.MANUFACTURINGFACILITY_KEY); + ManufacturingFacilityDTS manufacturingFacilityDTS = (ManufacturingFacilityDTS)betriebsstaetteMap.get(BaseManufacturingFacilityTest.MANUFACTURINGFACILITYDTS_KEY); + + addAddressToManufacturingFacility(betriebsstaetteMap, 1L, null, 815L, "This is a comment.", 'D'); + + ManufacturingFacilityDTS betriebsstaetteDTSMapped = mapper.map(manufacturingFacility, ManufacturingFacilityDTS.class); + ManufacturingFacility betriebsstaetteMappedBack = mapper.map(betriebsstaetteDTSMapped, ManufacturingFacility.class); + assertThat(manufacturingFacility, is(betriebsstaetteMappedBack)); + } + + @Test + public void testMapManufacuringFacilityToDTSMultipleAdr() { + Map betriebsstaetteMap = + getManufacturingFacility(3L,"First"); + + ManufacturingFacility manufacturingFacility = (ManufacturingFacility)betriebsstaetteMap.get(BaseManufacturingFacilityTest.MANUFACTURINGFACILITY_KEY); + ManufacturingFacilityDTS manufacturingFacilityDTS = (ManufacturingFacilityDTS)betriebsstaetteMap.get(BaseManufacturingFacilityTest.MANUFACTURINGFACILITYDTS_KEY); + + addAddressToManufacturingFacility(betriebsstaetteMap, 10L, "StreetA", 815L, "This is a comment. 10", 'D'); + addAddressToManufacturingFacility(betriebsstaetteMap, 11L, "StreetB", 816L, "This is a comment. 11", 'E'); + addAddressToManufacturingFacility(betriebsstaetteMap, 12L, "StreetC", 817L, "This is a comment. 12", 'F'); + + ManufacturingFacilityDTS betriebsstaetteDTSMapped = mapper.map(manufacturingFacility, ManufacturingFacilityDTS.class); + ManufacturingFacility betriebsstaetteMappedBack = mapper.map(betriebsstaetteDTSMapped, ManufacturingFacility.class); + assertThat(manufacturingFacility, is(betriebsstaetteMappedBack)); + } + + @Test + public void testMapManufacuringFacilityToDTSMerge() { + Map betriebsstaetteMap = + getManufacturingFacility(4L,"Manufacturing Facility Description."); + + ManufacturingFacility manufacturingFacility = (ManufacturingFacility)betriebsstaetteMap.get(BaseManufacturingFacilityTest.MANUFACTURINGFACILITY_KEY); + ManufacturingFacilityDTS manufacturingFacilityDTS = (ManufacturingFacilityDTS)betriebsstaetteMap.get(BaseManufacturingFacilityTest.MANUFACTURINGFACILITYDTS_KEY); + + addAddressToManufacturingFacility(betriebsstaetteMap, 10L, "StreetA", 815L, "This is a comment. 10", 'D'); + addAddressToManufacturingFacility(betriebsstaetteMap, 11L, "StreetB", 816L, "This is a comment. 11", 'E'); + addAddressToManufacturingFacility(betriebsstaetteMap, 12L, "StreetC", 817L, "This is a comment. 12", 'F'); + + // Edit some values on "orginal" bean. + // This is because we want to see if values are kept which are not mapped. + + // With the AddressMergingMapper this variable does not contain any addresses after merge. + // The entity mapped from contains 3 addresses. + // Without the AddressMergingMapper there are contained 3 adresses. + // But then the check for the land value fails. + ManufacturingFacilityDTS manufacturingFacilityDTSServer = mapper.map(manufacturingFacility, ManufacturingFacilityDTS.class); + manufacturingFacilityDTSServer.setIdNumber(4L); + Character vLand = 'D'; + for(AddressDTO currAnschrift: manufacturingFacilityDTSServer.getAddressL()){ + currAnschrift.setLand(vLand); + } + + ManufacturingFacility manufacturingFacilityToEdit = mapper.map(manufacturingFacilityDTSServer,ManufacturingFacility.class); + manufacturingFacilityToEdit.putPrototype(manufacturingFacilityDTSServer); + + // Now the bean will be edited to see if the mapped values are correctly merged. + List

anschriftenGUI = manufacturingFacilityToEdit.getAddresses(); + anschriftenGUI.remove(1); + + manufacturingFacilityToEdit.setDescription("Description after merge."); + + Address firstAdr = anschriftenGUI.get(0); + firstAdr.setStreet("Street new"); + + // merge + ManufacturingFacilityDTS prototype = manufacturingFacilityToEdit.returnPrototype(); + mapper.map(manufacturingFacilityToEdit, prototype); + + // Do some checks. + assertThat("IdNumber was not kept after merge.", prototype.getIdNumber(), is(4L)); + + // Check name of street + assertThat(prototype.getAddressL().get(0).getStreet(), is("Street new")); + + // Amount of addresses + List addressesFromPrototype = prototype.getAddressL(); + assertThat("An address was removed. In the merged DS this address does still exist.", + addressesFromPrototype.size(), is(2)); + + // land check + List addressesAfterMerge = prototype.getAddressL(); + AddressDTO addressOne = addressesAfterMerge.get(0); + AddressDTO addressTwo = addressesAfterMerge.get(1); + + assertThat("Land after merge is wrong.", addressOne.getLand(), is('D')); + assertThat("Land after merge is wrong.", addressTwo.getLand(), is('D')); + } + + + @Test + public void testMergingWithCustomMapper() { + MapperFacade mapper = createMapperFacade(); + + List dtos = new ArrayList<>(); + + Dto dto = new Dto(); + dto.setId(1L); + dto.setName("A"); + dtos.add(dto); + + Dto dto2 = new Dto(); + dto2.setId(2L); + dto2.setName("B"); + dtos.add(dto2); + + dto = new Dto(); + dto.setId(3L); + dto.setName("C"); + dtos.add(dto); + + DtoHolder source = new DtoHolder(); + source.setEntities(dtos); + + Type typeOf_DtoHolder = TypeFactory.valueOf(DtoHolder.class); + UtilityResolver.getDefaultPropertyResolverStrategy().getProperties(typeOf_DtoHolder); + + final EntityHolder entities = mapper.map(source, EntityHolder.class); + + Assert.assertNotNull(entities); + Assert.assertEquals(3, entities.getEntities().size()); + + final EntityHolder originalEntities = entities; + source.getEntities().remove(dto2); + dto2.setName("B-Changed"); + source.getEntities().add(dto2); + + mapper.map(source, entities); + + Assert.assertEquals(entities.getEntities().size(), originalEntities.getEntities().size()); + + Iterator entitiesIter = entities.getEntities().iterator(); + Iterator originalIter = originalEntities.getEntities().iterator(); + while (entitiesIter.hasNext()) { + Entity e = entitiesIter.next(); + Entity o = originalIter.next(); + Assert.assertSame(e, o); + } + } + + private static MapperFacade createMapperFacade() { + DefaultMapperFactory.Builder builder = new DefaultMapperFactory.Builder(); + MapperFactory factory = builder.build(); + + factory.registerMapper(new MergingMapper()); + return factory.getMapperFacade(); + } + + @Test + public void testMergingWithCustomMapperForChildren() { + MapperFacade mapper = createMapperFacade(); + + List dtos = new ArrayList<>(); + + ChildDto dto = new ChildDto(); + dto.setId(1L); + dto.setName("A"); + dtos.add(dto); + + ChildDto dto2 = new ChildDto(); + dto2.setId(2L); + dto2.setName("B"); + dtos.add(dto2); + + dto = new ChildDto(); + dto.setId(3L); + dto.setName("C"); + dtos.add(dto); + + AnotherDtoHolder source = new AnotherDtoHolder(); + source.setEntities(dtos); + + Type typeOf_DtoHolder = TypeFactory.valueOf(DtoHolder.class); + UtilityResolver.getDefaultPropertyResolverStrategy().getProperties(typeOf_DtoHolder); + + final AnotherEntityHolder entities = mapper.map(source, AnotherEntityHolder.class); + + Assert.assertNotNull(entities); + Assert.assertEquals(3, entities.getEntities().size()); + + final AnotherEntityHolder originalEntities = entities; + source.getEntities().remove(dto2); + dto2.setName("B-Changed"); + source.getEntities().add(dto2); + + mapper.map(source, entities); + + Assert.assertEquals(entities.getEntities().size(), originalEntities.getEntities().size()); + + Iterator entitiesIter = entities.getEntities().iterator(); + Iterator originalIter = originalEntities.getEntities().iterator(); + while (entitiesIter.hasNext()) { + Entity e = entitiesIter.next(); + Entity o = originalIter.next(); + Assert.assertSame(e, o); + } + } + + public static class MergingMapper extends CustomMapper, Collection> { + + public void mapAtoB(Collection a, Collection b, MappingContext context) { + merge(a, b); + } + + private Collection merge(Collection srcDtos, Collection dstEntities) { + + Set ids = new HashSet<>(srcDtos.size()); + for (Dto memberDto : srcDtos) { + Entity memberEntity = findEntity(dstEntities, memberDto.getId()); + if (memberEntity == null) { + dstEntities.add(mapperFacade.map(memberDto, Entity.class)); + } else { + mapperFacade.map(memberEntity, memberDto); + } + ids.add(memberDto.getId()); + } + + dstEntities.removeIf(dstEntity -> !dstEntity.isNew() && !ids.contains(dstEntity.getId())); + + return dstEntities; + + } + + private Entity findEntity(Collection dstEntities, Long id) { + for (Entity dstEntity : dstEntities) { + if (id.equals(dstEntity.getId())) { + return dstEntity; + } + } + return null; + } + + } + + public static class EntityHolder { + + private Collection entityList; + + public Collection getEntities() { + return entityList; + } + + public void setEntities(Collection entityList) { + this.entityList = entityList; + } + + } + + public static class AnotherEntityHolder { + private List entityList; + + public List getEntities() { + return entityList; + } + + public void setEntities(List entityList) { + this.entityList = entityList; + } + + } + + public static class DtoHolder { + + private Collection dtoList; + + public Collection getEntities() { + return dtoList; + } + + public void setEntities(Collection dtoList) { + this.dtoList = dtoList; + } + + } + + public static class AnotherDtoHolder { + private List dtoList; + + public List getEntities() { + return dtoList; + } + + public void setEntities(List dtoList) { + this.dtoList = dtoList; + } + + } + + public static class Entity { + + private Long id; + private String name; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public boolean isNew() { + return id == null; + } + } + + public static class ChildEntity extends Entity { + + } + + public static class Dto { + private Long id; + private String name; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + public static class ChildDto extends Dto { + + } + +} + diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue26TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue26TestCase.java new file mode 100644 index 00000000..337d23f8 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue26TestCase.java @@ -0,0 +1,54 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.test.MappingUtil; +import ma.glasnost.orika.test.community.issue26.Order; +import ma.glasnost.orika.test.community.issue26.OrderData; +import ma.glasnost.orika.test.community.issue26.OrderID; +import ma.glasnost.orika.test.community.issue26.OrderIDConverter; +import org.junit.Assert; +import org.junit.Test; + +/** + * Generic super-type not recognized. + *

+ * + * @see https://code.google.com/archive/p/orika/ + * + */ +public class Issue26TestCase { + + @Test + public void testMapping() { + MapperFactory mapperFactory = MappingUtil.getMapperFactory(); + + mapperFactory.registerClassMap( + mapperFactory.classMap(Order.class, OrderData.class) + .field("entityID", "orderId").byDefault().toClassMap()); + + mapperFactory.getConverterFactory().registerConverter(new OrderIDConverter()); + MapperFacade facade = mapperFactory.getMapperFacade(); + + OrderData data = new OrderData(1234L); + Order order = facade.map(data, Order.class); + Assert.assertEquals(new OrderID(1234L), order.getEntityID()); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue28TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue28TestCase.java new file mode 100644 index 00000000..795cbd87 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue28TestCase.java @@ -0,0 +1,58 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import ma.glasnost.orika.CustomConverter; +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.test.MappingUtil; +import ma.glasnost.orika.test.community.issue26.OrderID; +import ma.glasnost.orika.test.community.issue28.Order; +import ma.glasnost.orika.test.community.issue28.OrderData; +import org.junit.Assert; +import org.junit.Test; + +/** + * StackoverflowException on recursively-defined generic type. + *

+ * + * @see https://code.google.com/archive/p/orika/ + * + */ +public class Issue28TestCase { + @Test + public void testMapping() { + MapperFactory mapperFactory = MappingUtil.getMapperFactory(); + mapperFactory.getConverterFactory().registerConverter(new OrderIdConverter()); + mapperFactory.classMap(Order.class, OrderData.class).field("id", "number").byDefault().register(); + MapperFacade facade = mapperFactory.getMapperFacade(); + OrderData data = new OrderData(1234L); + Order order = facade.map(data, Order.class); + Assert.assertEquals(Long.valueOf(1234L), order.getId()); + } + + public static class OrderIdConverter extends CustomConverter { + + public OrderID convert(Long source, Type destinationType, MappingContext context) { + return new OrderID(source); + } + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue30TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue30TestCase.java new file mode 100644 index 00000000..79bf84a1 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue30TestCase.java @@ -0,0 +1,179 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.metadata.TypeBuilder; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.is; + +/** + * MappingException: cannot determine runtime type of destination collection. + *

+ * + * @see https://code.google.com/archive/p/orika/ + * + */ +public class Issue30TestCase { + + public static abstract class ComputerPart { + private Long id; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + } + + public static class HardDrive extends ComputerPart { + private String capacity; + + public String getCapacity() { + return capacity; + } + + public void setCapacity(String capacity) { + this.capacity = capacity; + } + } + + public static class VideoCard extends ComputerPart { + public String chip; + + public String getChip() { + return chip; + } + + public void setChip(String chip) { + this.chip = chip; + } + } + + public static class Inventory { + private List items; + + public List getItems() { + return items; + } + + public void setItems(List items) { + this.items = items; + } + } + + public static abstract class ComputerPartDTO { + private Long id; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + } + + public static class HardDriveDTO extends ComputerPartDTO { + private String capacity; + + public String getCapacity() { + return capacity; + } + + public void setCapacity(String capacity) { + this.capacity = capacity; + } + } + + public static class VideoCardDTO extends ComputerPartDTO { + public String chip; + + public String getChip() { + return chip; + } + + public void setChip(String chip) { + this.chip = chip; + } + } + + public static class InventoryDTO { + private List items; + + public List getItems() { + return items; + } + + public void setItems(List items) { + this.items = items; + } + } + + @Test + public void testOrder() { + MapperFactory factory = new DefaultMapperFactory.Builder().build(); + + Type> ih1 = new TypeBuilder>() { + }.build(); + Type> ih2 = new TypeBuilder>() { + }.build(); + + Type> iv1 = new TypeBuilder>() { + }.build(); + Type> iv2 = new TypeBuilder>() { + }.build(); + + factory.registerClassMap(factory.classMap(HardDrive.class, + HardDriveDTO.class).toClassMap()); + factory.registerClassMap(factory.classMap(VideoCard.class, + VideoCardDTO.class).toClassMap()); + factory.registerClassMap(factory.classMap(ih1, ih2).byDefault() + .toClassMap()); + factory.registerClassMap(factory.classMap(iv1, iv2).byDefault() + .toClassMap()); + + List hardDrives = new ArrayList<>(); + hardDrives.add(new HardDrive()); + hardDrives.add(new HardDrive()); + + Inventory inventory = new Inventory<>(); + inventory.setItems(hardDrives); + + InventoryDTO inventoryDTO = factory.getMapperFacade().map(inventory, + InventoryDTO.class); + + + assertThat(inventory.getItems(), hasSize(inventoryDTO.getItems().size())); + + for (Object o: inventoryDTO.getItems()) { + assertThat(o, is(instanceOf(ComputerPartDTO.class))); + } + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue314TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue314TestCase.java new file mode 100644 index 00000000..4a3f510a --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue314TestCase.java @@ -0,0 +1,55 @@ +package ma.glasnost.orika.test.community; + +import ma.glasnost.orika.impl.DefaultMapperFactory; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertNull; + +/** + * ClassMapBuilderForMaps class exclude method Does not work + *

+ * + * @see https://github.com/orika-mapper/orika/issues + */ +public class Issue314TestCase { + + @Test + public void exclude_classMapBuilderForMaps() { + + DefaultMapperFactory mapperFactory = new DefaultMapperFactory.Builder().build(); + mapperFactory.classMap(Map.class, B.class).exclude("b").byDefault().register(); + + Map map = new HashMap<>(); + map.put("a", "a"); + map.put("b", "b"); + + B b = mapperFactory.getMapperFacade().map(map, B.class); + assertNull(b.getB()); + } + + public static class B { + private String a; + private String b; + + public String getA() { + return a; + } + + public void setA(String a) { + this.a = a; + } + + public String getB() { + return b; + } + + public void setB(String b) { + this.b = b; + } + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue322TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue322TestCase.java new file mode 100644 index 00000000..e02b26c3 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue322TestCase.java @@ -0,0 +1,47 @@ +package ma.glasnost.orika.test.community; + +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.test.MappingUtil; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.assertEquals; + +/** + * @see https://github.com/orika-mapper/orika/issues/322 + */ +public class Issue322TestCase { + + @Test + public void compile_error_when_customized_list_element_mapping_int_to_integer() { + PersonList personList = new PersonList(); + Person person = new Person(); + person.age = 20; + personList.persons.add(person); + + MapperFactory mapperFactory = MappingUtil.getMapperFactory(); + mapperFactory.classMap(PersonList.class, PersonAgeListDto.class) + .field("persons{age}", "personAges{}") + .byDefault() + .register(); + + PersonAgeListDto dest = mapperFactory.getMapperFacade().map(personList, PersonAgeListDto.class); + + assertEquals(1, dest.personAges.size()); + assertEquals(Integer.valueOf(20), dest.personAges.get(0)); + } + + public static class Person { + public int age; + } + + public static class PersonList { + public List persons = new ArrayList<>(); + } + + public static class PersonAgeListDto { + public List personAges; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue34TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue34TestCase.java new file mode 100644 index 00000000..8b49cd48 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue34TestCase.java @@ -0,0 +1,110 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import static org.junit.Assert.assertEquals; +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.unenhance.HibernateUnenhanceStrategy; + +import org.junit.Test; + +/** + * The mapper create a child's instance instead of a parent's instance. + *

+ * + * @see https://code.google.com/archive/p/orika/ + * @author Dmitriy Khomyakov + */ +public class Issue34TestCase { + + @Test + public void testDefaultMapping() { + DefaultMapperFactory.Builder builder = new DefaultMapperFactory.Builder(); + builder.unenhanceStrategy(new HibernateUnenhanceStrategy()); + MapperFactory mapperFactory = builder.build(); + + MapperFacade mapperFacade = mapperFactory.getMapperFacade(); + + Entity entity = new Entity("small data", "big data"); + + Child child = mapperFacade.map(entity, Child.class); + assertEquals(child.getClass(), Child.class); + + Parent parent = mapperFacade.map(entity, Parent.class);// orika returns + // expensive + // object + assertEquals(Parent.class, parent.getClass()); + + } + + public static class Entity { + private String light; + private String expensive; + + public Entity(String light, String expensive) { + this.light = light; + this.expensive = expensive; + } + + public Entity() { + } + + public String getLight() { + return light; + } + + public void setLight(String light) { + this.light = light; + } + + public String getExpensive() { + return expensive; + } + + public void setExpensive(String expensive) { + this.expensive = expensive; + } + } + + public static class Parent { + private String light; + + public String getLight() { + return light; + } + + public void setLight(String light) { + this.light = light; + } + } + + public static class Child extends Parent { + private String expensive; + + public String getExpensive() { + return expensive; + } + + public void setExpensive(String expensive) { + this.expensive = expensive; + } + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue38TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue38TestCase.java new file mode 100644 index 00000000..075edb09 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue38TestCase.java @@ -0,0 +1,90 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import org.junit.Assert; +import org.junit.Test; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.test.MappingUtil; + +/** + * Want to have option to not set target object property when property value in the source object is null. + *

+ * + * @see https://code.google.com/archive/p/orika/ + */ +public class Issue38TestCase { + + @Test + public void testAvoidEmptyObjectCreation() { + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.registerClassMap(factory.classMap(A.class, B.class).field("b.i1", "i1").field("b.i2", "i2").toClassMap()); + + MapperFacade mapperFacade = factory.getMapperFacade(); + + + B b = new B(); + b.i1 = null; + b.i2 = null; + + + A result = mapperFacade.map(b, A.class); + + Assert.assertNull(result.b); + + b.i1 = 2; + b.i2 = null; + } + + @Test + public void testCreateDestinationIfNotNull() { + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.registerClassMap(factory.classMap(A.class, B.class).field("b.i1", "i1").field("b.i2", "i2").toClassMap()); + + MapperFacade mapperFacade = factory.getMapperFacade(); + + + B b = new B(); + b.i1 = 2; + b.i2 = 3; + + + A result = mapperFacade.map(b, A.class); + + Assert.assertNotNull(result.b); + Assert.assertEquals(b.i1, result.b.i1); + Assert.assertEquals(b.i2, result.b.i2); + + } + + public static class A { + public B b; + } + + public static class B { + public Integer i1; + public Integer i2; + } + + + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue41TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue41TestCase.java new file mode 100644 index 00000000..9a488b9a --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue41TestCase.java @@ -0,0 +1,108 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + + +import org.junit.Assert; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.ConfigurableMapper; +import ma.glasnost.orika.test.ConcurrentRule.Concurrent; +import ma.glasnost.orika.test.community.issue41.MyEnum; +import ma.glasnost.orika.test.community.issue41.MyEnumConverter; +import ma.glasnost.orika.test.community.issue41.MySourceObject; +import ma.glasnost.orika.test.community.issue41.MyTargetObject; + +import org.junit.Test; + +/** + * StackOverflowError for nested Enum. + *

+ * + * @see https://code.google.com/archive/p/orika/ + */ +public class Issue41TestCase { + + @Test + public void test_converter_string_to_enum_direct_working() { + + ConfigurableMapper mapper = new ConfigurableMapper() { + + @Override + public void configure(MapperFactory factory) { + + factory.registerClassMap(factory.classMap(MySourceObject.class, MyTargetObject.class).field("e", "directE") + + .toClassMap()); + + factory.getConverterFactory().registerConverter(new MyEnumConverter()); + } + }; + + MySourceObject s = new MySourceObject(); + s.setE("un"); + MyTargetObject t = mapper.map(s, MyTargetObject.class); + Assert.assertEquals(MyEnum.one, t.getDirectE()); + } + + @Test + @Concurrent(200) + public void test_converter_string_to_string_nested_not_working() { + + ConfigurableMapper mapper = new ConfigurableMapper() { + + @Override + public void configure(MapperFactory factory) { + + factory.registerClassMap(factory.classMap(MySourceObject.class, MyTargetObject.class)// + .field("e", "sub.s") + .toClassMap()); + + factory.getConverterFactory().registerConverter(new MyEnumConverter()); + } + }; + + MySourceObject s = new MySourceObject(); + s.setE("un"); + MyTargetObject t = mapper.map(s, MyTargetObject.class); + Assert.assertEquals("un", t.getSub().getS()); + } + + @Test + public void test_converter_string_to_enum_nested_not_working() { + + ConfigurableMapper mapper = new ConfigurableMapper() { + + @Override + public void configure(MapperFactory factory) { + factory.getConverterFactory().registerConverter(new MyEnumConverter()); + + factory.registerClassMap( // + factory.classMap(MySourceObject.class, MyTargetObject.class)// + .field("e", "sub.e") + .toClassMap()); + + } + }; + + MySourceObject s = new MySourceObject(); + s.setE("un"); + MyTargetObject t = mapper.map(s, MyTargetObject.class); + Assert.assertEquals(MyEnum.one, t.getSub().getE()); + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue44TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue44TestCase.java new file mode 100644 index 00000000..e1f7f612 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue44TestCase.java @@ -0,0 +1,231 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import ma.glasnost.orika.CustomConverter; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.impl.ConfigurableMapper; +import ma.glasnost.orika.metadata.Type; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static java.util.Arrays.asList; +import static org.hamcrest.Matchers.arrayWithSize; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + +/** + * Allow converters for Lists (or other collections). + *

+ * + * @see https://code.google.com/archive/p/orika/ + */ +public class Issue44TestCase { + + @Test + public void shouldMapCollection() { + ConfigurableMapper mapper = new ConfigurableMapper() { + @Override + protected void configure(MapperFactory factory) { + factory.classMap(Order.class, OrderDto.class).byDefault().register(); + factory.classMap(Product.class, ProductDto.class).byDefault().register(); + } + }; + Order order = new Order(); + Product product = new Product(); + product.setName("myName"); + order.setProducts(asList(product)); + OrderDto orderDto = mapper.map(order, OrderDto.class); + assertThat(orderDto.getProducts(), hasSize(1)); + assertThat(orderDto.getProducts().get(0).getName(), is(equalTo("myName"))); + } + + @Test + public void shouldMapCollectionWithConverter() { + ConfigurableMapper mapper = new ConfigurableMapper() { + @Override + protected void configure(MapperFactory factory) { + factory.getConverterFactory().registerConverter("productToName", new CustomConverter, List>() { + + public List convert(List source, Type> destinationType, MappingContext context) { + ArrayList list = new ArrayList<>(source.size()); + for (Product product : source) { + list.add(product.getName()); + } + return list; + } + }); + factory.classMap(Order.class, OrderDto.class) + .fieldMap("products", "productNames") + .converter("productToName") + .add() + .register(); + factory.classMap(Product.class, ProductDto.class).byDefault().register(); + } + }; + Order order = new Order(); + Product product = new Product(); + product.setName("myName"); + order.setProducts(asList(product)); + OrderDto orderDto = mapper.map(order, OrderDto.class); + assertThat(orderDto.getProductNames(), hasSize(1)); + assertThat(orderDto.getProductNames().get(0), is(equalTo("myName"))); + } + + @Test + public void shouldMapCollectionWithElementConverter_ToCollection() { + ConfigurableMapper mapper = new ConfigurableMapper() { + @Override + protected void configure(MapperFactory factory) { + factory.getConverterFactory().registerConverter("productToName", new CustomConverter() { + + public String convert(Product source, Type destinationType, MappingContext context) { + return source.getName(); + } + }); + factory.classMap(Order.class, OrderDto.class) + .fieldMap("products", "productNames") + .converter("productToName") + .add() + .register(); + factory.classMap(Product.class, ProductDto.class).byDefault().register(); + } + }; + + Order order = new Order(); + Product product = new Product(); + product.setName("myName"); + order.setProducts(asList(product)); + OrderDto orderDto = mapper.map(order, OrderDto.class); + assertThat(orderDto.getProductNames(), hasSize(1)); + assertThat(orderDto.getProductNames().get(0), is(equalTo("myName"))); + } + + @Test + public void shouldMapCollectionWithElementConverter_ToArray() { + ConfigurableMapper mapper = new ConfigurableMapper() { + @Override + protected void configure(MapperFactory factory) { + factory.getConverterFactory().registerConverter("productToName", new CustomConverter() { + + public String convert(Product source, Type destinationType, MappingContext context) { + return source.getName(); + } + }); + factory.classMap(Order.class, OrderDto2.class) + .fieldMap("products", "productNames") + .converter("productToName") + .add() + .register(); + factory.classMap(Product.class, ProductDto.class).byDefault().register(); + } + }; + + Order order = new Order(); + Product product = new Product(); + product.setName("myName"); + order.setProducts(asList(product)); + OrderDto2 orderDto = mapper.map(order, OrderDto2.class); + assertThat(orderDto.getProductNames(), arrayWithSize(1)); + assertThat(orderDto.getProductNames()[0], is(equalTo("myName"))); + } + + public static class Product { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + public static class Order { + private List products; + + public List getProducts() { + return products; + } + + public void setProducts(List products) { + this.products = products; + } + } + + public static class ProductDto { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + public static class OrderDto { + private List products; + private List productNames; + + public List getProducts() { + return products; + } + + public void setProducts(List products) { + this.products = products; + } + + public List getProductNames() { + return productNames; + } + + public void setProductNames(List productNames) { + this.productNames = productNames; + } + } + + public static class OrderDto2 { + private List products; + private String[] productNames; + + public List getProducts() { + return products; + } + + public void setProducts(List products) { + this.products = products; + } + + public String[] getProductNames() { + return productNames; + } + + public void setProductNames(String[] productNames) { + this.productNames = productNames; + } + } +} \ No newline at end of file diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue45TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue45TestCase.java new file mode 100644 index 00000000..693c85e5 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue45TestCase.java @@ -0,0 +1,121 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import ma.glasnost.orika.CustomConverter; +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.impl.ConfigurableMapper; +import ma.glasnost.orika.metadata.Type; +import org.junit.Assert; +import org.junit.Test; + +/** + * resolveSourceType does not distinguish by destinationType. + *

+ * + * @see https://code.google.com/archive/p/orika/ + */ +public class Issue45TestCase { + + public static class Source { + public String name; + public String description; + } + + public static class SourceChild extends Source { + } + + public static class Dest1 { + private final String name; + private final String description; + + public Dest1(Source src) { + this.name = src.name; + this.description = src.description; + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + } + + public static class Dest2 { + public String name; + public String description; + } + + private static class MyMapper extends ConfigurableMapper { + + private static class SourceConverter extends CustomConverter { + + public Dest1 convert(SourceChild source, Type destinationType, MappingContext context) { + return new Dest1(source); + } + } + + public void configure(MapperFactory mapperFactory) { + mapperFactory.getConverterFactory().registerConverter(new SourceConverter()); + } + } + + /* + * We need a type which can be resolved 2 different ways: + * + * SourceChild == Source : mapping SourceChild == SourceChild : converter + */ + @Test + public void testResolveTypes2() { + + MapperFacade mapper = new MyMapper(); + + Source src = new Source(); + src.name = "source 1"; + src.description = "source 1 description"; + + SourceChild srcChild = new SourceChild(); + srcChild.name = "source 1"; + srcChild.description = "source 1 description"; + + /* + * Mapping Source to Dest2 causes a mapping to be created + */ + Dest2 dest2 = mapper.map(src, Dest2.class); + /* + * SourceChild is able to use this mapping, so the resolved type in this + * case for SourceChild is 'Source', which gets cached in resolvedTypes + */ + Dest2 dest2B = mapper.map(srcChild, Dest2.class); + + Assert.assertNotNull(dest2); + Assert.assertNotNull(dest2B); + + /* + * But now, since the resolvedType for 'SourceChild' has been cached as + * 'Source', it cannot find the converter which has been specifically + * created for 'SourceChild' + */ + Dest1 dest1 = mapper.map(srcChild, Dest1.class); + Assert.assertNotNull(dest1); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue46TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue46TestCase.java new file mode 100644 index 00000000..24df1b40 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue46TestCase.java @@ -0,0 +1,148 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.OrikaSystemProperties; +import ma.glasnost.orika.test.MappingUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +/** + * Class-cast exception for mapped objects. + *

+ * + * @see https://code.google.com/archive/p/orika/ + */ +public class Issue46TestCase { + public static class One { + public List getTwos() { + return twos; + } + + public void setTwos(List twos) { + this.twos = twos; + } + + List twos = new ArrayList<>(); + + public One(String name) { + this.name = name; + twos.add(new Two(name)); + } + + public One() { + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + String name; + + } + + public static class Two { + public Two() { + } + + public Two(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + String name; + } + + public static class Parent { + public List getOneList() { + return oneList; + } + + public void setOneList(List oneList) { + this.oneList = oneList; + } + + List oneList = new ArrayList<>(); + + public List getTwoList() { + return twoList; + } + + public void setTwoList(List twoList) { + this.twoList = twoList; + } + + List twoList = new ArrayList<>(); + } + + @Test + public void test() { + System.setProperty(OrikaSystemProperties.WRITE_SOURCE_FILES, "true"); + + MapperFactory factory = MappingUtil.getMapperFactory(); + MapperFacade facade = factory.getMapperFacade(); + + List parents = new ArrayList<>(); + for (int i = 0; i < 100; i++) { + Parent parent = new Parent(); + List ones = new ArrayList<>(); + List twos = new ArrayList<>(); + for (int j = 0; j < 1000; j++) { + ones.add(new One(Integer.toString(j))); + twos.add(new Two(Integer.toString(j))); + } + + parent.oneList = ones; + parent.twoList = twos; + parents.add(parent); + } + + int transforms = 0; + try { + for (Parent parent : parents) { + transforms++; + + Parent result = facade.map(parent, Parent.class); + + for (One one : result.oneList) + for (Two two : one.twos) + Assert.assertNotNull(two.getName()); + + } + } catch (Exception e) { + throw new AssertionError("Failed to process graph. failed after " + transforms + " transforms, exception = " + e); + } + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue49TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue49TestCase.java new file mode 100644 index 00000000..11c6ce4d --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue49TestCase.java @@ -0,0 +1,88 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; + +import org.junit.Assert; +import org.junit.Test; + +/** + * MappingException when enum toString() is overridden. + *

+ * Verify that we use Enum.name instead of Enum.toString + * + * @see https://code.google.com/archive/p/orika/ + * @author Dmitriy Khomyakov + */ +public class Issue49TestCase { + + @Test + public void testMapOfEnum() { + DefaultMapperFactory.Builder builder = new DefaultMapperFactory.Builder(); + MapperFactory factory = builder.build(); + MapperFacade mapperFacade = factory.getMapperFacade(); + Entity entity = new Entity(); + entity.setState(State.B); + final Dto dto = mapperFacade.map(entity, Dto.class); + Assert.assertEquals(dto.getState(), entity.getState()); + } + + public static enum State { + A { + @Override + public String toString() { + return "first"; + } + }, + B { + @Override + public String toString() { + return "second"; + } + } + } + + public static class Entity { + private State state; + + public State getState() { + return state; + } + + public void setState(State state) { + this.state = state; + } + } + + public static class Dto { + private State state; + + public State getState() { + return state; + } + + public void setState(State state) { + this.state = state; + } + } + +} \ No newline at end of file diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue50TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue50TestCase.java new file mode 100644 index 00000000..846bc807 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue50TestCase.java @@ -0,0 +1,134 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import org.junit.Assert; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; + +import org.junit.Test; + +/** + * Exclusions are ignored when combined with used mappers. + *

+ * + * @see https://code.google.com/archive/p/orika/ + * @author matt.deboer@gmail.com + * + */ +public class Issue50TestCase { + + public static class Source { + public String id; + public String type; + public String name; + public int age; + } + + public static class Dest { + public String id; + public String type; + public String name; + public int age; + } + + public static class SubSource extends Source { + public String description; + public double weight; + } + + public static class SubDest extends Dest { + public String description; + public double weight; + } + + public static class SubSource2 extends SubSource { + public String taxId; + } + + public static class SubDest2 extends SubDest { + public String taxId; + } + + @Test + public void testExcludedFields() { + + MapperFactory factory = + new DefaultMapperFactory.Builder() + .build(); + + + factory.registerClassMap(factory.classMap(Source.class, Dest.class) + .exclude("id") + .exclude("type") + .byDefault()); + + factory.registerClassMap(factory + .classMap(SubSource.class, SubDest.class) + .use(Source.class, Dest.class).byDefault()); + + SubSource source = new SubSource(); + source.id = "1"; + source.type = "A"; + source.name = "Bob"; + source.age = 55; + + SubDest destination = factory.getMapperFacade().map(source, SubDest.class); + Assert.assertNull(destination.id); + Assert.assertNull(destination.type); + Assert.assertEquals(source.name, destination.name); + Assert.assertEquals(source.age, destination.age); + } + + /** + * This test case verifies that an excluded mapping from a used mapper + * can be overridden by explicitly specifying the field + */ + @Test + public void testOverrideExcludedFields() { + + MapperFactory factory = + new DefaultMapperFactory.Builder() + .build(); + + + factory.registerClassMap(factory.classMap(Source.class, Dest.class) + .exclude("id") + .exclude("type") + .byDefault()); + + factory.registerClassMap(factory + .classMap(SubSource2.class, SubDest2.class) + .field("type", "type") + .use(Source.class, Dest.class) + .byDefault()); + + SubSource2 source = new SubSource2(); + source.id = "1"; + source.type = "A"; + source.name = "Bob"; + source.age = 55; + + SubDest2 destination = factory.getMapperFacade().map(source, SubDest2.class); + Assert.assertNull(destination.id); + Assert.assertEquals(source.type, destination.type); + Assert.assertEquals(source.name, destination.name); + Assert.assertEquals(source.age, destination.age); + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue52aTestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue52aTestCase.java new file mode 100644 index 00000000..75d7d366 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue52aTestCase.java @@ -0,0 +1,109 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import org.junit.Assert; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; + +import org.junit.Test; + +/** + * StackOverflowError when using inheritance mapping. + *

+ * + * @see https://code.google.com/archive/p/orika/ + * @author matt.deboer@gmail.com + * + */ +public class Issue52aTestCase { + + @Test + public void test() { + + MapperFactory factory = new DefaultMapperFactory.Builder().build(); + factory.classMap(Parent.class, ParentDto.class).byDefault().register(); + factory.classMap(Child1.class, ChildDto1.class).byDefault().register(); + factory.classMap(Child2.class, ChildDto2.class).byDefault().register(); + factory.classMap(Child3.class, ChildDto3.class).byDefault().register(); + factory.classMap(ChildDto11.class, Child11.class).byDefault().register(); + factory.classMap(ChildDto12.class, Child12.class).byDefault().register(); + factory.classMap(ChildDto111.class, Child111.class).byDefault().register(); + + ChildDto11 dto11 = factory.getMapperFacade().map(new Child11(), ChildDto11.class); + ChildDto12 dto12 = factory.getMapperFacade().map(new Child12(), ChildDto12.class); + ChildDto111 dto111 = factory.getMapperFacade().map(new Child111(), ChildDto111.class); + ChildDto3 dto3 = factory.getMapperFacade().map(new Child3(), ChildDto3.class); + ChildDto2 dto2 = factory.getMapperFacade().map(new Child2(), ChildDto2.class); + ChildDto1 dto1 = factory.getMapperFacade().map(new Child1(), ChildDto1.class); + + Assert.assertNotNull(dto11); + Assert.assertNotNull(dto12); + Assert.assertNotNull(dto111); + Assert.assertNotNull(dto3); + Assert.assertNotNull(dto2); + Assert.assertNotNull(dto1); + } + + + public static class Parent { + + } + public static class Child1 extends Parent { + + } + public static class Child2 extends Parent { + + } + public static class Child3 extends Parent { + + } + public static class Child11 extends Child1 { + + } + public static class Child12 extends Child1 { + + } + public static class Child111 extends Child11 { + + } + + + public static class ParentDto { + + } + public static class ChildDto1 extends ParentDto { + + } + public static class ChildDto2 extends ParentDto { + + } + public static class ChildDto3 extends ParentDto { + + } + public static class ChildDto11 extends ChildDto1 { + + } + public static class ChildDto12 extends ChildDto1 { + + } + public static class ChildDto111 extends ChildDto11 { + + } +} + diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue52bTestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue52bTestCase.java new file mode 100644 index 00000000..49971b80 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue52bTestCase.java @@ -0,0 +1,111 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import org.junit.Assert; +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; + +import org.junit.Test; + +/** + * StackOverflowError when using inheritance mapping. + *

+ * + * @see https://code.google.com/archive/p/orika/ + * @author matt.deboer@gmail.com + * + */ +public class Issue52bTestCase { + + @Test + public void parentBeforeChild() { + + MapperFactory factory = new DefaultMapperFactory.Builder().build(); + MapperFacade mapper = factory.getMapperFacade(); + + A source = new A(); + source.field1 = "one"; + source.field2 = "two"; + + B dest = mapper.map(source, B.class); + + Assert.assertEquals(source.field1, dest.field1); + Assert.assertEquals(source.field2, dest.field2); + + A1 source2 = new A1(); + source2.field1 = "one"; + source2.field2 = "two"; + source2.field3 = "three"; + + dest = mapper.map(source2, B.class); + + Assert.assertEquals(source2.field1, dest.field1); + Assert.assertEquals(source2.field2, dest.field2); + Assert.assertEquals(source2.field3, dest.field3); + + } + + @Test + public void childBeforeParent() { + + MapperFactory factory = new DefaultMapperFactory.Builder().build(); + MapperFacade mapper = factory.getMapperFacade(); + + + A1 source2 = new A1(); + source2.field1 = "one"; + source2.field2 = "two"; + source2.field3 = "three"; + + + B dest = mapper.map(source2, B.class); + + Assert.assertEquals(source2.field1, dest.field1); + Assert.assertEquals(source2.field2, dest.field2); + Assert.assertEquals(source2.field3, dest.field3); + + A source = new A(); + source.field1 = "one"; + source.field2 = "two"; + + dest = mapper.map(source, B.class); + + Assert.assertEquals(source.field1, dest.field1); + Assert.assertEquals(source.field2, dest.field2); + + } + + public static class A { + public String field1; + public String field2; + } + + public static class A1 extends A { + public String field3; + } + + public static class B { + public String field1; + public String field2; + public String field3; + } + +} + diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue53TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue53TestCase.java new file mode 100644 index 00000000..816b996a --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue53TestCase.java @@ -0,0 +1,125 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import static org.junit.Assert.assertEquals; +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.test.MappingUtil; + +import org.junit.Test; + +/** + * Dynamic mapping always uses existing parent mapper even if it doesn't map all fields. + *

+ * + * @see https://code.google.com/archive/p/orika/ + * + */ +public class Issue53TestCase { + + @Test + public void subClassSetterOrikaTest() { + final MapperFactory mapperFactory = MappingUtil.getMapperFactory();/*new DefaultMapperFactory.Builder().build();*/ + final MapperFacade mapper = mapperFactory.getMapperFacade(); + + final SearchRecord sr = new SearchRecord(); + sr.setScore(88); + + final Result result = new Result(); + result.setBaseRecords(new Record()); + result.setResult(sr); + + final Result2 mappedResult = mapper.map(result, Result2.class); + + assertEquals(88, mappedResult.getResult().getScore()); + } + + public static class Record { + } + + public static class SearchRecord extends Record { + private int score; + + public int getScore() { + return score; + } + + public void setScore(final int score) { + this.score = score; + } + } + + public static class Result { + private Record baseRecords; + private SearchRecord result; + + public void setBaseRecords(final Record baseRecords) { + this.baseRecords = baseRecords; + } + + public Record getBaseRecords() { + return baseRecords; + } + + public SearchRecord getResult() { + return result; + } + + public void setResult(final SearchRecord result) { + this.result = result; + } + + } + + public static class Record2 { + } + + public static class SearchRecord2 extends Record2 { + private int score; + + public int getScore() { + return score; + } + + public void setScore(final int score) { + this.score = score; + } + } + + public static class Result2 { + private Record2 baseRecords; + private SearchRecord2 result; + + public Record2 getBaseRecords() { + return baseRecords; + } + + public void setBaseRecords(final Record2 baseRecords) { + this.baseRecords = baseRecords; + } + + public SearchRecord2 getResult() { + return result; + } + + public void setResult(final SearchRecord2 result) { + this.result = result; + } + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue61TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue61TestCase.java new file mode 100644 index 00000000..15c94e10 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue61TestCase.java @@ -0,0 +1,131 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import org.junit.Assert; +import org.junit.Test; + +import java.util.HashSet; +import java.util.Set; + +/** + * StackOverflowError on circle association + *

+ * + * @see https://code.google.com/archive/p/orika/ + * @author Dmitriy Khomyakov + */ +public class Issue61TestCase { + @Test + public void testAuthorityMap() { + DefaultMapperFactory.Builder builder = new DefaultMapperFactory.Builder(); + MapperFactory factory = builder.build(); + MapperFacade mapperFacade = factory.getMapperFacade(); + + MyEntity root = new MyEntity("root"); + MyEntity child = new MyEntity("child"); + root.getChildren().add(child); + root.getChildren().add(root); + child.addChild(root); + + MyDto myDto = mapperFacade.map(root, MyDto.class); + Assert.assertEquals(myDto.getCaption(), root.getCaption()); + + // System.out.println("myDto = " + myDto); + + } + + public static class MyEntity { + private String name; + private String caption; + private Set children; + + public MyEntity() { + } + + public MyEntity(String name) { + this.name = name; + children = new HashSet<>(); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getCaption() { + return caption; + } + + public void setCaption(String caption) { + this.caption = caption; + } + + public Set getChildren() { + return children; + } + + public void addChild(MyEntity myEntity) { + children.add(myEntity); + } + + public void setChildren(Set children) { + this.children = children; + } + + } + + public static class MyDto { + private String caption; + + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + private Set children; + + public String getCaption() { + return caption; + } + + public void setCaption(String caption) { + this.caption = caption; + } + + public Set getChildren() { + return children; + } + + public void setChildren(Set children) { + this.children = children; + } + + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue64Test.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue64Test.java new file mode 100644 index 00000000..37c265aa --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue64Test.java @@ -0,0 +1,142 @@ +package ma.glasnost.orika.test.community; + +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.OrikaSystemProperties; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static java.util.Arrays.asList; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * Orika does not create intermediate property when mapping lists. + *

+ * + * @see https://github.com/orika-mapper/orika/issues + */ +public class Issue64Test { + + private final MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build(); + private final Source source = new Source(); + + @BeforeClass + public static void setUp() throws Exception { + System.setProperty(OrikaSystemProperties.WRITE_SOURCE_FILES,"true"); + System.setProperty(OrikaSystemProperties.WRITE_CLASS_FILES,"true"); + } + + @Test + public void createIntermediateObjectForSingleProperty() { + mapperFactory.registerClassMap(mapperFactory.classMap(Source.class, Parent.class) + .fieldAToB("single", "child.nestedSingle") + ); + source.setSingle("SINGLE"); + + Parent target = mapperFactory.getMapperFacade(Source.class, Parent.class).map(source); + + assertEquals("SINGLE", target.getChild().getNestedSingle()); + } + + @Test + public void createIntermediateObjectForListProperty() { + mapperFactory.registerClassMap(mapperFactory.classMap(Source.class, Parent.class) + .fieldAToB("list{}", "child.nestedList{}") + ); + + source.setList(asList("A", "B")); + + Parent target = mapperFactory.getMapperFacade(Source.class, Parent.class).map(source); + + assertEquals(asList("A", "B"), target.getChild().getNestedList()); + } + + @Test + public void createIntermediateObjectForBothPropertiesWithNonNullSingle() { + mapperFactory.registerClassMap(mapperFactory.classMap(Source.class, Parent.class) + .fieldAToB("single", "child.nestedSingle") + .fieldAToB("list{}", "child.nestedList{}") + ); + source.setSingle("SINGLE"); + source.setList(asList("A", "B")); + + Parent target = mapperFactory.getMapperFacade(Source.class, Parent.class).map(source); + + assertEquals("SINGLE", target.getChild().getNestedSingle()); + assertEquals(asList("A", "B"), target.getChild().getNestedList()); + } + + @Test + public void createIntermediateObjectForBothPropertiesWithNullSingle() { + mapperFactory.registerClassMap(mapperFactory.classMap(Source.class, Parent.class) + .fieldAToB("list{}", "child.nestedList{}") + .fieldAToB("single", "child.nestedSingle") + ); + source.setSingle(null); + source.setList(asList("A", "B")); + + Parent target = mapperFactory.getMapperFacade(Source.class, Parent.class).map(source); + + assertNull(target.getChild().getNestedSingle()); + assertEquals(asList("A", "B"), target.getChild().getNestedList()); + } + + public static class Source { + private String single; + private List list; + + public String getSingle() { + return single; + } + + public void setSingle(String single) { + this.single = single; + } + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } + } + + public static class Parent { + private Child child; + + public Child getChild() { + return child; + } + + public void setChild(Child child) { + this.child = child; + } + } + + public static class Child { + private String nestedSingle; + private List nestedList = new ArrayList<>(); + + public String getNestedSingle() { + return nestedSingle; + } + + public void setNestedSingle(String nestedSingle) { + this.nestedSingle = nestedSingle; + } + + public List getNestedList() { + return nestedList; + } + + public void setNestedList(List nestedList) { + this.nestedList = nestedList; + } + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue64TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue64TestCase.java new file mode 100644 index 00000000..789c665b --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue64TestCase.java @@ -0,0 +1,224 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.test.MappingUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +/** + * SimpleConstructorResolverStrategy ignores generic parameter types + *

+ * + * @see https://code.google.com/archive/p/orika/ + * @author matt.deboer@gmail.com + * + */ +public class Issue64TestCase { + + @Test + public void mapWithConstructor() { + + Supplier supplier = new Supplier(); + supplier.setName("Chester Tester"); + supplier.setEmail("chester@email.com"); + supplier.setAddresses(new ArrayList<>()); + Address addr = new Address(); + addr.street = "1234 Test st."; + addr.city = "Testville"; + addr.country = "USA"; + addr.postalCode = "12354"; + supplier.getAddresses().add(addr); + Contact ct = new Contact(); + ct.name = "Bob Tester"; + ct.email = "bob@email.com"; + supplier.setContacts(new ArrayList<>()); + supplier.getContacts().add(ct); + + MapperFactory mapperFactory = MappingUtil.getMapperFactory(); + MapperFacade mapper = mapperFactory.getMapperFacade(); + + SupplierDto result = mapper.map(supplier, SupplierDto.class); + + Assert.assertNotNull(result); + Assert.assertEquals(supplier.getAddresses().size(), result.getAddresses().size()); + Assert.assertEquals(supplier.getContacts().size(), result.getContacts().size()); + for (int i=0; i < supplier.getContacts().size(); ++i) { + Assert.assertEquals(supplier.getContacts().get(i).email, result.getContacts().get(i).email); + Assert.assertEquals(supplier.getContacts().get(i).name, result.getContacts().get(i).name); + } + for (int i=0; i < supplier.getAddresses().size(); ++i) { + Assert.assertEquals(supplier.getAddresses().get(i).street, result.getAddresses().get(i).street); + Assert.assertEquals(supplier.getAddresses().get(i).city, result.getAddresses().get(i).city); + Assert.assertEquals(supplier.getAddresses().get(i).country, result.getAddresses().get(i).country); + Assert.assertEquals(supplier.getAddresses().get(i).postalCode, result.getAddresses().get(i).postalCode); + } + Assert.assertEquals(supplier.getEmail(), result.getEmail()); + Assert.assertEquals(supplier.getName(), result.getName()); + } + + public static class Supplier { + private List

addresses; + private List contacts; + private String name; + private String email; + /** + * @return the addresses + */ + public List
getAddresses() { + return addresses; + } + /** + * @param addresses the addresses to set + */ + public void setAddresses(List
addresses) { + this.addresses = addresses; + } + /** + * @return the contacts + */ + public List getContacts() { + return contacts; + } + /** + * @param contacts the contacts to set + */ + public void setContacts(List contacts) { + this.contacts = contacts; + } + /** + * @return the name + */ + public String getName() { + return name; + } + /** + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + /** + * @return the email + */ + public String getEmail() { + return email; + } + /** + * @param email the email to set + */ + public void setEmail(String email) { + this.email = email; + } + + } + + public static class SupplierDto { + private List
addresses; + private List contacts; + private String name; + private String email; + + public SupplierDto(List
addresses, List contacts, String name, String email) { + this.addresses = addresses; + this.contacts = contacts; + this.name = name; + this.email = email; + } + + /** + * @return the addresses + */ + public List
getAddresses() { + return addresses; + } + /** + * @param addresses the addresses to set + */ + public void setAddresses(List
addresses) { + this.addresses = addresses; + } + /** + * @return the contacts + */ + public List getContacts() { + return contacts; + } + /** + * @param contacts the contacts to set + */ + public void setContacts(List contacts) { + this.contacts = contacts; + } + /** + * @return the name + */ + public String getName() { + return name; + } + /** + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + /** + * @return the email + */ + public String getEmail() { + return email; + } + /** + * @param email the email to set + */ + public void setEmail(String email) { + this.email = email; + } + + + } + + public static class Address { + public String street; + public String city; + public String country; + public String postalCode; + } + + public static class AddressDto { + public String street; + public String city; + public String country; + public String postalCode; + } + + public static class Contact { + public String name; + public String email; + } + + public static class ContactDto { + public String name; + public String email; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue65TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue65TestCase.java new file mode 100644 index 00000000..7afd933a --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue65TestCase.java @@ -0,0 +1,119 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import java.util.Date; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.test.MappingUtil; + +import org.junit.Test; + +/** + * Orika wraps user exceptions in MapperException + *

+ * + * @see https://code.google.com/archive/p/orika/ + * @author matt.deboer@gmail.com + * + */ +public class Issue65TestCase { + + public static class CustomException extends RuntimeException { + private static final long serialVersionUID = 1L; + } + + public static class DomainObject { + + private Long value; + private Date date; + /** + * @return the value + */ + public Long getValue() { + return value; + } + /** + * @param value the value to set + */ + public void setValue(Long value) { + if (value == null || value <= 0) { + throw new CustomException(); + } + this.value = value; + } + /** + * @return the date + */ + public Date getDate() { + return date; + } + /** + * @param date the date to set + */ + public void setDate(Date date) { + this.date = date; + } + + } + + public static class DomainObjectDto { + + private Long value; + private Date date; + /** + * @return the value + */ + public Long getValue() { + return value; + } + /** + * @param value the value to set + */ + public void setValue(Long value) { + this.value = value; + } + /** + * @return the date + */ + public Date getDate() { + return date; + } + /** + * @param date the date to set + */ + public void setDate(Date date) { + this.date = date; + } + } + + + @Test(expected=CustomException.class) + public void throwExceptions() { + + MapperFactory mapperFactory = MappingUtil.getMapperFactory(); + MapperFacade mapper = mapperFactory.getMapperFacade(); + + DomainObjectDto dto = new DomainObjectDto(); + dto.setDate(new Date()); + dto.setValue(-2L); + + mapper.map(dto, DomainObject.class); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue67Test.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue67Test.java new file mode 100644 index 00000000..08e1dca5 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue67Test.java @@ -0,0 +1,62 @@ +package ma.glasnost.orika.test.community; + +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import org.junit.Before; +import org.junit.Test; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * NPE on VariableRef.isPrimitive() with map of map. + *

+ * + * @see https://github.com/orika-mapper/orika/issues + */ +public class Issue67Test { + + private MapperFactory mapperFactory; + private static final Date A_DATE = new Date(); + + @Before + public void setUp() throws Exception { + mapperFactory = new DefaultMapperFactory.Builder().build(); + mapperFactory.classMap(DateToIntegerToStringMap.class, DateToIntegerToStringMap.class) + .byDefault() + .register(); + } + + @Test + public void clone_a_map_of_map() { + DateToIntegerToStringMap original = new DateToIntegerToStringMap(); + Map integerStringMap = new HashMap<>(); + integerStringMap.put(5, "five"); + Map> dateMapMap = new HashMap<>(); + dateMapMap.put(A_DATE, integerStringMap); + original.setDateIntegerStringMap(dateMapMap); + + DateToIntegerToStringMap copy = mapperFactory.getMapperFacade().map(original, DateToIntegerToStringMap.class); + + Map nestedMap = copy.getDateIntegerStringMap().get(A_DATE); + assertNotNull(nestedMap); + assertEquals("five", nestedMap.get(5)); + } + + public static class DateToIntegerToStringMap { + + public Map> getDateIntegerStringMap() { + return dateIntegerStringMap; + } + + public void setDateIntegerStringMap(Map> dateIntegerStringMap) { + this.dateIntegerStringMap = dateIntegerStringMap; + } + + private Map> dateIntegerStringMap; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue67TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue67TestCase.java new file mode 100644 index 00000000..87d13373 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue67TestCase.java @@ -0,0 +1,71 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import org.junit.Test; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; + +/** + * Property with no getter (null readMethod) is not being excluded/ignored + *

+ * + * @see https://code.google.com/archive/p/orika/ + * @author matt.deboer@gmail.com + * + */ +public class Issue67TestCase { + + @Test + public void simpleCase() { + MapperFactory factory = new DefaultMapperFactory.Builder().build(); + factory.registerClassMap(factory.classMap(Bean.class, Bean.class) + .byDefault().toClassMap()); + MapperFacade mapper = factory.getMapperFacade(); + Bean bean = new Bean(); + bean.setSize(20); + bean.setName("Kidney"); + mapper.map(bean, Bean.class); + + /* If map pass no need to check */ + } + + public static class Bean { + + private String name; + private int size; + + /* + * public int getSize() { return size; } + */ + public void setSize(int size) { + this.size = size; + } + + public String getName() { + return name; + } + + public void setName(String value) { + this.name = value; + } + } +} \ No newline at end of file diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue68TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue68TestCase.java new file mode 100644 index 00000000..c67d84ff --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue68TestCase.java @@ -0,0 +1,321 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.ObjectFactory; +import ma.glasnost.orika.impl.ConfigurableMapper; +import org.junit.Test; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.is; + + +/** + * How to handle infinit recursion for entities with bidirectional many-to-many relations. + *

+ * + * @see https://code.google.com/archive/p/orika/ + * + */ +public class Issue68TestCase { + + @Test + public void testSimpleReverceCase() { + ConfigurableMapper mapper = new ConfigurableMapper() { + @Override + public void configure(MapperFactory mapperFactory) { + mapperFactory.classMap(InvoiceItem.class, InvoiceItemVO.class).byDefault().register(); + mapperFactory.classMap(ProjectItem.class, ProjectItemVO.class).byDefault().register(); + mapperFactory.classMap(Project.class, ProjectVO.class).byDefault().register(); + } + + }; + + ProjectVO projectVO = new ProjectVO(); + ProjectItemVO projectItemVO = new ProjectItemVO(); + InvoiceItemVO invoiceitemVO = new InvoiceItemVO(); + + projectItemVO.project = projectVO; + invoiceitemVO.project = projectVO; + + projectVO.getProjectItems().add(projectItemVO); + projectVO.name = "Great project"; + projectItemVO.getInvoiceItems().add(invoiceitemVO); + + invoiceitemVO.getProjectItems().add(projectItemVO); + + InvoiceItemProxy invoiceItemProxy = BeanFactory.createInvoiceItemProxy(); + mapper.map(invoiceitemVO, invoiceItemProxy); + + ProjectProxy projectProxy = BeanFactory.createProjectProxy(); + mapper.map(projectVO, projectProxy); + + assertThat(projectVO.getName(), is(projectProxy.getName())); + assertThat(projectVO.getProjectItems(), hasSize(projectProxy.getProjectItems().size())); + } + + public static class BeanFactory { + public static ProjectProxy createProjectProxy() { + return new Project(); + } + + public static ProjectItemProxy createProjectItemProxy() { + return new ProjectItem(); + } + + public static InvoiceItemProxy createInvoiceItemProxy() { + return new InvoiceItem(); + } + } + + public interface ProjectProxy { + + void setProjectItems(Set projectItems); + + Set getProjectItems(); + + void setName(String name); + + String getName(); + + } + + public static class Project implements ProjectProxy { + + private String name; + private Set projectItems = new HashSet(); + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Set getProjectItems() { + return convertSet(projectItems, ProjectItemProxy.class); + } + + public void setProjectItems(Set projectItems) { + this.projectItems = castSet(projectItems, ProjectItem.class); + } + } + + public class ProjectItemProxyFactory implements + ObjectFactory { + + /* + * @Override public ProjectItemProxy create(Object source, + * Type destinationType) { ProjectItemProxy personDto + * = new ProjectItem(); return personDto; } + */ + + public ProjectItemProxy create(Object source, MappingContext context) { + ProjectItemProxy personDto = new ProjectItem(); + return personDto; + } + } + + public interface ProjectItemProxy { + + void setInvoiceItems(Set invoiceItems); + + Set getInvoiceItems(); + + void setProject(ProjectProxy project); + + ProjectProxy getProject(); + + void setName(String name); + + String getName(); + + } + + public static class ProjectItem implements ProjectItemProxy { + private String name; + + private Project project; + + private Set invoiceItems = new HashSet(); + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public ProjectProxy getProject() { + return project; + } + + public void setProject(ProjectProxy project) { + this.project = (Project) project; + } + + public Set getInvoiceItems() { + return convertSet(invoiceItems, InvoiceItemProxy.class); + } + + public void setInvoiceItems(Set invoiceItems) { + this.invoiceItems = castSet(invoiceItems, InvoiceItem.class); + } + } + + public interface InvoiceItemProxy { + + ma.glasnost.orika.test.community.Issue68TestCase.ProjectProxy getProject(); + + void setProjectItems(Set projectItems); + + Set getProjectItems(); + + void setProject( + ma.glasnost.orika.test.community.Issue68TestCase.ProjectProxy project); + + } + + public static class InvoiceItem implements InvoiceItemProxy { + + private Project project; + + private Set projectItems = new HashSet(); + + public ProjectProxy getProject() { + return project; + } + + public void setProject(ProjectProxy project) { + this.project = (Project) project; + } + + public Set getProjectItems() { + return convertSet(projectItems, ProjectItemProxy.class); + } + + public void setProjectItems(Set projectItems) { + this.projectItems = castSet(projectItems, ProjectItem.class); + } + } + + public static class ProjectVO { + private String name; + private Set projectItems = new HashSet(); + + public String toString() { + return ""; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Set getProjectItems() { + return projectItems; + } + + public void setProjectItems(Set projectItems) { + this.projectItems = projectItems; + } + } + + public static class ProjectItemVO { + private String name; + + private ProjectVO project; + + private final Set invoiceItems = new HashSet(); + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public ProjectVO getProject() { + return project; + } + + public void setProject(ProjectVO project) { + this.project = project; + } + + public Set getInvoiceItems() { + return invoiceItems; + } + + // public void setInvoiceItems(Set invoiceItems) { + // this.invoiceItems = invoiceItems; + // } + } + + public static class InvoiceItemVO { + + private ProjectVO project; + + private final Set projectItems = new HashSet(); + + public ProjectVO getProject() { + return project; + } + + public void setProject(ProjectVO project) { + this.project = project; + } + + public Set getProjectItems() { + return projectItems; + } + + // public void setProjectItems(Set projectItems) { + // this.projectItems = projectItems; + // } + } + + public static Set convertSet(Set sourceSet, + Class targetType) { + if (sourceSet == null) + return null; + Set set = new HashSet(sourceSet); + return set; + } + + public static Set castSet(Set sourceSet, Class clazz) { + if (sourceSet == null) + return null; + Set set = new HashSet((Collection) sourceSet); + return set; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue69TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue69TestCase.java new file mode 100644 index 00000000..b90031ec --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue69TestCase.java @@ -0,0 +1,246 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.test.MappingUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Orika fails to map classes with lists which do not return internal references. + *

+ * + * @see https://code.google.com/archive/p/orika/ + * @author matt.deboer@gmail.com + * + */ +public class Issue69TestCase { + + + @Test + public void verify() { + + MapperFactory factory = MappingUtil.getMapperFactory(); + MapperFacade mapper = factory.getMapperFacade(); + + Source s = new Source(); + Map map = new HashMap<>(); + map.put("Kofi", "Annan"); + map.put("Julius", "Ceasar"); + s.setMap(map); + + List list = new ArrayList<>(); + list.add("apple"); + list.add("banana"); + s.setList(list); + + String[] array = new String[2]; + array[0] = "one"; + array[1] = "two"; + s.setArray(array); + + Destination d = mapper.map(s, Destination.class); + + Source mapBack = mapper.map(d, Source.class); + + Assert.assertEquals(s, mapBack); + + } + + + + /* + * TODO: + * Construct a usage case which contains a class with a list type + * which is returned as an unmodifiable list from the getter + * + */ + + public static class Source { + private Map map; + private List list; + private String[] array; + /** + * @return the map + */ + public Map getMap() { + return map != null ? Collections.unmodifiableMap(map) : null; + } + /** + * @param map the map to set + */ + public void setMap(Map map) { + this.map = map; + } + /** + * @return the list + */ + public List getList() { + return list != null ? Collections.unmodifiableList(list) : null; + } + /** + * @param list the list to set + */ + public void setList(List list) { + this.list = list; + } + /** + * @return the array + */ + public String[] getArray() { + return array!=null ? array.clone() : null; + } + /** + * @param array the array to set + */ + public void setArray(String[] array) { + this.array = array; + } + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + Arrays.hashCode(array); + result = prime * result + ((list == null) ? 0 : list.hashCode()); + result = prime * result + ((map == null) ? 0 : map.hashCode()); + return result; + } + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Source other = (Source) obj; + if (!Arrays.equals(array, other.array)) + return false; + if (list == null) { + if (other.list != null) + return false; + } else if (!list.equals(other.list)) + return false; + if (map == null) { + if (other.map != null) + return false; + } else if (!map.equals(other.map)) + return false; + return true; + } + } + + public static class Destination { + private Map map; + private List list; + private String[] array; + /** + * @return the map + */ + public Map getMap() { + return map != null ? Collections.unmodifiableMap(map) : null; + } + /** + * @param map the map to set + */ + public void setMap(Map map) { + this.map = map; + } + /** + * @return the list + */ + public List getList() { + return list != null ? Collections.unmodifiableList(list) : null; + } + /** + * @param list the list to set + */ + public void setList(List list) { + this.list = list; + } + /** + * @return the array + */ + public String[] getArray() { + return array!=null ? array.clone() : null; + } + /** + * @param array the array to set + */ + public void setArray(String[] array) { + this.array = array; + } + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + Arrays.hashCode(array); + result = prime * result + ((list == null) ? 0 : list.hashCode()); + result = prime * result + ((map == null) ? 0 : map.hashCode()); + return result; + } + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Destination other = (Destination) obj; + if (!Arrays.equals(array, other.array)) + return false; + if (list == null) { + if (other.list != null) + return false; + } else if (!list.equals(other.list)) + return false; + if (map == null) { + if (other.map != null) + return false; + } else if (!map.equals(other.map)) + return false; + return true; + } + + + + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue71TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue71TestCase.java new file mode 100644 index 00000000..7c7c8d32 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue71TestCase.java @@ -0,0 +1,82 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +/** + * Orika maps enum to enum, but not List<enum> to List<enum>. + *

+ * + * @see https://code.google.com/archive/p/orika/ + * + */ +public class Issue71TestCase { + + + @Test + public void testEnumListMap() { + final MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build(); + final MapperFacade mapper = mapperFactory.getMapperFacade(); + + final A a = new A(); + final List myEnumList = new ArrayList<>(); + myEnumList.add(MyEnum.foo); + a.setMyEnum(myEnumList); + mapper.map(a, A2.class); + + } + + public static enum MyEnum { + foo, bar + } + + public static class A { + private List myEnum; + + public List getMyEnum() { + return myEnum; + } + + public void setMyEnum(final List myEnum) { + this.myEnum = myEnum; + } + } + + public static enum MyEnum2 { + foo, bar + } + + public static class A2 { + private List myEnum; + + public List getMyEnum() { + return myEnum; + } + + public void setMyEnum(final List myEnum) { + this.myEnum = myEnum; + } + } + } diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue77Test.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue77Test.java new file mode 100644 index 00000000..c37220f2 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue77Test.java @@ -0,0 +1,69 @@ +package ma.glasnost.orika.test.community; + +import com.google.common.collect.ImmutableMap; +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.test.MappingUtil; +import org.junit.Test; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static com.google.common.collect.Sets.newHashSet; +import static java.util.Arrays.asList; +import static org.junit.Assert.assertEquals; + +/** + * Invalid code generated when embedded field name not a valid java variable name. + *

+ * + * @see https://github.com/orika-mapper/orika/issues + */ +public class Issue77Test { + + @Test + public void map_with_keys_containing_invalid_characters_for_a_variable_instantiation() { + MapperFactory mapperFactory = MappingUtil.getMapperFactory(true); + + mapperFactory.classMap(A.class, B.class) + .field("mapSource['foo//bar']", "targetSet") + .register(); + + MapperFacade mapperFacade = mapperFactory.getMapperFacade(); + + Map> mapSource = ImmutableMap.>builder() + .put("foo//bar", asList("one", "two")) + .build(); + A source = new A(); + source.setMapSource(mapSource); + + B map1 = mapperFacade.map(source, B.class); + + assertEquals(newHashSet("one", "two"), map1.getTargetSet()); + } + + public static class A { + private Map> mapSource; + + public Map> getMapSource() { + return mapSource; + } + + public void setMapSource(Map> mapSource) { + this.mapSource = mapSource; + } + } + + public static class B { + private Set targetSet; + + public Set getTargetSet() { + return targetSet; + } + + public void setTargetSet(Set targetSet) { + this.targetSet = targetSet; + } + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue77TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue77TestCase.java new file mode 100644 index 00000000..3aaafcd6 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue77TestCase.java @@ -0,0 +1,121 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + +/** + * A sub type is not being mapped to the configured mapping type. + *

+ * + * @see https://code.google.com/archive/p/orika/ + * + */ +public class Issue77TestCase { + + public static class A1 { + + } + + public static class B1 extends A1 { + int someProperty; + } + + public static class Container1 { + private List elements = new ArrayList<>(); + private A1 singleElement; + + public List getElements() { + return elements; + } + + public void setElements(final List elements) { + this.elements = elements; + } + + public A1 getSingleElement() { + return singleElement; + } + + public void setSingleElement(final A1 singleElement) { + this.singleElement = singleElement; + } + } + + public static class A2 { + + } + + public static class B2 extends A2 { + int someProperty; + } + + public static class Container2 { + private List elements = new ArrayList<>(); + private A2 singleElement; + + public List getElements() { + return elements; + } + + public void setElements(final List elements) { + this.elements = elements; + } + + public A2 getSingleElement() { + return singleElement; + } + + public void setSingleElement(final A2 singleElement) { + this.singleElement = singleElement; + } + } + + @Test + public void testMappingSubTypes() { + // Test data + final Container1 c1 = new Container1(); + c1.elements.add(new B1()); + c1.singleElement = new B1(); + + // mapper + final MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build(); + mapperFactory.classMap(B1.class, B2.class).byDefault().register(); + mapperFactory.classMap(B2.class, B1.class).byDefault().register(); + final MapperFacade mapper = mapperFactory.getMapperFacade(); + + // map + final Container2 c2 = mapper.map(c1, Container2.class); + + // check + assertThat(c1.singleElement, is(instanceOf(B1.class))); + assertThat(c2.singleElement, is(instanceOf(B2.class))); + assertThat(c2.elements.get(0), is(instanceOf(B2.class))); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue80TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue80TestCase.java new file mode 100644 index 00000000..7fad293d --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue80TestCase.java @@ -0,0 +1,77 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import java.util.HashMap; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.test.MappingUtil; + +import org.junit.Assert; +import org.junit.Test; + +/** + * There is a bug for JavaBean to Map. + *

+ * I define a class like this: public class JsonObject extends HashMap{...}. Orika can not map JavaBean to JsonObject. + * + * @see https://code.google.com/archive/p/orika/ + * + */ +public class Issue80TestCase { + + public static class JsonObject extends HashMap { + + } + + public static class JavaBean { + public String name; + public Integer id; + } + + @Test + public void test() { + + // TODO: determine whether the solution is that + // 1. we should be able to getNestedType(0) on JsonObject and get String + // or + // 2. we should be able to resolve the values of the get and put + // methods... + + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.classMap(JsonObject.class, JavaBean.class) + .field("name", "name") + .field("id", "id") + .register(); + + JsonObject source = new JsonObject(); + source.put("name", "Joe Smit"); + source.put("id", 22); + + MapperFacade mapper = factory.getMapperFacade(); + + JavaBean dest = mapper.map(source, JavaBean.class); + + Assert.assertEquals(source.get("name"), dest.name); + Assert.assertEquals(source.get("id"), dest.id); + + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue82TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue82TestCase.java new file mode 100644 index 00000000..ece018ae --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue82TestCase.java @@ -0,0 +1,344 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import ma.glasnost.orika.DefaultFieldMapper; +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.metadata.ClassMapBuilder; +import ma.glasnost.orika.metadata.ClassMapBuilderFactory; +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.property.PropertyResolverStrategy; +import ma.glasnost.orika.unenhance.HibernateUnenhanceStrategy; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * MappingException on customization the default field-name mapping. + *

+ * + * @see https://code.google.com/archive/p/orika/ + * @author Alexey Salnikov + */ +public class Issue82TestCase { + private MapperFacade mapperFacade; + + @Before + public void init() { + DefaultMapperFactory.Builder builder = new DefaultMapperFactory.Builder(); + builder.unenhanceStrategy(new HibernateUnenhanceStrategy()); + builder.classMapBuilderFactory(new MyClassMapBuilderFactory()); + MapperFactory mapperFactory = builder.build(); + mapperFacade = mapperFactory.getMapperFacade(); + } + + @Test + public void testMapDtoToEntity() { + DocTypeDto docTypeDto = new DocTypeDto(); + docTypeDto.setId(1L); + docTypeDto.setCaption("Test document type"); + + DocStatusDto docStatusDto = new DocStatusDto(); + docStatusDto.setId(1L); + docStatusDto.setDocTypeId(docTypeDto.getId()); + docStatusDto.setCaption("Draft"); + + SomeDocumentDto documentDto = new SomeDocumentDto(); + documentDto.setId(1L); + documentDto.setType(docTypeDto); + documentDto.setStatus(docStatusDto); + documentDto.setName("Some document"); + + SomeDocument document = mapperFacade.map(documentDto, SomeDocument.class); + assertNotNull(document.getStatus()); + assertNotNull(document.getStatus().getDocType()); + assertEquals(new Long(1), document.getStatus().getDocType().getId()); + + documentDto = mapperFacade.map(document, SomeDocumentDto.class); + assertNotNull(documentDto.getStatus()); + assertEquals(new Long(1), documentDto.getStatus().getDocTypeId()); + } + + @Test + public void testMapEntityToDto() { + DocType docType = new DocType(); + docType.setId(1L); + docType.setCaption("Test document type"); + + DocStatus docStatus = new DocStatus(); + docStatus.setId(1L); + docStatus.setDocType(docType); + docStatus.setCaption("Draft"); + + SomeDocument document = new SomeDocument(); + document.setType(docType); + document.setStatus(docStatus); + document.setName("Some document"); + + SomeDocumentDto documentDto = mapperFacade.map(document, SomeDocumentDto.class); + assertNotNull(documentDto.getStatus()); + assertEquals(new Long(1), documentDto.getStatus().getDocTypeId()); + + document = mapperFacade.map(documentDto, SomeDocument.class); + assertNotNull(document.getStatus()); + assertNotNull(document.getStatus().getDocType()); + assertEquals(new Long(1), document.getStatus().getDocType().getId()); + } + + /*********************************************************************************** + * Entities + **********************************************************************************/ + + public static class DocType { + private Long id; + private String caption; + + public DocType() { + } + + public DocType(DocType type) { + setId(type.getId()); + setCaption(type.getCaption()); + } + + public String getCaption() { + return caption; + } + + public void setCaption(String caption) { + this.caption = caption; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + } + + public static class DocStatus { + private Long id; + private String caption; + private DocType docType; + + public DocStatus() { + } + + public DocStatus(DocStatus status) { + setId(status.getId()); + setCaption(status.getCaption()); + setDocType(new DocType(status.getDocType())); + } + + public String getCaption() { + return caption; + } + + public void setCaption(String caption) { + this.caption = caption; + } + + public DocType getDocType() { + return docType; + } + + public void setDocType(DocType docType) { + this.docType = docType; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + } + + public static class SomeDocument { + private Long id; + private DocType type; + private DocStatus status; + private String name; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public DocStatus getStatus() { + return status; + } + + public void setStatus(DocStatus status) { + this.status = status; + } + + public DocType getType() { + return type; + } + + public void setType(DocType type) { + this.type = type; + } + } + + /*********************************************************************************** + * DTOs + **********************************************************************************/ + + public static class DocTypeDto { + private Long id; + private String caption; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getCaption() { + return caption; + } + + public void setCaption(String caption) { + this.caption = caption; + } + } + + public static class DocStatusDto { + private Long id; + private String caption; + private Long docTypeId; + + public String getCaption() { + return caption; + } + + public void setCaption(String caption) { + this.caption = caption; + } + + public Long getDocTypeId() { + return docTypeId; + } + + public void setDocTypeId(Long docTypeId) { + this.docTypeId = docTypeId; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + } + + public static class SomeDocumentDto { + private Long id; + private DocTypeDto type; + private DocStatusDto status; + private String name; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public DocStatusDto getStatus() { + return status; + } + + public void setStatus(DocStatusDto status) { + this.status = status; + } + + public DocTypeDto getType() { + return type; + } + + public void setType(DocTypeDto type) { + this.type = type; + } + } + + /*********************************************************************************** + * Factory & builder + **********************************************************************************/ + + private static class MyClassMapBuilderFactory extends ClassMapBuilderFactory { + @Override + protected ClassMapBuilder newClassMapBuilder(Type aType, Type bType, MapperFactory mapperFactory, + PropertyResolverStrategy propertyResolver, DefaultFieldMapper[] defaults) { + return new MyClassMapBuilder<>(aType, bType, mapperFactory, propertyResolver, defaults); + } + } + + private static class MyClassMapBuilder extends ClassMapBuilder { + public MyClassMapBuilder(Type aType, Type bType, MapperFactory mapperFactory, PropertyResolverStrategy propertyResolver, + DefaultFieldMapper... defaults) { + super(aType, bType, mapperFactory, propertyResolver, defaults); + } + + @Override + public ClassMapBuilder byDefault(DefaultFieldMapper... withDefaults) { + super.byDefault(withDefaults); + + if (getAType().getRawType().equals(DocStatus.class)) { + fieldMap("docType.id", "docTypeId").add(); + } else if (getAType().getRawType().equals(DocStatusDto.class)) { + fieldMap("docTypeId", "docType.id").add(); + } + + return this; + } + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue85TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue85TestCase.java new file mode 100644 index 00000000..d6f32c51 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue85TestCase.java @@ -0,0 +1,61 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.test.MappingUtil; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +/** + * NullPointerException in MultiOccurrenceToMultiOccurrence.mapFields. + *

+ * + * @see https://code.google.com/archive/p/orika/ + * @author conleym + * + */ +public final class Issue85TestCase { + + @Test + public void test() { + MapperFactory f = MappingUtil.getMapperFactory(); + f.classMap(MapContainer.class, Map.class).field("map{value}", "{key}").register(); + + final MapperFacade facade = f.getMapperFacade(); + final Map dest = new HashMap<>(); + final Map src = new HashMap<>(); + src.put("xyz", "123456"); + facade.map(new MapContainer<>(src), dest); + System.out.println(dest); + } + + + public final static class MapContainer { + public final Map map; + + public MapContainer(final Map map) { + this.map = map; + } + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue87TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue87TestCase.java new file mode 100644 index 00000000..8ed190f1 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue87TestCase.java @@ -0,0 +1,101 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingException; +import ma.glasnost.orika.impl.DefaultMapperFactory; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * Nested properties: Allow abstract nested property's fields mapping. + *

+ * + * @see https://code.google.com/archive/p/orika/ + * + */ +public class Issue87TestCase { + + private MapperFactory mapperFactory; + + @Before + public void createMapperFactoryAndDefineMapping() { + mapperFactory = new DefaultMapperFactory.Builder() + .useAutoMapping(false).build(); + mapperFactory.classMap(FakeBeanA.class, FakeBeanB.class) + .field("fieldA", "fieldB.nestedField").register(); + } + + @Test(expected = MappingException.class) + public void cannotMapAbstractNestedPropertyWhenConcreteTypeIsNotRegistered() { + + // We expect to get a MappingException. Indeed, Orika doesn't know how + // to create an + // instance of AbstractNestedField (the type of FakeBeanB.fieldB) + createAnInstanceOfFakeBeanAAndMapItToFakeBeanB(); + } + + @Test + public void mapAbstractNestedPropertyWhenConcreteTypeIsRegistered() { + + // Register concrete type for AbstractNestedType + mapperFactory.registerConcreteType(AbstractNestedType.class, + NestedType.class); + + // Orika should be able to create an instance of FieldB abstract type + // (as we have explicitly defined above the concrete type to create and + // the SimpleConstructorResolverStrategy is normally able to create an + // instance of this concrete type) + // Therefore, the mapping should work ! + createAnInstanceOfFakeBeanAAndMapItToFakeBeanB(); + } + + private void createAnInstanceOfFakeBeanAAndMapItToFakeBeanB() { + + // Create an instance of FakeBeanA and assign a value to its fieldA + FakeBeanA fakeBeanA = new FakeBeanA(); + fakeBeanA.fieldA = 42; + + // Try the mapping from fakeBeanA to FakeBeanB + FakeBeanB fakeBeanB = mapperFactory.getMapperFacade().map(fakeBeanA, + FakeBeanB.class); + + // Assert the fieldA has been correctly mapped to fieldB.nestedField + Assert.assertEquals(fakeBeanA.fieldA, fakeBeanB.fieldB.nestedField); + } + + public static class FakeBeanA { + public int fieldA; + } + + public static class FakeBeanB { + public AbstractNestedType fieldB; + } + + public static class NestedType extends AbstractNestedType { + } + + public static abstract class AbstractNestedType { + public int nestedField; + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue90TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue90TestCase.java new file mode 100644 index 00000000..f6320066 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue90TestCase.java @@ -0,0 +1,99 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; + +import org.junit.Test; + +/** + * Simple mappings fail. + *

+ * I am trying to map type A to C, then B to C. I could reproduce with really simple classes, A, B, C being a class with a single string + * attribute named "s". + *

+ * This fails with exception "B is an unsupported source class". Looks like Orika uses the first converter: it expects A and gets B instead. + *

+ * The exception goes away when I explicitly register the mappings A->C, B->C. This is tedious because this forces me to register all + * possible mappings (a lot in my case!) during initialization. + *

+ * Please check out attached test case. + *

+ * I could reproduce the issue with Orika 1.4.1 and 1.4.2-SNAPSHOT. + *

+ * + * @see https://code.google.com/archive/p/orika/ + * + */ +public class Issue90TestCase { + + public static class A { + + private final String s; + + public A(String s) { + this.s = s; + } + + public String getS() { + return s; + } + } + + public static class B { + + private final String s; + + public B(String s) { + this.s = s; + } + public String getS() { + return s; + } + } + + public static class C { + + private final String s; + + public C(String s) { + this.s = s; + } + public String getS() { + return s; + } + } + + @Test + public void reproduce() throws Exception { + final MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build(); + + // Uncomment registers below to workaround the problem... + //mapperFactory.classMap(A.class, C.class).byDefault().register(); + //mapperFactory.classMap(B.class, C.class).byDefault().register(); + + final MapperFacade mapper = mapperFactory.getMapperFacade(); + A a = new A("foo"); + C c = mapper.map(a, C.class); + B b = new B("bar"); + c = mapper.map(b, C.class); // This one fails + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue91Test.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue91Test.java new file mode 100644 index 00000000..1856ff2f --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue91Test.java @@ -0,0 +1,76 @@ +package ma.glasnost.orika.test.community; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.OrikaSystemProperties; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.assertNotNull; + +/** + * No concrete class mapping defined error mapping a list of interfaces. + *

+ * + * @see https://github.com/orika-mapper/orika/issues + */ +public class Issue91Test { + + private MapperFacade mapperFacade; + + @Before + public void setUp() throws Exception { + System.setProperty(OrikaSystemProperties.WRITE_SOURCE_FILES,"true"); + final MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build(); + mapperFacade = mapperFactory.getMapperFacade(); + } + + @Test + public void test() { + A a = new A(); + B b = new C(); + b.setName("pippo"); + a.getList().add(b); + + A out = mapperFacade.map(a, A.class); + + assertNotNull(out); + } + + public static class A { + + private List list = new ArrayList<>(); + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } + } + + public static class C implements B { + + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + } + + public interface B { + String getName(); + void setName(String name); + } +} + diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue92TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue92TestCase.java new file mode 100644 index 00000000..cf287254 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue92TestCase.java @@ -0,0 +1,108 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import java.util.HashMap; + +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +/** + * NPE when mapping a class implementing a map. + *

+ * + * @see https://code.google.com/archive/p/orika/ + * + */ +public class Issue92TestCase { + + private MapperFactory factory; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + } + + @AfterClass + public static void tearDownAfterClass() throws Exception { + } + + @Before + public void setUp() throws Exception { + factory = new DefaultMapperFactory.Builder().build(); + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void test() { + factory.classMap(CustomMap.class, CustomClass.class).field("id", "id").register(); + CustomMap customMap = new CustomMap(); + customMap.setId("test"); + CustomClass customClass = factory.getMapperFacade().map(customMap, CustomClass.class); + assertThat(customClass.getId(),is(equalTo(customMap.getId()))); + } + + static public class CustomMap extends HashMap { + private String id; + + /** + * @return the id + */ + public final String getId() { + return id; + } + + /** + * @param id the id to set + */ + public final void setId(String id) { + this.id = id; + } + } + + static public class CustomClass { + private String id; + + /** + * @return the id + */ + public final String getId() { + return id; + } + + /** + * @param id the id to set + */ + public final void setId(String id) { + this.id = id; + } + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue98TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue98TestCase.java new file mode 100644 index 00000000..4adc5f5d --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue98TestCase.java @@ -0,0 +1,211 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.ConfigurableMapper; +import org.junit.Test; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.assertEquals; + +/** + * ClassCastException when mapping list of subtypes. + *

+ * + * @see https://code.google.com/archive/p/orika/ + * + */ +public class Issue98TestCase { + + @Test + public void testMixedPaymentListMapping() throws Exception { + CardPayment card = new CardPayment(); + card.setAmount(BigDecimal.TEN); + card.setAuthorization("1234"); + + CashPayment cash = new CashPayment(); + cash.setAmount(BigDecimal.ONE); + + List list = new ArrayList<>(); + list.add(card); + list.add(cash); + List dtos = new CustomMapper().mapAsList(list, PaymentDTO.class); + + int numCardPayments = 0; + int numCashPayments = 0; + for (PaymentDTO paymentDTO : dtos) { + if (paymentDTO instanceof CardPaymentDTO) + numCardPayments++; + else if (paymentDTO instanceof CashPaymentDTO) + numCashPayments++; + } + + assertEquals(1, numCardPayments); + assertEquals(1, numCashPayments); + + } + + @Test + public void testUnmixedPaymentListMapping() throws Exception { + CardPayment card = new CardPayment(); + card.setAmount(BigDecimal.TEN); + card.setAuthorization("1234"); + + CardPayment card2 = new CardPayment(); + card2.setAmount(BigDecimal.ONE); + card2.setAuthorization("4321"); + + List list = new ArrayList<>(); + list.add(card); + list.add(card2); + List dtos = new CustomMapper().mapAsList(list, PaymentDTO.class); + + int numCardPayments = 0; + int numCashPayments = 0; + for (PaymentDTO paymentDTO : dtos) { + if (paymentDTO instanceof CardPaymentDTO) + numCardPayments++; + else if (paymentDTO instanceof CashPaymentDTO) + numCashPayments++; + } + + assertEquals(2, numCardPayments); + assertEquals(0, numCashPayments); + + } + + public static abstract class Payment implements Serializable { + /** + * + */ + private static final long serialVersionUID = 1L; + private BigDecimal amount; + + public BigDecimal getAmount() { + return amount; + } + + public void setAmount(BigDecimal amount) { + this.amount = amount; + } + } + + public static class CardPayment extends Payment { + /** + * + */ + private static final long serialVersionUID = 1L; + private String authorization; + + public String getAuthorization() { + return authorization; + } + + public void setAuthorization(String authorization) { + this.authorization = authorization; + } + } + + public static class CashPayment extends Payment { + /** + * + */ + private static final long serialVersionUID = 1L; + private String description; + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + } + + public static abstract class PaymentDTO implements Serializable { + /** + * + */ + private static final long serialVersionUID = 1L; + private BigDecimal amount; + + public BigDecimal getAmount() { + return amount; + } + + public void setAmount(BigDecimal amount) { + this.amount = amount; + } + } + + public static class CardPaymentDTO extends PaymentDTO { + /** + * + */ + private static final long serialVersionUID = 1L; + private String authorization; + + public String getAuthorization() { + return authorization; + } + + public void setAuthorization(String authorization) { + this.authorization = authorization; + } + } + + public static class CashPaymentDTO extends PaymentDTO { + /** + * + */ + private static final long serialVersionUID = 1L; + private String description; + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + } + + public class CustomMapper extends ConfigurableMapper { + + @Override + protected void configure(MapperFactory factory) { + + super.configure(factory); + + factory.classMap(PaymentDTO.class, Payment.class).byDefault().register(); + + factory.classMap(CashPaymentDTO.class, CashPayment.class).use(PaymentDTO.class, Payment.class).byDefault().register(); + + factory.classMap(CardPaymentDTO.class, CardPayment.class).use(PaymentDTO.class, Payment.class).byDefault().register(); + + } + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/Issue99Test.java b/core/src/test/java/ma/glasnost/orika/test/community/Issue99Test.java new file mode 100644 index 00000000..c3f9f005 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/Issue99Test.java @@ -0,0 +1,81 @@ +package ma.glasnost.orika.test.community; + +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.converter.builtin.DateToStringConverter; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import org.junit.Test; + +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; + +import static org.junit.Assert.assertEquals; + +/** + * Registering map with multiple converters does not work. + *

+ * + * @see https://github.com/orika-mapper/orika/issues + */ +public class Issue99Test { + @Test + public void testDateMapping() throws Exception { + MapperFactory mapperFactory = new DefaultMapperFactory.Builder().mapNulls(false).useAutoMapping(false).build(); + + DateToStringConverter dateConverter1 = new DateToStringConverter("yyyy-MM-dd"); + DateToStringConverter dateConverter2 = new DateToStringConverter("yyyy-MM-dd kk:mm:ss"); + mapperFactory.getConverterFactory().registerConverter("yyyy-MM-dd", dateConverter1); + mapperFactory.getConverterFactory().registerConverter("yyyy-MM-dd kk:mm:ss", dateConverter2); + + mapperFactory.classMap(A.class, B.class) + .fieldMap("dateA1", "dateB1").converter("yyyy-MM-dd").add() + .fieldMap("dateA2", "dateB2").converter("yyyy-MM-dd kk:mm:ss").add() + .register(); + + A a = new A(); + a.setDateA1(Calendar.getInstance().getTime()); + a.setDateA2("2015-12-30 10:26:33"); + B b = new B(); + + mapperFactory.getMapperFacade().map(a, b); + + assertEquals(b.getDateB1(), new SimpleDateFormat("yyyy-MM-dd").format(a.getDateA1())); + assertEquals(b.getDateB2(), new SimpleDateFormat("yyyy-MM-dd kk:mm:ss").parse(a.getDateA2())); + } + + public class A { + private Date dateA1; // map to string + private String dateA2; // map from string to date + + public Date getDateA1() { + return dateA1; + } + public void setDateA1(Date dateA1) { + this.dateA1 = dateA1; + } + public String getDateA2() { + return dateA2; + } + public void setDateA2(String dateA2) { + this.dateA2 = dateA2; + } + } + + public class B { + private String dateB1; + private Date dateB2; + + public String getDateB1() { + return dateB1; + } + public void setDateB1(String dateB1) { + this.dateB1 = dateB1; + } + public Date getDateB2() { + return dateB2; + } + public void setDateB2(Date dateB2) { + this.dateB2 = dateB2; + } + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/IssueArrayToListTestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/IssueArrayToListTestCase.java new file mode 100755 index 00000000..e15ed52c --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/IssueArrayToListTestCase.java @@ -0,0 +1,178 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import org.junit.Test; + +import java.util.List; + +import static java.util.Arrays.asList; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +public class IssueArrayToListTestCase { + + public static class A { + String[] strings; + + int[] ints; + + Integer[] integers; + + public String[] getStrings() { + return strings; + } + + public void setStrings(String[] strings) { + this.strings = strings; + } + + public int[] getInts() { + return ints; + } + + public void setInts(int[] ints) { + this.ints = ints; + } + + public Integer[] getIntegers() { + return integers; + } + + public void setIntegers(Integer[] integers) { + this.integers = integers; + } + } + + public static class B { + List strings; + + List integers; + + public List getStrings() { + return strings; + } + + public void setStrings(List strings) { + this.strings = strings; + } + + public List getIntegers() { + return integers; + } + + public void setIntegers(List integers) { + this.integers = integers; + } + } + + @Test + public void testStringArrayToListOfString() { + MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build(); + + MapperFacade mapperFacade = mapperFactory.getMapperFacade(); + + A a = new A(); + a.setStrings(new String[] { "4" }); + + B b = mapperFacade.map(a, B.class); + assertEquals(asList("4"), b.getStrings()); + } + + @Test + public void testListOfStringToStringArray() { + MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build(); + + MapperFacade mapperFacade = mapperFactory.getMapperFacade(); + + B b = new B(); + b.setStrings(asList("5")); + + A a = mapperFacade.map(b, A.class); + assertArrayEquals(new String[] { "5" }, a.getStrings()); + } + + @Test + public void testIntArrayToListOfInteger() { + MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build(); + + mapperFactory.classMap(A.class, B.class).field("ints", "integers").byDefault().register(); + + MapperFacade mapperFacade = mapperFactory.getMapperFacade(); + + A a = new A(); + a.setInts(new int[] { 4 }); + + B b = mapperFacade.map(a, B.class); + assertNotNull(b.getIntegers()); + assertEquals(1, b.getIntegers().size()); + assertEquals(Integer.class, b.getIntegers().get(0).getClass()); + assertEquals(Integer.valueOf(4), b.getIntegers().get(0)); + } + + @Test + public void testListOfIntegerToIntArray() { + MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build(); + + mapperFactory.classMap(A.class, B.class).field("ints", "integers").byDefault().register(); + + MapperFacade mapperFacade = mapperFactory.getMapperFacade(); + + B b = new B(); + b.setIntegers(asList(6)); + + A a = mapperFacade.map(b, A.class); + assertArrayEquals(new int[] { 6 }, a.getInts()); + } + + @Test + public void testIntegerArrayToListOfInteger() { + MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build(); + + MapperFacade mapperFacade = mapperFactory.getMapperFacade(); + + A a = new A(); + a.setIntegers(new Integer[] { 4 }); + + B b = mapperFacade.map(a, B.class); + assertNotNull(b.getIntegers()); + assertEquals(1, b.getIntegers().size()); + assertEquals(Integer.class, b.getIntegers().get(0).getClass()); + assertEquals(Integer.valueOf(4), b.getIntegers().get(0)); + } + + @Test + public void testListOfIntegerToIntegerArray() { + MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build(); + + MapperFacade mapperFacade = mapperFactory.getMapperFacade(); + + B b = new B(); + b.setIntegers(asList(7)); + + A a = mapperFacade.map(b, A.class); + assertArrayEquals(new Integer[] { 7 }, a.getIntegers()); + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/JaxbElementTestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/JaxbElementTestCase.java new file mode 100644 index 00000000..6418ca50 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/JaxbElementTestCase.java @@ -0,0 +1,193 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import ma.glasnost.orika.CustomConverter; +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.ObjectFactory; +import ma.glasnost.orika.impl.ConfigurableMapper; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.metadata.TypeBuilder; +import ma.glasnost.orika.metadata.TypeFactory; +import org.junit.Assert; +import org.junit.Test; + +import javax.xml.bind.JAXBElement; +import javax.xml.namespace.QName; + +public class JaxbElementTestCase { + + /** + * Fake JAXB element... + * + * @param + */ + public static class MockJAXBElement { + private T value; + + public T getValue() { + return value; + } + + public void setValue(T value) { + this.value = value; + } + } + + public static class ActorDTO { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + public static class PersonDTO extends ActorDTO { + } + + public static class InstitutionDTO extends ActorDTO { + } + + public static class EventDTO { + MockJAXBElement actor; // actor.getValue() returns + + public MockJAXBElement getActor() { + return actor; + } + + public void setActor(MockJAXBElement actor) { + this.actor = actor; + } + + } + + public static class Actor { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + public static class ActorHolder { + public Actor actor; + } + + public static class ActorDTOHolder { + public JAXBElement actor; + } + + /** + * Encapsulate the configuration in your own reusable mapper + * + */ + public static class MyMapper extends ConfigurableMapper { + + public static class EventConverter extends CustomConverter { + + private final MapperFacade mapper; + private final Type typeOf_ActorDTO = new TypeBuilder() { + }.build(); + + public EventConverter(MapperFacade mapper) { + this.mapper = mapper; + } + + public Actor convert(EventDTO source, Type destinationType, MappingContext context) { + return mapper.map(source.getActor().getValue(), typeOf_ActorDTO, destinationType, context); + } + } + + public void configure(MapperFactory factory) { + factory.getConverterFactory().registerConverter(new EventConverter(this)); + } + + } + + @Test + public void testJaxbElement() { + + MapperFacade mapper = new MyMapper(); + + EventDTO event = new EventDTO(); + MockJAXBElement element = new MockJAXBElement<>(); + PersonDTO person = new PersonDTO(); + person.setName("Chuck Testa"); + element.setValue(person); + event.setActor(element); + + Actor actor = mapper.map(event, Actor.class); + + Assert.assertNotNull(actor); + Assert.assertEquals(person.getName(), actor.getName()); + + InstitutionDTO institution = new InstitutionDTO(); + institution.setName("Vermin Supreme"); + element.setValue(institution); + + actor = mapper.map(event, Actor.class); + + Assert.assertNotNull(actor); + Assert.assertEquals(institution.getName(), actor.getName()); + } + + public static class JaxbTypeFactory implements ObjectFactory> { + + public JAXBElement create(Object source, MappingContext mappingContext) { + if (source instanceof Actor) { + return new JAXBElement<>(new QName("http://example.com/JAXBTest", "Actor"), Actor.class, (Actor) source); + } + throw new IllegalArgumentException("source must be an Actor"); + } + } + + @Test + public void testRealJaxbElement() { + + MapperFactory factory = new DefaultMapperFactory.Builder().build(); + factory.registerObjectFactory(new JaxbTypeFactory(), new TypeBuilder>() { + }.build(), TypeFactory.valueOf(Actor.class)); + + MapperFacade mapper = factory.getMapperFacade(); + + Actor actor = new Actor(); + actor.setName("Some Body"); + ActorHolder holder = new ActorHolder(); + holder.actor = actor; + + ActorDTOHolder dest = mapper.map(holder, ActorDTOHolder.class); + + Assert.assertNotNull(dest); + Assert.assertNotNull(dest.actor); + Assert.assertEquals(dest.actor.getValue().getName(), actor.getName()); + + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/LongPathPropertyTestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/LongPathPropertyTestCase.java new file mode 100644 index 00000000..1027e8ea --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/LongPathPropertyTestCase.java @@ -0,0 +1,64 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import java.util.List; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.ConfigurableMapper; + +import org.junit.Assert; + +import org.junit.Test; + +public class LongPathPropertyTestCase { + + @Test + public void testSimpleCase() { + MapperFacade mapper = new ConfigurableMapper() { + + @Override + protected void configure(final MapperFactory factory) { + factory.classMap(A.class, D.class).field("second[0].third[0].message", "message").register(); + } + + }; + D source = new D(); + source.message = "Hello World"; + + Assert.assertEquals(source.message, mapper.map(source, A.class).second.get(0).third.get(0).message); + } + + public static class A { + public List second; + } + + public static class B { + public List third; + } + + public static class C { + public String message; + } + + public static class D { + public String message; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/MixConversionMappingTestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/MixConversionMappingTestCase.java new file mode 100644 index 00000000..ebfb66e7 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/MixConversionMappingTestCase.java @@ -0,0 +1,96 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import ma.glasnost.orika.CustomConverter; +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.test.MappingUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.util.HashSet; +import java.util.Set; + +public class MixConversionMappingTestCase { + + @Test + public void testMixMapConvert() { + + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.classMap(B.class, D.class).fieldMap("instanceSet").add().byDefault().register(); + + factory.getConverterFactory().registerConverter(new CustomConverter, Set>() { + + public Set convert(Set source, Type> destinationType, MappingContext context) { + + C c = new C(); + c.message = source.iterator().next().message + "-converted"; + + Set result = new HashSet<>(); + result.add(c); + + return result; + } + }); + + MapperFacade mapperFacade = factory.getMapperFacade(); + + B b = new B(); + A a = new A(); + + b.instanceSet = new HashSet<>(); + b.instanceSet.add(a); + a.message = "a"; + + // Converter + D d = mapperFacade.map(b, D.class); + + Assert.assertEquals("a-converted", d.instanceSet.iterator().next().message); + + // Default mapping + d.instanceSet.iterator().next().message = "c"; + b = mapperFacade.map(d, B.class); + + Assert.assertEquals("c", b.instanceSet.iterator().next().message); + } + + public static class A { + + public String message; + } + + public static class B { + + public Set instanceSet = new HashSet<>(); + } + + public static class C { + + public String message; + } + + public static class D { + + public Set instanceSet; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/NestedListToArrayTestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/NestedListToArrayTestCase.java new file mode 100644 index 00000000..ea9c9384 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/NestedListToArrayTestCase.java @@ -0,0 +1,160 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.metadata.ClassMapBuilder; +import ma.glasnost.orika.test.MappingUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +public class NestedListToArrayTestCase { + + + public static class L1 { + private List list = new ArrayList<>(); + + public final List getList() { + return list; + } + + public final void setList(final List list) { + this.list = list; + } + } + + public static class L2 { + private V2[] list; + + public final V2[] getList() { + return list; + } + + public final void setList(final V2[] list) { + this.list = list; + } + } + + public static class R1 { + private List list = new ArrayList<>(); + + public final void setList(final List list) { + this.list = list; + } + + public List getList() { + return list; + } + } + + public static class R2 { + private L2[] list; + + public final L2[] getList() { + return list; + } + + public final void setList(final L2[] list) { + this.list = list; + } + } + + public static class V1 { + public enum V1Type { + A, B + } + + private V1Type type = V1Type.A; + + public final V1Type getType() { + return type; + } + + + public final void setType(final V1Type type) { + this.type = type; + } + } + + public static class V2 { + public enum V2Type { + A, B + } + + private V2Type type = V2Type.A; + + + public final V2Type getType() { + return type; + } + + public final void setType(final V2Type type) { + this.type = type; + } + } + + + @Test + public void testMapping() { + + + MapperFactory mapperFactory = MappingUtil.getMapperFactory(); + final ClassMapBuilder builder = mapperFactory.classMap(R1.class, R2.class); + + mapperFactory.registerClassMap(builder.byDefault().toClassMap()); + + final MapperFacade facade = mapperFactory.getMapperFacade(); + + + + final R1 r1 = new R1(); + final List list = new ArrayList<>(); + final L1 l1 = new L1(); + final List v1List = new ArrayList<>(); + final V1 v1 = new V1(); + v1List.add(v1); + l1.setList(v1List); + list.add(l1); + r1.setList(list); + + final R2 r2 = facade.map(r1, R2.class); + + Assert.assertNotNull(r2); + Assert.assertNotNull(r2.getList()); + for (L2 l2: r2.getList()) { + Assert.assertNotNull(l2); + Assert.assertNotNull(l2.getList()); + for (V2 v2: l2.getList()) { + Assert.assertNotNull(v2); + Assert.assertNotNull(v2.getType()); + } + } + + Assert.assertEquals(r1.getList().get(0).getList().get(0).getType().toString(), + r2.getList()[0].getList()[0].getType().toString()); + + } + + + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/PersonMappingTestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/PersonMappingTestCase.java new file mode 100644 index 00000000..d7b96cb4 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/PersonMappingTestCase.java @@ -0,0 +1,273 @@ +package ma.glasnost.orika.test.community; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import org.junit.Test; + +import java.util.List; + +/** + * There doesn't appear to be a way to do this mapping using default behavior... + * + * @author keithroberts + * + */ +public class PersonMappingTestCase { + + /** + * RUn 3 maps, rely on engine to map per the sub type. + * Only one map appears to be retained in memory. The cache must key on the source type. + * This means you cannot have multiple maps with the same source type... + * @throws Exception + */ + //@Test + public void testMultiMap() throws Exception { + PersonHolderA holderA = new PersonHolderA(); + PersonName name = new PersonName(); + name.setFirstName("George"); + name.setLastName("Goober"); + name.setFullName("George Goober"); + name.setSuffix("II"); + holderA.setPersonNameA(name); + + name = new PersonName(); + name.setFirstName("Joe"); + name.setLastName("Poluka"); + name.setFullName("Joe Poluka"); + holderA.setPersonNameB(name); + + name = new PersonName(); + name.setFirstName("Fred"); + name.setLastName("Foo"); + name.setFullName("Fred Foo"); + holderA.setPersonNameC(name); + + MapperFactory mapperFactory = new DefaultMapperFactory.Builder() + .build(); + mapperFactory + .classMap(PersonHolderA.class, PersonHolderB.class) + .field("personNameA","persons:{getPersons()|setPersons(%s)|type=List<" + SuffixPerson.class.getCanonicalName() + ">}[0]") //suffix + //.field("personNameB","persons[1]") //full + //.field("personNameC","persons[2]") //full + .register(); + + mapperFactory + .classMap(PersonName.class, SuffixPerson.class) + .field("firstName","firstName") + .field("lastName","lastName") + .field("suffix","suffix") + .register(); + + mapperFactory + .classMap(PersonName.class, FullPerson.class) + .field("firstName","firstName") + .field("lastName","lastName") + .field("fullName","fullName") + .register(); + + //medicaidHousehold[0].householdMemberReference[0].ref:{getRef()|setRef(%s)|type=gov.cms.hix._0_1.hix_core.PersonType}.id + + MapperFacade mapper = mapperFactory.getMapperFacade(); + PersonHolderB resultType = mapper.map(holderA,PersonHolderB.class); + + System.out.println("result=" + resultType); + } + + /** + * Uses one map only. This has a problem picking up the sub class contained in the list. + * When the syntax on the EL seems correct, get a stackoverflow exception. + * @throws Exception + */ + @Test + public void testSingleMap() throws Exception { + PersonHolderA holderA = new PersonHolderA(); + PersonName name = new PersonName(); + name.setFirstName("George"); + name.setLastName("Goober"); + name.setFullName("George Goober"); + name.setSuffix("II"); + holderA.setPersonNameA(name); + + name = new PersonName(); + name.setFirstName("Joe"); + name.setLastName("Poluka"); + name.setFullName("Joe Poluka"); + holderA.setPersonNameB(name); + + name = new PersonName(); + name.setFirstName("Fred"); + name.setLastName("Foo"); + name.setFullName("Fred Foo"); + holderA.setPersonNameC(name); + + MapperFactory mapperFactory = new DefaultMapperFactory.Builder() + .build(); + mapperFactory + .classMap(PersonHolderA.class, PersonHolderB.class) + .field("personNameA.suffix","persons:{getPersons()|setPersons(%s)|type=List<" + SuffixPerson.class.getCanonicalName() + ">}[0].suffix") //suffix + .field("personNameA.firstName","persons[0].firstName") //suffix + .field("personNameA.lastName","persons[0].lastName") //suffix + .register(); + + //medicaidHousehold[0].householdMemberReference[0].ref:{getRef()|setRef(%s)|type=gov.cms.hix._0_1.hix_core.PersonType}.id + + MapperFacade mapper = mapperFactory.getMapperFacade(); + PersonHolderB resultType = mapper.map(holderA,PersonHolderB.class); + + System.out.println("result=" + resultType); + } + + public static class PersonName { + + private String firstName; + private String lastName; + + // getters/setters omitted + public String getFirstName() { + return firstName; + } + public void setFirstName(String firstName) { + this.firstName = firstName; + } + public String getLastName() { + return lastName; + } + public void setLastName(String lastName) { + this.lastName = lastName; + } + + private String fullName; + + public String getFullName() { + return fullName; + } + + public void setFullName(String fullName) { + this.fullName = fullName; + } + + private String suffix; + + public String getSuffix() { + return suffix; + } + + public void setSuffix(String suffix) { + this.suffix = suffix; + } + + + } + public static class PersonBase { + + private String firstName; + private String lastName; + + // getters/setters omitted + public String getFirstName() { + return firstName; + } + public void setFirstName(String firstName) { + this.firstName = firstName; + } + public String getLastName() { + return lastName; + } + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String toString() + { + return " firstName="+firstName+" lastName="+lastName; + } + } + + public static class FullPerson extends PersonBase { + + private String fullName; + + public String getFullName() { + return fullName; + } + + public void setFullName(String fullName) { + this.fullName = fullName; + } + + public String toString() + { + return super.toString()+" fullName="+fullName; + } + + } + + public static class SuffixPerson extends PersonBase { + + private String suffix; + + public String getSuffix() { + return suffix; + } + + public void setSuffix(String suffix) { + this.suffix = suffix; + } + + public String toString() + { + return super.toString()+" suffix="+suffix; + } + } + + public static class PersonHolderA { + + private PersonName personNameA; + private PersonName personNameB; + private PersonName personNameC; + + public PersonName getPersonNameA() { + return personNameA; + } + public void setPersonNameA(PersonName personNameA) { + this.personNameA = personNameA; + } + public PersonName getPersonNameB() { + return personNameB; + } + public void setPersonNameB(PersonName personNameB) { + this.personNameB = personNameB; + } + public PersonName getPersonNameC() { + return personNameC; + } + public void setPersonNameC(PersonName personNameC) { + this.personNameC = personNameC; + } + } + + public static class PersonHolderB { + + private List persons; + + public List getPersons() { + return persons; + } + + public void setPersons(List persons) { + this.persons = persons; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + for (PersonBase person : this.persons) + { + buffer.append(person.toString()).append("\n"); + } + return buffer.toString(); + } + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/PullRequest10TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/PullRequest10TestCase.java new file mode 100644 index 00000000..c5d9dfeb --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/PullRequest10TestCase.java @@ -0,0 +1,102 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import static org.hamcrest.Matchers.greaterThan; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.*; +import java.util.Arrays; +import java.util.List; + +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.metadata.TypeFactory; + +import org.junit.Test; + +/** + * Correctly implement compareTo contract for Type. + *

+ * + * @see https://github.com/orika-mapper/orika + */ +public class PullRequest10TestCase { + public static class Base { + } + + public static class SubType1 extends Base { + } + + public static class SubSubType11 extends SubType1 { + } + + public static class SubSubType12 extends SubType1 { + } + + public static class SubType2 extends Base { + } + + public static class SubSubType21 extends SubType2 { + } + + public static class SubSubType22 extends SubType2 { + } + + @Test + public void testClassInheritanceSorting() { + List> types = Arrays.> asList( + TypeFactory.valueOf(Base.class), + TypeFactory.valueOf(SubType1.class), + TypeFactory.valueOf(SubType2.class), + TypeFactory.valueOf(SubSubType11.class), + TypeFactory.valueOf(SubSubType12.class), + TypeFactory.valueOf(SubSubType21.class), + TypeFactory.valueOf(SubSubType22.class)); + + for (Type x : types) { + for (Type y : types) { + assertThat("sgn(x.compareTo(y)) == -sgn(y.compareTo(x)) for x=" + + x.getSimpleName() + ", y=" + y.getSimpleName(), + sgn(x.compareTo(y)), is(-sgn(y.compareTo(x)))); + + for (Type z : types) { + if (x.compareTo(y) > 0 && y.compareTo(z) > 0) { + assertThat( + "(x.compareTo(y)>0 && y.compareTo(z)>0) implies x.compareTo(z)>0 for x=" + + x.getSimpleName() + ", y=" + + y.getSimpleName() + ", z=" + + z.getSimpleName(), + x.compareTo(z), is(greaterThan(0))); + } + if (x.compareTo(y) == 0) { + assertThat( + "x.compareTo(y)==0 implies sgn(x.compareTo(z)) == sgn(y.compareTo(z)) for x=" + + x.getSimpleName() + ", y=" + + y.getSimpleName() + ", z=" + + z.getSimpleName(), + sgn(x.compareTo(z)), is(sgn(y.compareTo(z)))); + } + } + } + } + } + + private int sgn(int value) { + return Math.round(Math.signum(value)); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/PullRequest88TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/PullRequest88TestCase.java new file mode 100644 index 00000000..40bc47d1 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/PullRequest88TestCase.java @@ -0,0 +1,70 @@ +package ma.glasnost.orika.test.community; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.metadata.TypeBuilder; +import ma.glasnost.orika.test.MappingUtil; +import org.junit.Before; +import org.junit.Test; + +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import static java.util.Arrays.asList; +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.hasEntry; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; +import static org.junit.Assert.assertThat; + +/** + * Do not loose Map instance when mapping MultiOccurenceVariable to a Map. + *

+ * + * @see https://github.com/orika-mapper/orika + */ +public class PullRequest88TestCase { + public static final Type> SET = new TypeBuilder>() {}.build(); + public static final Type> MAP = new TypeBuilder>() {}.build(); + + private MapperFacade mapper; + + @Before + public void setUp() { + MapperFactory mapperFactory = MappingUtil.getMapperFactory(); + mapperFactory.classMap(SET, MAP) + .field("{name}", "{key}") + .field("{name}", "{value}") + .register(); + + mapper = mapperFactory.getMapperFacade(); + } + + @Test + public void testSetToMap() throws Exception { + Set set = new HashSet<>(asList(new A("a"), new A("b"))); + Map map = mapper.map(set, SET, MAP); + assertThat(map.keySet(), is(not(empty()))); + assertThat(map, hasEntry("a", "a")); + assertThat(map, hasEntry("b", "b")); + } + + public static class A { + private String name; + + public A(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } +} + diff --git a/core/src/test/java/ma/glasnost/orika/test/community/PullRequest8TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/PullRequest8TestCase.java new file mode 100644 index 00000000..c4f2c736 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/PullRequest8TestCase.java @@ -0,0 +1,65 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community; + +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.ObjectFactory; +import ma.glasnost.orika.impl.DefaultConstructorObjectFactory; +import ma.glasnost.orika.metadata.TypeFactory; +import ma.glasnost.orika.test.MappingUtil; +import org.junit.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.is; + +/** + * lookupObjectFactory should consider superclasses for source type. + *

+ * + * @see https://github.com/orika-mapper/orika + */ +public class PullRequest8TestCase { + public static class MySourceType { + } + + public static class MyType { + } + + public static class MyObjectFactory extends + DefaultConstructorObjectFactory { + public MyObjectFactory(Class type) { + super(type); + } + } + + @Test + public void test() { + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.registerObjectFactory( + new MyObjectFactory<>(MyType.class), + TypeFactory.valueOf(MyType.class)); + factory.registerClassMap(factory.classMap(MySourceType.class, + MyType.class).toClassMap()); + ObjectFactory myFactory = factory.lookupObjectFactory( + TypeFactory.valueOf(MyType.class), + TypeFactory.valueOf(MySourceType.class)); + assertThat(myFactory, is(instanceOf(MyObjectFactory.class))); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/collection/AbstractMapperTest.java b/core/src/test/java/ma/glasnost/orika/test/community/collection/AbstractMapperTest.java new file mode 100644 index 00000000..bada6f61 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/collection/AbstractMapperTest.java @@ -0,0 +1,29 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.collection; + +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; + +public abstract class AbstractMapperTest { + protected MapperFactory createMapperFactory() { + MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build(); + return mapperFactory; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/collection/AbstractOrder.java b/core/src/test/java/ma/glasnost/orika/test/community/collection/AbstractOrder.java new file mode 100644 index 00000000..5966bebd --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/collection/AbstractOrder.java @@ -0,0 +1,41 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.collection; + +import java.util.Collection; + +public class AbstractOrder

{ + private Collection

positions; + + // sun.reflect.generics.reflectiveObjects.TypeVariableImpl cannot be cast to + // java.lang.Class + public Collection

getPositions() { + return positions; + } + + // sun.reflect.generics.reflectiveObjects.WildcardTypeImpl cannot be cast to + // java.lang.Class + public Collection getPositionen2() { + return positions; + } + + public void setPositions(Collection

positions) { + this.positions = positions; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/collection/IPosition.java b/core/src/test/java/ma/glasnost/orika/test/community/collection/IPosition.java new file mode 100644 index 00000000..b606fd06 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/collection/IPosition.java @@ -0,0 +1,23 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.collection; + +public interface IPosition { + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/collection/MapperTest.java b/core/src/test/java/ma/glasnost/orika/test/community/collection/MapperTest.java new file mode 100644 index 00000000..878f312f --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/collection/MapperTest.java @@ -0,0 +1,59 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.collection; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class MapperTest extends AbstractMapperTest { + private MapperFacade facade; + + @Before + public void setUp() { + MapperFactory mapperFactory = createMapperFactory(); + mapperFactory.registerClassMap(mapperFactory.classMap(Order.class, OrderData.class).byDefault().toClassMap()); + mapperFactory.registerClassMap(mapperFactory.classMap(Position.class, PositionData.class).byDefault().toClassMap()); + facade = mapperFactory.getMapperFacade(); + } + + @Test + public void test() { + OrderData data = new OrderData(); + data.setName("asd"); + PositionData positionData = new PositionData(); + positionData.setNumber("1234"); + data.add(positionData); + positionData = new PositionData(); + positionData.setNumber("2345"); + data.add(positionData); + Order order = facade.map(data, Order.class); + Assert.assertEquals("asd", order.getName()); + Assert.assertEquals(2, order.getPositions().size()); + Assert.assertEquals("1234", order.getPositions().iterator().next().getNumber()); + // map it back + OrderData data2 = facade.map(order, OrderData.class); + Assert.assertEquals("asd", data2.getName()); + Assert.assertEquals(2, data2.getPositions().size()); + Assert.assertEquals("1234", data2.getPositions().iterator().next().getNumber()); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/collection/Order.java b/core/src/test/java/ma/glasnost/orika/test/community/collection/Order.java new file mode 100644 index 00000000..23292d28 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/collection/Order.java @@ -0,0 +1,31 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.collection; + +public class Order extends AbstractOrder { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/collection/OrderData.java b/core/src/test/java/ma/glasnost/orika/test/community/collection/OrderData.java new file mode 100644 index 00000000..f45a6c96 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/collection/OrderData.java @@ -0,0 +1,50 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.collection; + +import java.util.ArrayList; +import java.util.List; + +public class OrderData { + private String name; + private List positions; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getPositions() { + return positions; + } + + public void setPositions(List positions) { + this.positions = positions; + } + + public void add(PositionData data) { + if (positions == null) { + positions = new ArrayList<>(); + } + positions.add(data); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/collection/Position.java b/core/src/test/java/ma/glasnost/orika/test/community/collection/Position.java new file mode 100644 index 00000000..cd18a7ee --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/collection/Position.java @@ -0,0 +1,31 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.collection; + +public class Position implements IPosition { + private String number; + + public String getNumber() { + return number; + } + + public void setNumber(String number) { + this.number = number; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/collection/PositionData.java b/core/src/test/java/ma/glasnost/orika/test/community/collection/PositionData.java new file mode 100644 index 00000000..2179df35 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/collection/PositionData.java @@ -0,0 +1,31 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.collection; + +public class PositionData { + private String number; + + public String getNumber() { + return number; + } + + public void setNumber(String number) { + this.number = number; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue121/Issue121TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/issue121/Issue121TestCase.java new file mode 100644 index 00000000..d5f06d81 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue121/Issue121TestCase.java @@ -0,0 +1,141 @@ +package ma.glasnost.orika.test.community.issue121; + +import ma.glasnost.orika.BoundMapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.metadata.TypeFactory; +import ma.glasnost.orika.test.MappingUtil; +import ma.glasnost.orika.test.community.issue121.aobjects.AMapAObjects1; +import ma.glasnost.orika.test.community.issue121.aobjects.AObject1; +import ma.glasnost.orika.test.community.issue121.aobjects.AObject2; +import ma.glasnost.orika.test.community.issue121.bobjects.BContainerListBObject1; +import ma.glasnost.orika.test.community.issue121.bobjects.BObject1; +import ma.glasnost.orika.test.community.issue121.bobjects.BObject2Container; +import ma.glasnost.orika.test.community.issue121.util.RandomUtils; +import org.junit.Assert; +import org.junit.Test; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author: Ilya Krokhmalyov YC14IK1 + * @since: 8/23/13 + */ + +public class Issue121TestCase { + + public BoundMapperFacade getFacade(MapperFactory mapperFactory) { + return mapperFactory.getMapperFacade(AMapAObjects1.class, BContainerListBObject1.class); + } + + public AMapAObjects1 getInstance() { + Map map = new HashMap<>(); + map.put(RandomUtils.randomInt(), AObject1.instance()); + map.put(RandomUtils.randomInt(), AObject1.instance()); + map.put(RandomUtils.randomInt(), AObject1.instance()); + AMapAObjects1 instance = new AMapAObjects1(map); + return instance; + } + + @Test + public void test1() throws Throwable { + + MapperFactory mapperFactory = MappingUtil.getMapperFactory(true); + mapperFactory.classMap(AMapAObjects1.class, BContainerListBObject1.class) + .fieldAToB("map", "list").register(); + mapperFactory.classMap(TypeFactory.valueOf(Map.class, Integer.class, AObject1.class), + TypeFactory.valueOf(List.class, BObject1.class)) + // Custom mapper + .field("{key}", "{key}") + .field("{value}", "{}") + .byDefault() + .register(); + + BoundMapperFacade mapper = getFacade(mapperFactory); + + AMapAObjects1 instance = getInstance(); + BContainerListBObject1 result = mapper.map(instance); + + Assert.assertEquals("Not equals count of mapped objects", result.getList().size(), instance.size()); + Assert.assertEquals(result.getList().get(0).getKey(), instance.getMap().entrySet().iterator().next().getKey()); + // Assert in this point, because seconds class mapper + // not found + Integer firstResultId = result.getList().get(0).getId(); + Integer firstInstanceId = instance.getMap() + .entrySet().iterator().next().getValue().getId(); + Assert.assertEquals("Bug here. Value empty", firstInstanceId, firstResultId); + Assert.assertEquals(result.getList().get(0).getName(), instance.getMap().entrySet().iterator().next().getValue().getName()); + } + + @Test + public void test2() throws Throwable { + MapperFactory mapperFactory = MappingUtil.getMapperFactory(true); + + mapperFactory.classMap(AMapAObjects1.class, BContainerListBObject1.class).fieldAToB("map{value}", "list{}").register(); + mapperFactory.classMap(AObject1.class, BObject1.class).byDefault().register(); + + BoundMapperFacade mapper = getFacade(mapperFactory); + + AMapAObjects1 instance = getInstance(); + BContainerListBObject1 result = mapper.map(instance); + + Assert.assertEquals("Bug here!!! Not equals count of mapped objects. You can see, that in result only last element.", + result.getList().size(), instance.size()); + } + + @Test + public void test3() throws Throwable { + + MapperFactory mapperFactory = MappingUtil.getMapperFactory(true); + + mapperFactory.classMap(AMapAObjects1.class, BContainerListBObject1.class) + .fieldAToB("map{value}", "list{}") + .fieldAToB("map{key}", "list{key}") + .register(); + mapperFactory.classMap(AObject1.class, BObject1.class).field("list", "container.list").byDefault().register(); + + BoundMapperFacade mapper = getFacade(mapperFactory); + + AMapAObjects1 instance = getInstance(); + mapper.map(instance); + + } + + @Test + public void test4() throws Throwable { + MapperFactory mapperFactory = MappingUtil.getMapperFactory(true); + + mapperFactory.classMap(AMapAObjects1.class, BContainerListBObject1.class) + .fieldAToB("map{value}", "list{}") + .fieldAToB("map{key}", "list{key}") + .register(); + mapperFactory.classMap(AObject1.class, BObject1.class).field("list{}", "container.list{}").byDefault().register(); + + } + + @Test + public void test5() throws Throwable { + + MapperFactory mapperFactory = new DefaultMapperFactory.Builder().mapNulls(true).build(); + + mapperFactory.classMap(AMapAObjects1.class, BContainerListBObject1.class) + .fieldAToB("map{value}", "list{}") + .fieldAToB("map{key}", "list{key}") + .register(); + mapperFactory.classMap(AObject1.class, BObject1.class).field("list", "container").register(); + mapperFactory.classMap(TypeFactory.valueOf(List.class, AObject2.class), BObject2Container.class) + .field("{}", "list{}") + .byDefault() + .register(); + + BoundMapperFacade mapper = getFacade(mapperFactory); + + AMapAObjects1 instance = getInstance(); + BContainerListBObject1 result = mapper.map(instance); + + Assert.assertNotNull("Result is null", result); + Assert.assertNotNull("Inner List is null", result.getList()); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue121/aobjects/AMapAObjects1.java b/core/src/test/java/ma/glasnost/orika/test/community/issue121/aobjects/AMapAObjects1.java new file mode 100644 index 00000000..fb9e10f6 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue121/aobjects/AMapAObjects1.java @@ -0,0 +1,14 @@ +package ma.glasnost.orika.test.community.issue121.aobjects; + +import java.util.Map; + +/** + * @author: Ilya Krokhmalyov YC14IK1 + * @since: 8/23/13 + */ + +public class AMapAObjects1 extends AbstractOrderedMap { + public AMapAObjects1(Map map) { + super(map); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue121/aobjects/AObject1.java b/core/src/test/java/ma/glasnost/orika/test/community/issue121/aobjects/AObject1.java new file mode 100644 index 00000000..c11fc6e4 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue121/aobjects/AObject1.java @@ -0,0 +1,62 @@ +package ma.glasnost.orika.test.community.issue121.aobjects; + +import java.util.Arrays; +import java.util.List; + +import ma.glasnost.orika.test.community.issue121.util.RandomUtils; + +/** + * @author: Ilya Krokhmalyov YC14IK1 + * @since: 8/23/13 + */ + +public class AObject1 { + + public static AObject1 instance() { + AObject1 aObject1 = new AObject1(); + aObject1.id = RandomUtils.randomInt(); + aObject1.name = RandomUtils.randomString(); + aObject1.list = Arrays.asList(AObject2.instance(),AObject2.instance()); + return aObject1; + } + + private Integer id; + private String name; + private List list; + + public AObject1() { + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } + + @Override + public String toString() { + return "AObject1{" + + "id=" + id + + ", name='" + name + '\'' + + ", list=" + list + + '}'; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue121/aobjects/AObject2.java b/core/src/test/java/ma/glasnost/orika/test/community/issue121/aobjects/AObject2.java new file mode 100644 index 00000000..914ef9af --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue121/aobjects/AObject2.java @@ -0,0 +1,34 @@ +package ma.glasnost.orika.test.community.issue121.aobjects; + +import ma.glasnost.orika.test.community.issue121.util.RandomUtils; + +/** + * @author: Ilya Krokhmalyov YC14IK1 + * @since: 8/23/13 + */ + +public class AObject2 { + + public static AObject2 instance() { + AObject2 aObject2 = new AObject2(); + aObject2.id = RandomUtils.randomInt(); + return aObject2; + } + + private Integer id; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + @Override + public String toString() { + return "AObject2{" + + "id=" + id + + '}'; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue121/aobjects/AbstractOrderedMap.java b/core/src/test/java/ma/glasnost/orika/test/community/issue121/aobjects/AbstractOrderedMap.java new file mode 100644 index 00000000..ef67127c --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue121/aobjects/AbstractOrderedMap.java @@ -0,0 +1,64 @@ +package ma.glasnost.orika.test.community.issue121.aobjects; + +import java.io.Serializable; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + +/** + * @author: Ilya Krokhmalyov YC14IK1 + * @since: 8/23/13 + */ + +public abstract class AbstractOrderedMap implements Iterable, Serializable { + + protected final Map resultSet = new LinkedHashMap<>(); + + protected AbstractOrderedMap(Map map) { + resultSet.putAll(map); + } + + public Iterator iterator() { + return Collections.unmodifiableCollection(resultSet.values()).iterator(); + } + + public T get(K id) { + return resultSet.get(id); + } + + public T getSingle() { + if(resultSet.size() == 1) { + return resultSet.values().iterator().next(); + } else if (resultSet.size() == 0) { + return null; + } else { + throw new IllegalStateException("The operation is not allowed when collection size is greater then one"); + } + } + + public Map getMap() { + return Collections.unmodifiableMap(resultSet); + } + + public int size() { + return resultSet.size(); + } + + public boolean containsId(K id) { + return resultSet.containsKey(id); + } + + public Set idSet() { + return Collections.unmodifiableSet(resultSet.keySet()); + } + + @Override + public String toString() { + return this.getClass().getSimpleName() + "{" + + "resultSet=" + resultSet + + '}'; + } +} + diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue121/bobjects/BContainerListBObject1.java b/core/src/test/java/ma/glasnost/orika/test/community/issue121/bobjects/BContainerListBObject1.java new file mode 100644 index 00000000..3063bbf1 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue121/bobjects/BContainerListBObject1.java @@ -0,0 +1,36 @@ +package ma.glasnost.orika.test.community.issue121.bobjects; + +import java.util.List; + +/** + * @author: Ilya Krokhmalyov YC14IK1 + * @since: 8/23/13 + */ + +/** + * + * This need, for example, for REST + */ + +public class BContainerListBObject1 { + + private List list; + + public BContainerListBObject1() { + } + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } + + @Override + public String toString() { + return "BContainerListBObject1{" + + "list=" + list + + '}'; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue121/bobjects/BObject1.java b/core/src/test/java/ma/glasnost/orika/test/community/issue121/bobjects/BObject1.java new file mode 100644 index 00000000..5d9bc80a --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue121/bobjects/BObject1.java @@ -0,0 +1,55 @@ +package ma.glasnost.orika.test.community.issue121.bobjects; + +/** + * @author: Ilya Krokhmalyov YC14IK1 + * @since: 8/23/13 + */ + +public class BObject1 { + private Integer id; + private String name; + private Integer key; + private BObject2Container container; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getKey() { + return key; + } + + public void setKey(Integer key) { + this.key = key; + } + + public BObject2Container getContainer() { + return container; + } + + public void setContainer(BObject2Container container) { + this.container = container; + } + + @Override + public String toString() { + return "BObject1{" + + "id=" + id + + ", name='" + name + '\'' + + ", key=" + key + + ", container=" + container + + '}'; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue121/bobjects/BObject2.java b/core/src/test/java/ma/glasnost/orika/test/community/issue121/bobjects/BObject2.java new file mode 100644 index 00000000..b5ef9131 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue121/bobjects/BObject2.java @@ -0,0 +1,25 @@ +package ma.glasnost.orika.test.community.issue121.bobjects; + +/** + * @author: Ilya Krokhmalyov YC14IK1 + * @since: 8/23/13 + */ + +public class BObject2 { + private Integer id; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + @Override + public String toString() { + return "BObject2{" + + "id=" + id + + '}'; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue121/bobjects/BObject2Container.java b/core/src/test/java/ma/glasnost/orika/test/community/issue121/bobjects/BObject2Container.java new file mode 100644 index 00000000..14f388dc --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue121/bobjects/BObject2Container.java @@ -0,0 +1,28 @@ +package ma.glasnost.orika.test.community.issue121.bobjects; + +import java.util.List; + +/** + * @author: Ilya Krokhmalyov YC14IK1 + * @since: 8/23/13 + */ + +public class BObject2Container { + + private List list; + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } + + @Override + public String toString() { + return "BObject2Container{" + + "list=" + list + + '}'; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue121/util/RandomUtils.java b/core/src/test/java/ma/glasnost/orika/test/community/issue121/util/RandomUtils.java new file mode 100644 index 00000000..98e3c85e --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue121/util/RandomUtils.java @@ -0,0 +1,28 @@ +package ma.glasnost.orika.test.community.issue121.util; + +import java.util.Random; + +/** + * @author: Ilya Krokhmalyov YC14IK1 + * @since: 8/23/13 + */ + +public class RandomUtils { + private static final Random random = new Random(); + + public static int randomInt() { + return random.nextInt(); + } + + public static String randomString() { + String candidateChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + StringBuilder sb = new StringBuilder(); + Random random = new Random(); + for (int i = 0; i < 10; i++) { + sb.append(candidateChars.charAt(random.nextInt(candidateChars + .length()))); + } + + return sb.toString(); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue131/Issue131Test.java b/core/src/test/java/ma/glasnost/orika/test/community/issue131/Issue131Test.java new file mode 100644 index 00000000..82abdba8 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue131/Issue131Test.java @@ -0,0 +1,112 @@ +package ma.glasnost.orika.test.community.issue131; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.test.MappingUtil; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +/** + * Property types are not correctly resolved from generic interfaces. + *

+ * + * @see https://github.com/orika-mapper/orika/issues + * + */ +public class Issue131Test { + + private MapperFacade mapper; + + public static class A { + private List content; + + public List getContent() { + return content; + } + + public void setContent(List content) { + this.content = content; + } + } + + public interface TB { + Collection getContent(); + + void setContent(Collection content); + } + + public interface BStrings extends TB { + } + + public interface BLongs extends TB { + } + + public static class ConcreteBStrings implements BStrings { + private Collection content; + + public Collection getContent() { + return content; + } + + public void setContent(Collection content) { + this.content = content; + } + } + + public static class ConcreteBLongs implements BLongs { + private Collection content; + + @Override + public Collection getContent() { + return content; + } + + @Override + public void setContent(Collection content) { + this.content = content; + } + } + + @Before + public void setup() { + MapperFactory mapperFactory = MappingUtil.getMapperFactory(); + mapperFactory.classMap(A.class, TB.class).byDefault().register(); + mapperFactory.classMap(A.class, BStrings.class).byDefault().register(); + mapperFactory.classMap(A.class, BLongs.class).byDefault().register(); + mapperFactory.registerConcreteType(BStrings.class, ConcreteBStrings.class); + mapperFactory.registerConcreteType(BLongs.class, ConcreteBLongs.class); + + mapper = mapperFactory.getMapperFacade(); + } + + @Test + public void testCase() { + A a = new A(); + a.setContent(Arrays.asList(1L, 2L, 3L)); + BLongs longs = mapper.map(a, BLongs.class); + assertElementOfType(longs.getContent(), Long.class); + + BStrings strings = mapper.map(a, BStrings.class); + assertElementOfType(strings.getContent(), String.class); + + } + + private static void assertElementOfType(Collection collection, Class expectedType) { + assertThat(collection, is(not(empty()))); + for (Object e : collection) { + Class elementType = e.getClass(); + Assert.assertTrue("element '" + e + "' should be assignable to '" + expectedType + " but is of " + elementType, + expectedType.isAssignableFrom(elementType)); + } + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue135/Domain.java b/core/src/test/java/ma/glasnost/orika/test/community/issue135/Domain.java new file mode 100644 index 00000000..f59255de --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue135/Domain.java @@ -0,0 +1,45 @@ +package ma.glasnost.orika.test.community.issue135; + +public class Domain { + + private SubA subA; + + private SubB subB; + + private int primitive; + private boolean active; + + public SubA getSubA() { + return subA; + } + + public void setSubA(SubA subA) { + this.subA = subA; + } + + public SubB getSubB() { + return subB; + } + + public void setSubB(SubB subB) { + this.subB = subB; + } + + public int getPrimitive() { + return primitive; + } + + public void setPrimitive(int primtive) { + this.primitive = primtive; + } + + public boolean isActive() { + return active; + } + + public void setActive(boolean active) { + this.active = active; + } + + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue135/Issue135Test.java b/core/src/test/java/ma/glasnost/orika/test/community/issue135/Issue135Test.java new file mode 100644 index 00000000..2c834dee --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue135/Issue135Test.java @@ -0,0 +1,36 @@ +package ma.glasnost.orika.test.community.issue135; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.test.MappingUtil; + +public class Issue135Test { + + private MapperFacade mapper; + + @Before + public void setup() { + MapperFactory mapperFactory = MappingUtil.getMapperFactory(); + mapperFactory.classMap(Domain.class, Representation.class) + .mapNulls(true) + .mapNullsInReverse(true) + .field("subB", "repA.repB") // this causes NPE if repA is null + .field("active", "repA.active") + .field("primitive", "repA.primitive") + .register(); + + mapper = mapperFactory.getMapperFacade(); + } + + @Test + public void testCase(){ + Domain src = new Domain(); + //throws NPE + Representation target = mapper.map(src, Representation.class); + Assert.assertNotNull(target); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue135/RepA.java b/core/src/test/java/ma/glasnost/orika/test/community/issue135/RepA.java new file mode 100644 index 00000000..1ee1ec92 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue135/RepA.java @@ -0,0 +1,45 @@ +package ma.glasnost.orika.test.community.issue135; + +public class RepA { + + private String id; + private int primitive; + private Boolean active; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + private RepB repB; + + public RepB getRepB() { + return repB; + } + + public void setRepB(RepB repB) { + this.repB = repB; + } + + public int getPrimitive() { + return primitive; + } + + public void setPrimitive(int primtive) { + this.primitive = primtive; + } + + public Boolean getActive() { + return active; + } + + public void setActive(Boolean active) { + this.active = active; + } + + + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue135/RepB.java b/core/src/test/java/ma/glasnost/orika/test/community/issue135/RepB.java new file mode 100644 index 00000000..cf8267bd --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue135/RepB.java @@ -0,0 +1,15 @@ +package ma.glasnost.orika.test.community.issue135; + +public class RepB { + + private String id; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue135/Representation.java b/core/src/test/java/ma/glasnost/orika/test/community/issue135/Representation.java new file mode 100644 index 00000000..efbb55fe --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue135/Representation.java @@ -0,0 +1,14 @@ +package ma.glasnost.orika.test.community.issue135; + +public class Representation { + + private RepA repA; + + public RepA getRepA() { + return repA; + } + + public void setRepA(RepA repA) { + this.repA = repA; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue135/SubA.java b/core/src/test/java/ma/glasnost/orika/test/community/issue135/SubA.java new file mode 100644 index 00000000..c62595d8 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue135/SubA.java @@ -0,0 +1,15 @@ +package ma.glasnost.orika.test.community.issue135; + +public class SubA { + + private String id; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue135/SubB.java b/core/src/test/java/ma/glasnost/orika/test/community/issue135/SubB.java new file mode 100644 index 00000000..12011b24 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue135/SubB.java @@ -0,0 +1,15 @@ +package ma.glasnost.orika.test.community.issue135; + +public class SubB { + + private String id; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue137/CustomFactory.java b/core/src/test/java/ma/glasnost/orika/test/community/issue137/CustomFactory.java new file mode 100644 index 00000000..371900ba --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue137/CustomFactory.java @@ -0,0 +1,35 @@ +package ma.glasnost.orika.test.community.issue137; + +import java.lang.reflect.Constructor; + +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.ObjectFactory; + +/** + * Created with IntelliJ IDEA. + * User: tgruenheit + * Date: 06.12.13 + * Time: 20:13 + * To change this template use File | Settings | File Templates. + */ +public class CustomFactory implements ObjectFactory { + + public T create( Object o, MappingContext mappingContext ){ + + //FIXME: While converting second LevelTwo object, resolvedDestinationType is LevelThree + @SuppressWarnings("unchecked") + Class rawType = (Class) mappingContext.getResolvedDestinationType().getRawType(); + + try { + + Constructor declaredConstructor = rawType.getDeclaredConstructor(); + declaredConstructor.setAccessible( true ); + + return declaredConstructor.newInstance(); + + } catch (Exception e) { + throw new RuntimeException( e ); + } + + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue137/LevelOne.java b/core/src/test/java/ma/glasnost/orika/test/community/issue137/LevelOne.java new file mode 100644 index 00000000..dd598a9e --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue137/LevelOne.java @@ -0,0 +1,23 @@ +package ma.glasnost.orika.test.community.issue137; + +import java.util.Set; + +/** + * Created with IntelliJ IDEA. + * User: tgruenheit + * Date: 06.12.13 + * Time: 19:34 + * To change this template use File | Settings | File Templates. + */ +public class LevelOne { + + private Set levelTwos; + + public Set getLevelTwos() { + return levelTwos; + } + + public void setLevelTwos(Set levelTwos) { + this.levelTwos = levelTwos; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue137/LevelTest.java b/core/src/test/java/ma/glasnost/orika/test/community/issue137/LevelTest.java new file mode 100644 index 00000000..8828d5d8 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue137/LevelTest.java @@ -0,0 +1,47 @@ +package ma.glasnost.orika.test.community.issue137; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.metadata.TypeFactory; +import org.junit.Test; + +import java.util.HashSet; + +/** + * Created with IntelliJ IDEA. + * User: tgruenheit + * Date: 06.12.13 + * Time: 19:36 + * To change this template use File | Settings | File Templates. + */ +public class LevelTest { + + @Test + public void orikaTest() { + + MapperFactory factory = new DefaultMapperFactory.Builder().build(); + + factory.registerObjectFactory(new CustomFactory<>(), TypeFactory.valueOf( LevelOne.class ) ); + factory.registerObjectFactory(new CustomFactory<>(), TypeFactory.valueOf( LevelTwo.class ) ); + factory.registerObjectFactory(new CustomFactory<>(), TypeFactory.valueOf( LevelThree.class ) ); + + LevelOne levelOne = new LevelOne(); + + levelOne.setLevelTwos(new HashSet<>() ); + + for( int i=0; i < 2; i++ ){ + LevelTwo two = new LevelTwo(); + two.setLevelThreeValue( new LevelThree() ); + + levelOne.getLevelTwos().add( two ); + } + + MapperFacade mapperFacade = factory.getMapperFacade(); + + LevelOne mapped = mapperFacade.map(levelOne, LevelOne.class); + + System.out.println( mapped ); + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue137/LevelThree.java b/core/src/test/java/ma/glasnost/orika/test/community/issue137/LevelThree.java new file mode 100644 index 00000000..153d3e30 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue137/LevelThree.java @@ -0,0 +1,23 @@ +package ma.glasnost.orika.test.community.issue137; + +import java.util.UUID; + +/** + * Created with IntelliJ IDEA. + * User: tgruenheit + * Date: 06.12.13 + * Time: 19:34 + * To change this template use File | Settings | File Templates. + */ +public class LevelThree { + + private String someValue = UUID.randomUUID().toString(); + + public String getSomeValue() { + return someValue; + } + + public void setSomeValue(String someValue) { + this.someValue = someValue; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue137/LevelTwo.java b/core/src/test/java/ma/glasnost/orika/test/community/issue137/LevelTwo.java new file mode 100644 index 00000000..f2a926ae --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue137/LevelTwo.java @@ -0,0 +1,21 @@ +package ma.glasnost.orika.test.community.issue137; + +/** + * Created with IntelliJ IDEA. + * User: tgruenheit + * Date: 06.12.13 + * Time: 19:34 + * To change this template use File | Settings | File Templates. + */ +public class LevelTwo { + + private LevelThree levelThreeValue; + + public LevelThree getLevelThreeValue() { + return levelThreeValue; + } + + public void setLevelThreeValue(LevelThree levelThreeValue) { + this.levelThreeValue = levelThreeValue; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue148/Issue148Test.java b/core/src/test/java/ma/glasnost/orika/test/community/issue148/Issue148Test.java new file mode 100644 index 00000000..9b713156 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue148/Issue148Test.java @@ -0,0 +1,119 @@ +package ma.glasnost.orika.test.community.issue148; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.test.MappingUtil; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.Collection; +import java.util.Collections; + +public class Issue148Test { + + private MapperFacade mapper; + + public class Category { + + private String name; + + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + } + public interface Categorized { + Collection getCategories(); + + void setCategories(Collection categories); + } + + public static class Product implements Categorized { + private Collection categories; + private String test; + + @Override + public Collection getCategories() { + return categories; + } + + @Override + public void setCategories(Collection categories) { + this.categories = categories; + } + + public String getTest() { + return test; + } + + public void setTest(String test) { + this.test = test; + } + } + + public interface TagSet { + Collection getTags(); + void setTags(Collection tags); + } + + public static class ItemTag { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + public static class Item implements TagSet { + private Collection tags; + private String test; + + @Override + public Collection getTags() { + return tags; + } + + @Override + public void setTags(Collection tags) { + this.tags = tags; + } + + public String getTest() { + return test; + } + + public void setTest(String test) { + this.test = test; + } + } + + @Before + public void setup() { + MapperFactory mapperFactory = MappingUtil.getMapperFactory(); + mapperFactory.classMap(Categorized.class, TagSet.class).field("categories", "tags").byDefault().register(); + mapperFactory.classMap(Category.class, ItemTag.class).byDefault().register(); + mapperFactory.classMap(Product.class, Item.class).byDefault().register(); + + mapper = mapperFactory.getMapperFacade(); + } + + @Test + public void testCase() { + Product product = new Product(); + Category category = new Category(); + category.setName("test"); + product.setCategories(Collections.singleton(category)); + Item b = mapper.map(product, Item.class); + + Assert.assertNotNull(b.getTags()); + Assert.assertEquals("test", b.getTags().iterator().next().getName()); + } + +} \ No newline at end of file diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue20/BaseDto.java b/core/src/test/java/ma/glasnost/orika/test/community/issue20/BaseDto.java new file mode 100644 index 00000000..ba88294c --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue20/BaseDto.java @@ -0,0 +1,83 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue20; + +import java.io.Serializable; + +/** + * @author Dmitriy Khomyakov + * @author matt.deboer@gmail.com + */ +public abstract class BaseDto implements Serializable { + /** + * + */ + private static final long serialVersionUID = 1L; + + private Long id; + + private Long version; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getVersion() { + return version; + } + + public void setVersion(Long version) { + this.version = version; + } + + public boolean isNew() { + return id == null; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + + if (o == null || (getClass() != o.getClass())) + return false; + + BaseDto that = (BaseDto) o; + + if (isNew()) { + return this == that; + } else { + return id.equals(that.id); + } + + } + + @Override + public int hashCode() { + return id != null ? id.hashCode() : 0; + } + + @Override + public String toString() { + return "BaseDto{" + "id=" + id + ", version=" + version + '}'; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue20/BaseEntity.java b/core/src/test/java/ma/glasnost/orika/test/community/issue20/BaseEntity.java new file mode 100644 index 00000000..799b4bae --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue20/BaseEntity.java @@ -0,0 +1,100 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue20; + +import org.hibernate.proxy.HibernateProxy; + +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.MappedSuperclass; +import javax.persistence.Transient; +import javax.persistence.Version; + +/** + * @author Dmitriy Khomyakov + * @author matt.deboer@gmail.com + */ +@MappedSuperclass +public abstract class BaseEntity { + private Long id; + + private Long version; + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + @Version + public Long getVersion() { + return version; + } + + public void setVersion(Long version) { + this.version = version; + } + + @Transient + public boolean isNew() { + return id == null; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + + if (o instanceof HibernateProxy) { + return o.equals(this); + } + + if (o == null || (getClass() != o.getClass())) { + return false; + } + + + BaseEntity that = (BaseEntity) o; + + if (isNew()) { + return this == that; + } else { + return id.equals(that.id); + } + + } + + @Override + public int hashCode() { + return id != null ? id.hashCode() : 0; + } + + @Override + public String toString() { + return "BaseEntity{" + + "id=" + id + + ", version=" + version + + '}'; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue20/User.java b/core/src/test/java/ma/glasnost/orika/test/community/issue20/User.java new file mode 100644 index 00000000..b9a93262 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue20/User.java @@ -0,0 +1,86 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue20; + + + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; + +/** + * @author Dmitriy Khomyakov + * @author matt.deboer@gmail.com + */ +@Entity +public class User extends BaseEntity { + private UsrGroup group; + private String name; + private String password; + + public User(String name) { + this(name, name); + } + + public User(String name, String password) { + this.name = name; + this.password = password; + } + + public User() { + } + + + public void setName(String name) { + this.name = name; + } + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn + public UsrGroup getGroup() { + return group; + } + + public void setGroup(UsrGroup group) { + this.group = group; + } + + @Column(unique = true) + public String getName() { + return name; + } + + + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + @Override + public String toString() { + return "User{" + + "name='" + name + '\'' + + "} " + super.toString(); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue20/UserDto.java b/core/src/test/java/ma/glasnost/orika/test/community/issue20/UserDto.java new file mode 100644 index 00000000..028caae8 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue20/UserDto.java @@ -0,0 +1,64 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue20; + +/** + * @author Dmitriy Khomyakov + * @author matt.deboer@gmail.com + */ +public class UserDto extends BaseDto { + + /** + * + */ + private static final long serialVersionUID = 1L; + private String name; + // private String password; + private UserGroupDto group; + + public UserDto() { + } + + public UserDto(String name, UserGroupDto group) { + this.name = name; + this.group = group; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public UserGroupDto getGroup() { + return group; + } + + public void setGroup(UserGroupDto group) { + this.group = group; + } + + @Override + public String toString() { + return "UserDto{" + "name='" + name + '\'' + + // ", password='" + password + '\'' + + "} " + super.toString(); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue20/UserGroupDto.java b/core/src/test/java/ma/glasnost/orika/test/community/issue20/UserGroupDto.java new file mode 100644 index 00000000..d6310c54 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue20/UserGroupDto.java @@ -0,0 +1,60 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue20; + +import java.util.Set; + +/** + * @author Dmitriy Khomyakov + * @author matt.deboer@gmail.com + */ +public class UserGroupDto extends BaseDto { + /** + * + */ + private static final long serialVersionUID = 1L; + private String name; + private Set users; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Set getUsers() { + return users; + } + + public void setUsers(Set users) { + this.users = users; + } + + public void addUser(UserDto user) { + getUsers().add(user); + user.setGroup(this); + } + + @Override + public String toString() { + return "UserGroupDto{" + "name='" + name + '\'' + ", users=" + users + + "} " + super.toString(); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue20/UserInfo.java b/core/src/test/java/ma/glasnost/orika/test/community/issue20/UserInfo.java new file mode 100644 index 00000000..0d077bdb --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue20/UserInfo.java @@ -0,0 +1,43 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue20; + +/** + * @author Dmitriy Khomyakov + * @author matt.deboer@gmail.com + */ +public class UserInfo extends BaseDto { + /** + * + */ + private static final long serialVersionUID = 1L; + private String name; + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + @Override + public String toString() { + return "UserInfo{" + "name='" + name + '\'' + "} " + super.toString(); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue20/UsrGroup.java b/core/src/test/java/ma/glasnost/orika/test/community/issue20/UsrGroup.java new file mode 100644 index 00000000..6a6b89ef --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue20/UsrGroup.java @@ -0,0 +1,83 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue20; + +import javax.persistence.Entity; +import javax.persistence.JoinColumn; +import javax.persistence.OneToMany; +import java.util.HashSet; +import java.util.Set; + +/** + * @author Dmitriy Khomyakov + * @author matt.deboer@gmail.com + */ +@Entity +public class UsrGroup extends BaseEntity { + private String name; + private String caption; + private Set users; + + public UsrGroup() { + } + + + public UsrGroup(String name) { + this.name = name; + users = new HashSet<>(); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getCaption() { + return caption; + } + + public void setCaption(String caption) { + this.caption = caption; + } + + @OneToMany + @JoinColumn + public Set getUsers() { + return users; + } + + public void setUsers(Set users) { + this.users = users; + } + + public void addUser(User user){ + getUsers().add(user); + user.setGroup(this); + } + + @Override + public String toString() { + return "UserGroup{" + + "name='" + name + '\'' + + ", caption='" + caption + '\'' + + "} " + super.toString(); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue21/Authority.java b/core/src/test/java/ma/glasnost/orika/test/community/issue21/Authority.java new file mode 100644 index 00000000..9ad160da --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue21/Authority.java @@ -0,0 +1,87 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue21; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.ManyToMany; +import java.util.HashSet; +import java.util.Set; + +/** + * + * @author Dmitriy Khomyakov + * @author matt.deboer@gmail.com + */ +@Entity +public class Authority extends BaseEntity { + private String name; + private String caption; + private Set children; + + public Authority() { + } + + public Authority(String name) { + this.name = name; + children = new HashSet<>(); + } + + @Column(unique = true) + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getCaption() { + return caption; + } + + public void setCaption(String caption) { + this.caption = caption; + } + + + + + @ManyToMany + public Set getChildren() { + return children; + } + + public void addChild(Authority authority){ + children.add(authority); + } + + public void setChildren(Set children) { + this.children = children; + } + + @Override + public String toString() { + return "Authority{" + + "name='" + name + '\'' + + ", caption='" + caption + '\'' + + "} " + super.toString(); + } +} + + diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue21/AuthorityDto.java b/core/src/test/java/ma/glasnost/orika/test/community/issue21/AuthorityDto.java new file mode 100644 index 00000000..791eed4e --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue21/AuthorityDto.java @@ -0,0 +1,67 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue21; + +import java.util.Set; + +/** +* +* @author Dmitriy Khomyakov +* @author matt.deboer@gmail.com +*/ +public class AuthorityDto extends BaseDto { + private String caption; + + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + private Set children; + + + public String getCaption() { + return caption; + } + + public void setCaption(String caption) { + this.caption = caption; + } + + public Set getChildren() { + return children; + } + + public void setChildren(Set children) { + this.children = children; + } + + + + @Override + public String toString() { + return "AuthorityDto{" + + "caption='" + caption + '\'' + + "} " + super.toString(); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue21/BaseDto.java b/core/src/test/java/ma/glasnost/orika/test/community/issue21/BaseDto.java new file mode 100644 index 00000000..13799e46 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue21/BaseDto.java @@ -0,0 +1,84 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue21; + +import java.io.Serializable; + +/** + * + * @author Dmitriy Khomyakov + * @author matt.deboer@gmail.com + */ +public abstract class BaseDto implements Serializable { + /** + * + */ + private static final long serialVersionUID = 1L; + + private Long id; + + private Long version; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getVersion() { + return version; + } + + public void setVersion(Long version) { + this.version = version; + } + + public boolean isNew() { + return id == null; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + + if (o == null || (getClass() != o.getClass())) + return false; + + BaseDto that = (BaseDto) o; + + if (isNew()) { + return this == that; + } else { + return id.equals(that.id); + } + + } + + @Override + public int hashCode() { + return id != null ? id.hashCode() : 0; + } + + @Override + public String toString() { + return "BaseDto{" + "id=" + id + ", version=" + version + '}'; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue21/BaseEntity.java b/core/src/test/java/ma/glasnost/orika/test/community/issue21/BaseEntity.java new file mode 100644 index 00000000..8258a277 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue21/BaseEntity.java @@ -0,0 +1,97 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue21; + +import org.hibernate.proxy.HibernateProxy; + +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.MappedSuperclass; +import javax.persistence.Transient; +import javax.persistence.Version; + +/** + * + * @author Dmitriy Khomyakov + * @author matt.deboer@gmail.com + */ +@MappedSuperclass +public abstract class BaseEntity { + private Long id; + + private Long version; + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + @Version + public Long getVersion() { + return version; + } + + public void setVersion(Long version) { + this.version = version; + } + + @Transient + public boolean isNew() { + return id == null; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + + if (o instanceof HibernateProxy) { + return o.equals(this); + } + + if (o == null || (getClass() != o.getClass())) { + return false; + } + + BaseEntity that = (BaseEntity) o; + + if (isNew()) { + return this == that; + } else { + return id.equals(that.id); + } + + } + + @Override + public int hashCode() { + return id != null ? id.hashCode() : 0; + } + + @Override + public String toString() { + return "BaseEntity{" + "id=" + id + ", version=" + version + '}'; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue21/User.java b/core/src/test/java/ma/glasnost/orika/test/community/issue21/User.java new file mode 100644 index 00000000..b2c67454 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue21/User.java @@ -0,0 +1,92 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue21; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToMany; +import javax.persistence.ManyToOne; +import java.util.Set; + +/** + * + * @author Dmitriy Khomyakov + * @author matt.deboer@gmail.com + */ +@Entity +public class User extends BaseEntity { + private UserGroup group; + private String name; + private String password; + private Set authorities; + + public User(String name) { + this(name, name); + } + + public User(String name, String password) { + this.name = name; + this.password = password; + } + + public User() { + } + + public void setName(String name) { + this.name = name; + } + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn + public UserGroup getGroup() { + return group; + } + + public void setGroup(UserGroup group) { + this.group = group; + } + + @Column(unique = true) + public String getName() { + return name; + } + + public void setAuthorities(Set authorities) { + this.authorities = authorities; + } + + @ManyToMany + public Set getAuthorities() { + return authorities; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + @Override + public String toString() { + return "User{" + "name='" + name + '\'' + "} " + super.toString(); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue21/UserDto.java b/core/src/test/java/ma/glasnost/orika/test/community/issue21/UserDto.java new file mode 100644 index 00000000..1b89f28f --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue21/UserDto.java @@ -0,0 +1,73 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue21; + +import java.util.Set; + +/** + * + * @author Dmitriy Khomyakov + * @author matt.deboer@gmail.com + */ +public class UserDto extends BaseDto { + + private String name; + // private String password; + private UserGroupDto group; + + private Set authorities; + + public UserDto() { + } + + public UserDto(String name, UserGroupDto group) { + this.name = name; + this.group = group; + } + + public Set getAuthorities() { + return authorities; + } + + public void setAuthorities(Set authorities) { + this.authorities = authorities; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public UserGroupDto getGroup() { + return group; + } + + public void setGroup(UserGroupDto group) { + this.group = group; + } + + @Override + public String toString() { + return "UserDto{" + "name='" + name + '\'' + + // ", password='" + password + '\'' + + "} " + super.toString(); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue21/UserGroup.java b/core/src/test/java/ma/glasnost/orika/test/community/issue21/UserGroup.java new file mode 100644 index 00000000..25ed4a01 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue21/UserGroup.java @@ -0,0 +1,86 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue21; + +import javax.persistence.Entity; +import javax.persistence.JoinColumn; +import javax.persistence.OneToMany; +import java.util.HashSet; +import java.util.Set; + +/** + * + * @author Dmitriy Khomyakov + * @author matt.deboer@gmail.com + */ +@Entity +public class UserGroup extends BaseEntity { + private String name; + private String caption; + private Set users; + + public UserGroup() { + } + + public UserGroup(String name) { + this.name = name; + users = new HashSet<>(); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getCaption() { + return caption; + } + + public void setCaption(String caption) { + this.caption = caption; + } + + @OneToMany + @JoinColumn + public Set getUsers() { + return users; + } + + public void setUsers(Set users) { + this.users = users; + } + + public void removeUser(User user) { + getUsers().remove(user); + user.setGroup(null); + } + + public void addUser(User user) { + getUsers().add(user); + user.setGroup(this); + } + + @Override + public String toString() { + return "UserGroup{" + "name='" + name + '\'' + ", caption='" + caption + + '\'' + "} " + super.toString(); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue21/UserGroupDto.java b/core/src/test/java/ma/glasnost/orika/test/community/issue21/UserGroupDto.java new file mode 100644 index 00000000..9638baf6 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue21/UserGroupDto.java @@ -0,0 +1,62 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue21; + +import java.util.Set; + +/** + * + * @author Dmitriy Khomyakov + * @author matt.deboer@gmail.com + */ +public class UserGroupDto extends BaseDto { + private String name; + private Set users; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Set getUsers() { + return users; + } + + public void setUsers(Set users) { + this.users = users; + } + + public void addUser(UserDto user) { + getUsers().add(user); + user.setGroup(this); + } + + public void removeUser(UserDto user) { + getUsers().remove(user); + user.setGroup(this); + } + + @Override + public String toString() { + return "UserGroupDto{" + "name='" + name + '\'' + ", users=" + users + + "} " + super.toString(); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue21/UserInfo.java b/core/src/test/java/ma/glasnost/orika/test/community/issue21/UserInfo.java new file mode 100644 index 00000000..4f879841 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue21/UserInfo.java @@ -0,0 +1,42 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue21; + +/** +* +* @author Dmitriy Khomyakov +* @author matt.deboer@gmail.com +*/ +public class UserInfo extends BaseDto { + private String name; + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + @Override + public String toString() { + return "UserInfo{" + + "name='" + name + '\'' + + "} " + super.toString(); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue25/AddressMergingMapper.java b/core/src/test/java/ma/glasnost/orika/test/community/issue25/AddressMergingMapper.java new file mode 100644 index 00000000..d84b0b20 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue25/AddressMergingMapper.java @@ -0,0 +1,73 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue25; + +import ma.glasnost.orika.CustomMapper; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.test.community.issue25.modelA.Address; +import ma.glasnost.orika.test.community.issue25.modelB.AddressDTO; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class AddressMergingMapper extends + CustomMapper, List> { + + public void mapAtoB(List

a, List b, + MappingContext context) { + merge(a, b, context); + } + + public void mapBtoA(List b, List
a, + MappingContext context) { + mapperFacade.mapAsCollection(b, a, Address.class, context); + } + + private List merge( + List
srcAddress, + List dstAddressesDTO, + MappingContext context) { + Set savedIdNumbers = new HashSet<>( + srcAddress.size()); + for (Address currentAddress : srcAddress) { + AddressDTO foundAddressDTO = findEntity(dstAddressesDTO, + currentAddress.getIdNumber()); + if (foundAddressDTO == null) { + dstAddressesDTO.add(mapperFacade.map(currentAddress, + AddressDTO.class, context)); + } else { + mapperFacade.map(currentAddress, foundAddressDTO, context); + } + savedIdNumbers.add(currentAddress.getIdNumber()); + } + dstAddressesDTO.removeIf(vCurrentAnschriftDTO -> !savedIdNumbers.contains(vCurrentAnschriftDTO + .getIdNumber())); + return dstAddressesDTO; + } + + private AddressDTO findEntity(List dstAddressDTO, + Long aIdnumber) { + for (AddressDTO vCurrentDTO : dstAddressDTO) { + if (aIdnumber.equals(vCurrentDTO.getIdNumber())) { + return vCurrentDTO; + } + } + return null; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue25/BaseManufacturingFacilityTest.java b/core/src/test/java/ma/glasnost/orika/test/community/issue25/BaseManufacturingFacilityTest.java new file mode 100644 index 00000000..e3698692 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue25/BaseManufacturingFacilityTest.java @@ -0,0 +1,98 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue25; + +import ma.glasnost.orika.test.community.issue25.modelA.Address; +import ma.glasnost.orika.test.community.issue25.modelA.ManufacturingFacility; +import ma.glasnost.orika.test.community.issue25.modelB.AddressDTO; +import ma.glasnost.orika.test.community.issue25.modelB.ManufacturingFacilityDTS; +import org.junit.After; +import org.junit.Before; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public abstract class BaseManufacturingFacilityTest { + + protected static final String MANUFACTURINGFACILITY_KEY = "ManufacturingFacility"; + protected static final String MANUFACTURINGFACILITYDTS_KEY = "ManufacturingFacilityDTS"; + + public BaseManufacturingFacilityTest() { + } + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + public Map getManufacturingFacility(Long aIdNumber, String aDescription){ + Map vReturnMap = new HashMap<>(); + + ManufacturingFacility vManufacturingFacility = new ManufacturingFacility(); + vManufacturingFacility.setDescription(aDescription); + vReturnMap.put(MANUFACTURINGFACILITY_KEY, vManufacturingFacility); + + ManufacturingFacilityDTS vBetriebsstaetteDTS = new ManufacturingFacilityDTS(); + vBetriebsstaetteDTS.setDescription(aDescription); + vBetriebsstaetteDTS.setIdNumber(aIdNumber); + vReturnMap.put(MANUFACTURINGFACILITYDTS_KEY, vBetriebsstaetteDTS); + + return vReturnMap; + } + + + public void addAddressToManufacturingFacility(Map betriebsstaetteMap, + Long idNumber, + String street, + Long postalcode, + String comment, + Character land){ + ManufacturingFacility manufacturingFacility = (ManufacturingFacility)betriebsstaetteMap.get(MANUFACTURINGFACILITY_KEY); + ManufacturingFacilityDTS manufacturingFacilityDTS = (ManufacturingFacilityDTS)betriebsstaetteMap.get(MANUFACTURINGFACILITYDTS_KEY); + + Address vAnschrift = new Address(); + vAnschrift.setIdNumber(idNumber); + vAnschrift.setStreet(street); + vAnschrift.setPostalcode(postalcode); + + if(manufacturingFacility.getAddresses()==null) + manufacturingFacility.setAddresses(new ArrayList<>()); + List
anschriften = manufacturingFacility.getAddresses(); + anschriften.add(vAnschrift); + + + AddressDTO vAnschriftDTO = new AddressDTO(); + vAnschriftDTO.setComment(comment); + vAnschriftDTO.setIdNumber(idNumber); + vAnschriftDTO.setLand(land); + vAnschriftDTO.setPostalcode(postalcode); + vAnschriftDTO.setStreet(street); + + if(manufacturingFacilityDTS.getAddressL()==null){ + manufacturingFacilityDTS.setAddressL(new ArrayList<>()); + } + List anschriftenDTO = manufacturingFacilityDTS.getAddressL(); + anschriftenDTO.add(vAnschriftDTO); + } +} + diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue25/CustomOrikaMapper.java b/core/src/test/java/ma/glasnost/orika/test/community/issue25/CustomOrikaMapper.java new file mode 100644 index 00000000..602bb507 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue25/CustomOrikaMapper.java @@ -0,0 +1,59 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue25; + +import java.util.ArrayList; +import java.util.List; + +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.converter.ConverterFactory; +import ma.glasnost.orika.impl.ConfigurableMapper; +import ma.glasnost.orika.metadata.TypeBuilder; +import ma.glasnost.orika.test.community.issue25.modelA.Address; +import ma.glasnost.orika.test.community.issue25.modelA.ManufacturingFacility; +import ma.glasnost.orika.test.community.issue25.modelB.AddressDTO; +import ma.glasnost.orika.test.community.issue25.modelB.ManufacturingFacilityDTS; + +public class CustomOrikaMapper extends ConfigurableMapper { + + @Override + public void configure(MapperFactory mapperFactory) { + + mapperFactory.registerMapper(new AddressMergingMapper()); + mapperFactory.registerConcreteType(new TypeBuilder>(){}.build(), + new TypeBuilder>(){}.build()); + mapperFactory.registerConcreteType(new TypeBuilder>(){}.build(), + new TypeBuilder>(){}.build()); + + ConverterFactory converterFactory = mapperFactory.getConverterFactory(); + //Add converters... + + mapperFactory.registerClassMap(mapperFactory.classMap(ManufacturingFacility.class, ManufacturingFacilityDTS.class ) + .fieldMap("description" , "manufacturingfacility.description").add() + .fieldMap("addresses","addressL").add() + .toClassMap() + ); + + mapperFactory.registerClassMap(mapperFactory.classMap(Address.class, AddressDTO.class ) + .fieldMap("idNumber", "idNumber").add() + .fieldMap("street", "street").add() + .fieldMap("postalcode", "postalcode").add() + .toClassMap() + ); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue25/modelA/Address.java b/core/src/test/java/ma/glasnost/orika/test/community/issue25/modelA/Address.java new file mode 100644 index 00000000..b52fb6e0 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue25/modelA/Address.java @@ -0,0 +1,76 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue25.modelA; + + +import java.util.Objects; + +public class Address { + + private Long idNumber = null; + private String street = null; + private Long postalcode = null; + + public Address() { + super(); + } + + public String getStreet() { + return street; + } + + public void setStreet(String street) { + this.street = street; + } + + public Long getPostalcode() { + return postalcode; + } + + public void setPostalcode(Long postalcode) { + this.postalcode = postalcode; + } + + public Long getIdNumber() { + return idNumber; + } + + public void setIdNumber(Long idNumber) { + this.idNumber = idNumber; + } + + @Override + public boolean equals(Object other){ + if (other == this) return true; + if (other == null) return false; + if (getClass() != other.getClass()) return false; + + Address anschrift = (Address)other; + + return Objects.equals(street, anschrift.street) && + Objects.equals(postalcode, anschrift.postalcode) && + Objects.equals(idNumber, anschrift.idNumber); + } + + @Override + public int hashCode(){ + return (this.street == null ? 10 : street.hashCode()) ^ + (this.postalcode == null ? 11 : postalcode.hashCode()^ + (this.idNumber == null ? 11 : idNumber.hashCode())); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue25/modelA/ManufacturingFacility.java b/core/src/test/java/ma/glasnost/orika/test/community/issue25/modelA/ManufacturingFacility.java new file mode 100644 index 00000000..5d71beac --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue25/modelA/ManufacturingFacility.java @@ -0,0 +1,76 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue25.modelA; + +import ma.glasnost.orika.test.community.issue25.modelB.ManufacturingFacilityDTS; + +import java.util.List; +import java.util.Objects; + + +public class ManufacturingFacility { + + // If an entity is read from database this property is set for merging. + private ManufacturingFacilityDTS prototype; + private List
addresses; + private String description; + + // START read instance + public ManufacturingFacilityDTS returnPrototype(){ + return this.prototype; + } + + public void putPrototype(ManufacturingFacilityDTS prototype){ + this.prototype = prototype; + } + // END read instance + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public List
getAddresses() { + return addresses; + } + + public void setAddresses(List
addresses) { + this.addresses = addresses; + } + + @Override + public boolean equals(Object other){ + + if (other == this) return true; + if (other == null) return false; + if (getClass() != other.getClass()) return false; + ManufacturingFacility betriebsstaette = (ManufacturingFacility)other; + + return Objects.equals(description, betriebsstaette.description) && + Objects.equals(addresses, betriebsstaette.addresses); + } + + @Override + public int hashCode() { + return (this.description == null ? 17 : description.hashCode()); + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue25/modelB/AddressDTO.java b/core/src/test/java/ma/glasnost/orika/test/community/issue25/modelB/AddressDTO.java new file mode 100644 index 00000000..2a374b9d --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue25/modelB/AddressDTO.java @@ -0,0 +1,68 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue25.modelB; + +import java.io.Serializable; + +public class AddressDTO implements Serializable { + + /** + * + */ + private static final long serialVersionUID = -8573731692897972845L; + + private Long idNumber; + private String street = null; + private Long postalcode = null; + private String comment = null; + private Character land = null; + public Long getIdNumber() { + return idNumber; + } + public void setIdNumber(Long idNumber) { + this.idNumber = idNumber; + } + public String getStreet() { + return street; + } + public void setStreet(String street) { + this.street = street; + } + public Long getPostalcode() { + return postalcode; + } + public void setPostalcode(Long postalcode) { + this.postalcode = postalcode; + } + public String getComment() { + return comment; + } + public void setComment(String comment) { + this.comment = comment; + } + public Character getLand() { + return land; + } + public void setLand(Character land) { + this.land = land; + } + + + + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue25/modelB/ManufacturingFacilityDTO.java b/core/src/test/java/ma/glasnost/orika/test/community/issue25/modelB/ManufacturingFacilityDTO.java new file mode 100644 index 00000000..7a9a1f0f --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue25/modelB/ManufacturingFacilityDTO.java @@ -0,0 +1,53 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue25.modelB; + +import java.io.Serializable; + + +public class ManufacturingFacilityDTO implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 4949602104392727453L; + + private String description; + private Long idNumber; + + public ManufacturingFacilityDTO(){ + + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Long getIdNumber() { + return idNumber; + } + + public void setIdNumber(Long idNumber) { + this.idNumber = idNumber; + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue25/modelB/ManufacturingFacilityDTS.java b/core/src/test/java/ma/glasnost/orika/test/community/issue25/modelB/ManufacturingFacilityDTS.java new file mode 100644 index 00000000..1bf6aff3 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue25/modelB/ManufacturingFacilityDTS.java @@ -0,0 +1,63 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue25.modelB; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +public class ManufacturingFacilityDTS implements Serializable { + + /** + * + */ + private static final long serialVersionUID = -1917745131193055771L; + + private ManufacturingFacilityDTO manufacturingfacility; + private List addressL; + + public ManufacturingFacilityDTO getManufacturingfacility() { + return (manufacturingfacility==null)? manufacturingfacility = new ManufacturingFacilityDTO():this.manufacturingfacility; + } + public void setManufacturingfacility(ManufacturingFacilityDTO manufacturingfacility) { + this.manufacturingfacility = manufacturingfacility; + } + public List getAddressL() { + return (addressL == null ? addressL = new ArrayList<>() : addressL); + } + public void setAddressL(List addressL) { + this.addressL = addressL; + } + + public String getDescription() { + return getManufacturingfacility().getDescription(); + } + + public void setDescription(String description) { + getManufacturingfacility().setDescription(description); + } + + public Long getIdNumber() { + return getManufacturingfacility().getIdNumber(); + } + + public void setIdNumber(Long idNumber) { + getManufacturingfacility().setIdNumber(idNumber); + } +} + diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue26/AbstractEntity.java b/core/src/test/java/ma/glasnost/orika/test/community/issue26/AbstractEntity.java new file mode 100644 index 00000000..92b4620c --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue26/AbstractEntity.java @@ -0,0 +1,38 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue26; + +public abstract class AbstractEntity { + private ID entityID; + + public AbstractEntity() { /* Required by Orika mapping */ + this(null); + } + + public AbstractEntity(ID entityID) { + this.entityID = entityID; + } + + public ID getEntityID() { + return entityID; + } + + public void setEntityID(ID entityID) { + this.entityID = entityID; + } +} \ No newline at end of file diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue26/AbstractOrderID.java b/core/src/test/java/ma/glasnost/orika/test/community/issue26/AbstractOrderID.java new file mode 100644 index 00000000..a8f66bc5 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue26/AbstractOrderID.java @@ -0,0 +1,76 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue26; + +public abstract class AbstractOrderID { + private static final long serialVersionUID = 2L; + + private Long bestellungID; + + public Long getID() { + return bestellungID; + } + + public AbstractOrderID() { /* Required by Orika mapping */ + this(null); + } + + public AbstractOrderID(Long bestellungID) { + this.bestellungID = bestellungID; + } + + public AbstractOrderID(long bestellungID) { + this.bestellungID = bestellungID; + } + + public Long getBestellungID() { + return bestellungID; + } + + public void setBestellungID(Long bestellungID) { + this.bestellungID = bestellungID; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((bestellungID == null) ? 0 : bestellungID.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + AbstractOrderID other = (AbstractOrderID) obj; + if (bestellungID == null) { + if (other.bestellungID != null) + return false; + } else if (!bestellungID.equals(other.bestellungID)) + return false; + return true; + } + + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue26/Order.java b/core/src/test/java/ma/glasnost/orika/test/community/issue26/Order.java new file mode 100644 index 00000000..b0b756ec --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue26/Order.java @@ -0,0 +1,30 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue26; + +public final class Order extends AbstractEntity { + private static final long serialVersionUID = 1L; + + public Order() { + this(null); + } + + public Order(OrderID id) { + super(id); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue26/OrderData.java b/core/src/test/java/ma/glasnost/orika/test/community/issue26/OrderData.java new file mode 100644 index 00000000..046be56d --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue26/OrderData.java @@ -0,0 +1,40 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue26; + +import java.io.Serializable; + +public class OrderData implements Serializable { + private static final long serialVersionUID = 1L; + private Long orderId; + + public OrderData() { + } + + public OrderData(Long Id) { + this.orderId = Id; + } + + public Long getOrderId() { + return orderId; + } + + public void setOrderId(Long Id) { + this.orderId = Id; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue26/OrderID.java b/core/src/test/java/ma/glasnost/orika/test/community/issue26/OrderID.java new file mode 100644 index 00000000..31691987 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue26/OrderID.java @@ -0,0 +1,36 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue26; + +public class OrderID extends AbstractOrderID { + + private static final long serialVersionUID = 1L; + + public OrderID() { /* Required by Orika mapping */ + this(null); + } + + public OrderID(Long orderID) { + super(orderID); + } + + public OrderID(long orderID) { + super(orderID); + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue26/OrderIDConverter.java b/core/src/test/java/ma/glasnost/orika/test/community/issue26/OrderIDConverter.java new file mode 100644 index 00000000..04cc0a4b --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue26/OrderIDConverter.java @@ -0,0 +1,35 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue26; + +import ma.glasnost.orika.CustomConverter; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.metadata.Type; + +public class OrderIDConverter extends CustomConverter { + + /* + * (non-Javadoc) + * + * @see ma.glasnost.orika.Converter#convert(java.lang.Object, + * ma.glasnost.orika.metadata.Type) + */ + public OrderID convert(Long source, Type destinationType, MappingContext context) { + return new OrderID(source); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue28/AbstractOrder.java b/core/src/test/java/ma/glasnost/orika/test/community/issue28/AbstractOrder.java new file mode 100644 index 00000000..21383faf --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue28/AbstractOrder.java @@ -0,0 +1,36 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue28; + +public abstract class AbstractOrder> extends PositionContainer { + private static final long serialVersionUID = 3L; + + private final Long number; + + public AbstractOrder() { + this(null); + } + + public AbstractOrder(Long number) { + this.number = number; + } + + public Long getId() { + return number; + } +} \ No newline at end of file diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue28/Order.java b/core/src/test/java/ma/glasnost/orika/test/community/issue28/Order.java new file mode 100644 index 00000000..e995af76 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue28/Order.java @@ -0,0 +1,39 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue28; + +public class Order extends AbstractOrder { + private static final long serialVersionUID = 1L; + private int customerNumber; + + public Order() { + this(null); + } + + public Order(Long id) { + super(id); + } + + public int getCustomerNumber() { + return customerNumber; + } + + public void setCustomerNumber(int customerNumber) { + this.customerNumber = customerNumber; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue28/OrderData.java b/core/src/test/java/ma/glasnost/orika/test/community/issue28/OrderData.java new file mode 100644 index 00000000..cd2d83d2 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue28/OrderData.java @@ -0,0 +1,40 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue28; + +import java.io.Serializable; + +public class OrderData implements Serializable { + private static final long serialVersionUID = 1L; + private Long number; + + public OrderData() { + } + + public OrderData(Long number) { + this.number = number; + } + + public Long getNumber() { + return number; + } + + public void setNumber(Long number) { + this.number = number; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue28/Position.java b/core/src/test/java/ma/glasnost/orika/test/community/issue28/Position.java new file mode 100644 index 00000000..3aa8b1b4 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue28/Position.java @@ -0,0 +1,30 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue28; + +public class Position { + private T order; + + public T getOrder() { + return order; + } + + public void setOrder(T order) { + this.order = order; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue28/PositionContainer.java b/core/src/test/java/ma/glasnost/orika/test/community/issue28/PositionContainer.java new file mode 100644 index 00000000..a4cbde4e --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue28/PositionContainer.java @@ -0,0 +1,32 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue28; + +import java.util.Collection; + +public abstract class PositionContainer { + private Collection> positions; + + public Collection> getPositions() { + return positions; + } + + public void setPositions(Collection> positions) { + this.positions = positions; + } +} \ No newline at end of file diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue41/MyEnum.java b/core/src/test/java/ma/glasnost/orika/test/community/issue41/MyEnum.java new file mode 100644 index 00000000..6fb1ae4e --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue41/MyEnum.java @@ -0,0 +1,22 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue41; + +public enum MyEnum { + one, two +} \ No newline at end of file diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue41/MyEnumConverter.java b/core/src/test/java/ma/glasnost/orika/test/community/issue41/MyEnumConverter.java new file mode 100644 index 00000000..334b1110 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue41/MyEnumConverter.java @@ -0,0 +1,36 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue41; + +import ma.glasnost.orika.CustomConverter; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.metadata.Type; + +public class MyEnumConverter extends CustomConverter { + + public MyEnum convert(String source, Type destinationType, MappingContext context) { + if ("un".equals(source)) { + return MyEnum.one; + } + + if ("deux".equals(source)) { + return MyEnum.two; + } + return null; + } +} \ No newline at end of file diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue41/MySourceObject.java b/core/src/test/java/ma/glasnost/orika/test/community/issue41/MySourceObject.java new file mode 100644 index 00000000..27ea4e65 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue41/MySourceObject.java @@ -0,0 +1,30 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue41; + +public class MySourceObject { + private String e; + + public String getE() { + return e; + } + + public void setE(String e) { + this.e = e; + } +} \ No newline at end of file diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue41/MyTargetObject.java b/core/src/test/java/ma/glasnost/orika/test/community/issue41/MyTargetObject.java new file mode 100644 index 00000000..e3684977 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue41/MyTargetObject.java @@ -0,0 +1,40 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue41; + + +public class MyTargetObject { + private MyTargetSubObject sub; + private MyEnum directE; + + public MyEnum getDirectE() { + return directE; + } + + public void setDirectE(MyEnum directE) { + this.directE = directE; + } + + public MyTargetSubObject getSub() { + return sub; + } + + public void setSub(MyTargetSubObject sub) { + this.sub = sub; + } +} \ No newline at end of file diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue41/MyTargetSubObject.java b/core/src/test/java/ma/glasnost/orika/test/community/issue41/MyTargetSubObject.java new file mode 100644 index 00000000..51dfc3c7 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue41/MyTargetSubObject.java @@ -0,0 +1,40 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue41; + +public class MyTargetSubObject { + private MyEnum e; + + private String s; + + public String getS() { + return s; + } + + public void setS(String s) { + this.s = s; + } + + public MyEnum getE() { + return e; + } + + public void setE(MyEnum e) { + this.e = e; + } +} \ No newline at end of file diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue42/InheritanceTestcase.java b/core/src/test/java/ma/glasnost/orika/test/community/issue42/InheritanceTestcase.java new file mode 100644 index 00000000..fc1eca66 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue42/InheritanceTestcase.java @@ -0,0 +1,145 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue42; + +import ma.glasnost.orika.CustomMapper; +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.metadata.ClassMapBuilder; +import org.junit.Assert; +import org.junit.Test; + +public class InheritanceTestcase { + + @Test + public void testInheritance() { + + MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build(); + + mapperFactory.registerClassMap(mapperFactory.classMap(BaseEntity.class, BaseEntityDto.class).byDefault().toClassMap()); + + ClassMapBuilder userClassMapBuilder = mapperFactory.classMap(BaseUser.class, BaseUserDto.class); + userClassMapBuilder.customize(new CustomMapper() { + @Override + public void mapAtoB(BaseUser a, BaseUserDto b, MappingContext mappingContext) { + b.setName(a.getName() + " [mapped from BaseUser to BaseUserDto]"); + } + + @Override + public void mapBtoA(BaseUserDto b, BaseUser a, MappingContext mappingContext) { + a.setName(b.getName() + " [mapped from BaseUserDto to BaseUser]"); + } + }); + mapperFactory.registerClassMap(userClassMapBuilder.use(BaseEntity.class, BaseEntityDto.class).byDefault().toClassMap()); + + mapperFactory.registerClassMap(mapperFactory.classMap(Customer.class, CustomerDto.class) + .use(BaseUser.class, BaseUserDto.class) + .byDefault() + .toClassMap()); + + MapperFacade mapperFacade = mapperFactory.getMapperFacade(); + + Customer customer = new Customer(); + customer.setId(1234L); + customer.setName("Customer Name"); + customer.setEmail("test@test.org"); + + CustomerDto customerDto = mapperFacade.map(customer, CustomerDto.class); + + Customer c = mapperFacade.map(customerDto, Customer.class); + + Assert.assertEquals(customer.getEmail(), c.getEmail()); + Assert.assertEquals(customer.getId(), c.getId()); + + } + + public static class BaseEntity { + protected Long id; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + } + + public static class BaseUser extends BaseEntity { + protected String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + public static class Customer extends BaseUser { + protected String email; + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + } + + public static class BaseEntityDto { + protected Long id; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + } + + public static class BaseUserDto extends BaseEntityDto { + protected String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + public static class CustomerDto extends BaseUserDto { + protected String email; + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue91/VectorTestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/issue91/VectorTestCase.java new file mode 100644 index 00000000..7e7b81bf --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue91/VectorTestCase.java @@ -0,0 +1,77 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue91; + +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import org.junit.Assert; +import org.junit.Test; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import java.util.Vector; + +public class VectorTestCase { + private final MapperFactory factory = new DefaultMapperFactory.Builder().build(); + + @Test + public void test() { + + factory.classMap(XTrade.class, Trade.class) + .fieldMap("fees").bElementType(Fee.class).add() + .byDefault() + .register(); + + XTrade xtrade = new XTrade(); + XFee xfee = new XFee(); + xfee.amount = BigDecimal.valueOf(34.95); + xfee.description = "ATM Fee"; + xtrade.fees.add(xfee); + xfee = new XFee(); + xfee.amount = BigDecimal.valueOf(250.00); + xfee.description = "Cable Bill"; + xtrade.fees.add(xfee); + + Trade trade = factory.getMapperFacade().map(xtrade, Trade.class); + Assert.assertEquals(2, trade.fees.size()); + Assert.assertEquals(xtrade.fees.get(0).amount, ((Fee) trade.fees.get(0)).amount); + Assert.assertEquals(xtrade.fees.get(0).description, ((Fee) trade.fees.get(0)).description); + Assert.assertEquals(xtrade.fees.get(1).amount, ((Fee) trade.fees.get(1)).amount); + Assert.assertEquals(xtrade.fees.get(1).description, ((Fee) trade.fees.get(1)).description); + } + + public static class XTrade { + public List fees = new ArrayList<>(); + } + + public static class XFee { + public BigDecimal amount; + public String description; + } + + public static class Trade { + public Vector fees = new Vector(); + } + + public static class Fee { + public BigDecimal amount; + public String description; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue94/OrikaTestNulls.java b/core/src/test/java/ma/glasnost/orika/test/community/issue94/OrikaTestNulls.java new file mode 100644 index 00000000..d314b2d9 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue94/OrikaTestNulls.java @@ -0,0 +1,174 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue94; + +import java.util.Date; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.metadata.ClassMapBuilder; +import ma.glasnost.orika.test.MappingUtil; + +import org.junit.Assert; +import org.junit.Test; + +public class OrikaTestNulls { + + + + public static class ContainerA { + private Date startDate; + private Date endDate; + + public Date getStartDate() { + return startDate; + } + + public void setStartDate(Date startDate) { + this.startDate = startDate; + } + + public Date getEndDate() { + return endDate; + } + + public void setEndDate(Date endDate) { + this.endDate = endDate; + } + + } + + public static class ContainerB { + private Date startDate; + + private InnerContainer inner; + + public Date getStartDate() { + return startDate; + } + + public void setStartDate(Date startDate) { + this.startDate = startDate; + } + + public InnerContainer getInner() { + return inner; + } + + public void setInner(InnerContainer inner) { + this.inner = inner; + } + + } + + public static class InnerContainer { + private Date endDate; + + public Date getEndDate() { + return endDate; + } + + public void setEndDate(Date endDate) { + this.endDate = endDate; + } + + } + + @Test + public void mapNestedNulls_atGlobalLevel() { + MapperFactory mapperFactory = new DefaultMapperFactory.Builder().mapNulls(true).build(); + ClassMapBuilder classMapBuilder = mapperFactory.classMap(ContainerA.class, + ContainerB.class); + classMapBuilder.field("startDate", "startDate"); + classMapBuilder.field("endDate", "inner.endDate"); + classMapBuilder.register(); + + MapperFacade facade = mapperFactory.getMapperFacade(); + + ContainerA a = new ContainerA(); + ContainerB b = new ContainerB(); + b.setStartDate(new Date()); + + InnerContainer c = new InnerContainer(); + c.setEndDate(new Date()); + + b.setInner(c); + + facade.map(a, b); + + Assert.assertNull("StartDate is not null", b.getStartDate()); + Assert.assertNull("EndDate is not null", b.getInner().getEndDate()); + } + + @Test + public void mapNestedNulls_atClassMapLevel() { + MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build(); + ClassMapBuilder classMapBuilder = mapperFactory.classMap(ContainerA.class, + ContainerB.class); + classMapBuilder.mapNulls(true); + classMapBuilder.field("startDate", "startDate"); + classMapBuilder.field("endDate", "inner.endDate"); + classMapBuilder.register(); + + MapperFacade facade = mapperFactory.getMapperFacade(); + + ContainerA a = new ContainerA(); + ContainerB b = new ContainerB(); + b.setStartDate(new Date()); + + InnerContainer c = new InnerContainer(); + c.setEndDate(new Date()); + + b.setInner(c); + + facade.map(a, b); + + Assert.assertNull("StartDate is not null", b.getStartDate()); + Assert.assertNull("EndDate is not null", b.getInner().getEndDate()); + } + + @Test + public void mapNestedNulls_atFieldLevel() { + MapperFactory mapperFactory = MappingUtil.getMapperFactory(true); + ClassMapBuilder classMapBuilder = mapperFactory.classMap(ContainerA.class, + ContainerB.class); + classMapBuilder.fieldMap("startDate", "startDate").mapNulls(true).add(); + classMapBuilder.fieldMap("endDate", "inner.endDate").mapNulls(true).add(); + classMapBuilder.register(); + + MapperFacade facade = mapperFactory.getMapperFacade(); + + ContainerA a = new ContainerA(); + ContainerB b = new ContainerB(); + b.setStartDate(new Date()); + + InnerContainer c = new InnerContainer(); + c.setEndDate(new Date()); + + b.setInner(c); + + Assert.assertNull(a.getStartDate()); + Assert.assertNull(a.getEndDate()); + facade.map(a, b); + + Assert.assertNull("StartDate is not null", b.getStartDate()); + Assert.assertNull("EndDate is not null", b.getInner().getEndDate()); + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue96/Address.java b/core/src/test/java/ma/glasnost/orika/test/community/issue96/Address.java new file mode 100644 index 00000000..7c101024 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue96/Address.java @@ -0,0 +1,38 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue96; + +public class Address { + private String city; + + public Address() { + } + + public Address(String city) { + this.city = city; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue96/AddressData.java b/core/src/test/java/ma/glasnost/orika/test/community/issue96/AddressData.java new file mode 100644 index 00000000..78d63985 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue96/AddressData.java @@ -0,0 +1,38 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue96; + +public class AddressData { + private String city; + + public AddressData() { + } + + public AddressData(String city) { + this.city = city; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue96/Customer.java b/core/src/test/java/ma/glasnost/orika/test/community/issue96/Customer.java new file mode 100644 index 00000000..a15e3331 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue96/Customer.java @@ -0,0 +1,40 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue96; + +public class Customer { + private String name; + private Address address; + + 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; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue96/CustomerData.java b/core/src/test/java/ma/glasnost/orika/test/community/issue96/CustomerData.java new file mode 100644 index 00000000..ff6c9668 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue96/CustomerData.java @@ -0,0 +1,40 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue96; + +public class CustomerData { + private String name; + private String city; + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/issue96/Issue96TestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/issue96/Issue96TestCase.java new file mode 100644 index 00000000..ad1ea837 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/issue96/Issue96TestCase.java @@ -0,0 +1,52 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.issue96; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.metadata.ClassMapBuilder; + +import org.junit.Before; +import org.junit.Test; + +public class Issue96TestCase { + private MapperFacade facade; + + @Before + public void setUp() { + MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build(); + ClassMapBuilder builder = mapperFactory.classMap(Customer.class, CustomerData.class); + builder.field("name", "name"); + builder.field("address.city", "city"); + mapperFactory.registerClassMap(builder.toClassMap()); + facade = mapperFactory.getMapperFacade(); + } + + @Test + public void test() { + AddressData address = new AddressData("city"); + // The next line produces a new mapper for AddresssData and Address + facade.map(address, Address.class); + CustomerData customer = new CustomerData(); + customer.setCity("city"); + customer.setName("name"); + facade.map(customer, Customer.class); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/community/vector/VectorTestCase.java b/core/src/test/java/ma/glasnost/orika/test/community/vector/VectorTestCase.java new file mode 100644 index 00000000..d1a62e78 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/community/vector/VectorTestCase.java @@ -0,0 +1,79 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.community.vector; + +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import org.junit.Assert; +import org.junit.Test; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import java.util.Vector; + +public class VectorTestCase { + private final MapperFactory factory = new DefaultMapperFactory.Builder().build(); + + @Test + public void test() { + + // Property.Builder builder = new Property.Builder(); + // builder.merge(UtilityResolver.getDefaultPropertyResolverStrategy().getProperty(Trade.class, + // "fees")); + // Property fees = builder.elementType(TypeFactory.valueOf()).build(); + + factory.classMap(XTrade.class, Trade.class).fieldMap("fees").bElementType(Fee.class).add().byDefault().register(); + + XTrade xtrade = new XTrade(); + XFee xfee = new XFee(); + xfee.amount = BigDecimal.valueOf(34.95); + xfee.description = "ATM Fee"; + xtrade.fees.add(xfee); + xfee = new XFee(); + xfee.amount = BigDecimal.valueOf(250.00); + xfee.description = "Cable Bill"; + xtrade.fees.add(xfee); + + Trade trade = factory.getMapperFacade().map(xtrade, Trade.class); + Assert.assertEquals(2, trade.fees.size()); + Assert.assertEquals(xtrade.fees.get(0).amount, ((Fee) trade.fees.get(0)).amount); + Assert.assertEquals(xtrade.fees.get(0).description, ((Fee) trade.fees.get(0)).description); + Assert.assertEquals(xtrade.fees.get(1).amount, ((Fee) trade.fees.get(1)).amount); + Assert.assertEquals(xtrade.fees.get(1).description, ((Fee) trade.fees.get(1)).description); + } + + public static class XTrade { + public List fees = new ArrayList<>(); + } + + public static class XFee { + public BigDecimal amount; + public String description; + } + + public static class Trade { + public Vector fees = new Vector(); + } + + public static class Fee { + public BigDecimal amount; + public String description; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/complex/LocalizedStringTestCases.java b/core/src/test/java/ma/glasnost/orika/test/complex/LocalizedStringTestCases.java new file mode 100644 index 00000000..a90ef94f --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/complex/LocalizedStringTestCases.java @@ -0,0 +1,7 @@ +package ma.glasnost.orika.test.complex; + +/** + * Created by sidi on 17/04/17. + */ +public class LocalizedStringTestCases { +} diff --git a/core/src/test/java/ma/glasnost/orika/test/concurrency/DefaultBoundMapperFacadeConcurrentInitTestCase.java b/core/src/test/java/ma/glasnost/orika/test/concurrency/DefaultBoundMapperFacadeConcurrentInitTestCase.java new file mode 100644 index 00000000..a714b5f0 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/concurrency/DefaultBoundMapperFacadeConcurrentInitTestCase.java @@ -0,0 +1,87 @@ +package ma.glasnost.orika.test.concurrency; + +import com.google.common.collect.Lists; +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.test.MappingUtil; +import ma.glasnost.orika.test.concurrency.model.ModelWithNestedObjDest; +import ma.glasnost.orika.test.concurrency.model.ModelWithNestedObjSource; +import ma.glasnost.orika.test.concurrency.model.NestedModel; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +/** + * Checks that instantiation and cache inside of <{@link ma.glasnost.orika.impl.DefaultBoundMapperFacade} is thread safe. + */ +public class DefaultBoundMapperFacadeConcurrentInitTestCase { + + private MapperFacade mapper; + + private final int threads = 20; + private ExecutorService executor; + + @Before + public void setup() { + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.classMap(ModelWithNestedObjSource.class, ModelWithNestedObjDest.class) + .byDefault() + .register(); + + mapper = factory.getMapperFacade(); + + executor = Executors.newFixedThreadPool(threads); + } + + @After + public void cleanup() { + if (executor != null) { + executor.shutdownNow(); + } + } + + @Test + public void testCase() { + CountDownLatch readyLatch = new CountDownLatch(threads); + + List> futures = IntStream.range(0, threads).mapToObj(i -> + executor.submit(() -> { + ModelWithNestedObjSource model = i % 2 == 0 + ? new ModelWithNestedObjSource(Lists.newArrayList(new NestedModel("str"))) + : new ModelWithNestedObjSource(Lists.newArrayList(new NestedModel(1))); + + readyLatch.countDown(); + try { + if (readyLatch.await(1, TimeUnit.SECONDS)) { + Assert.assertEquals(model.getValue(), mapper.map(model, ModelWithNestedObjDest.class).getValue()); + } else { + throw new RuntimeException("Latch timeout"); + } + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + }) + ).collect(Collectors.toList()); + + // check that no exception thrown inside futures + for (Future future : futures) { + try { + future.get(1, TimeUnit.SECONDS); + } catch (InterruptedException | ExecutionException | TimeoutException e) { + throw new RuntimeException(e); + } + } + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/concurrency/model/ModelWithNestedObjDest.java b/core/src/test/java/ma/glasnost/orika/test/concurrency/model/ModelWithNestedObjDest.java new file mode 100644 index 00000000..7a9235ed --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/concurrency/model/ModelWithNestedObjDest.java @@ -0,0 +1,16 @@ +package ma.glasnost.orika.test.concurrency.model; + +import java.util.List; + +public class ModelWithNestedObjDest { + + private List value; + + public List getValue() { + return value; + } + + public void setValue(List value) { + this.value = value; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/concurrency/model/ModelWithNestedObjSource.java b/core/src/test/java/ma/glasnost/orika/test/concurrency/model/ModelWithNestedObjSource.java new file mode 100644 index 00000000..ba2dd671 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/concurrency/model/ModelWithNestedObjSource.java @@ -0,0 +1,20 @@ +package ma.glasnost.orika.test.concurrency.model; + +import java.util.List; + +public class ModelWithNestedObjSource { + + private List value; + + public ModelWithNestedObjSource(List value) { + this.value = value; + } + + public List getValue() { + return value; + } + + public void setValue(List value) { + this.value = value; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/concurrency/model/NestedModel.java b/core/src/test/java/ma/glasnost/orika/test/concurrency/model/NestedModel.java new file mode 100644 index 00000000..aab8a46f --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/concurrency/model/NestedModel.java @@ -0,0 +1,38 @@ +package ma.glasnost.orika.test.concurrency.model; + +import java.util.Objects; + +public class NestedModel { + + private Object value; + + public NestedModel(Object value) { + this.value = value; + } + + public Object getValue() { + return value; + } + + public void setValue(Object value) { + this.value = value; + } + + @Override + public int hashCode() { + return Objects.hash(value); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + NestedModel other = (NestedModel) obj; + return Objects.equals(value, other.value); + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/constructor/ConstructorMappingTestCase.java b/core/src/test/java/ma/glasnost/orika/test/constructor/ConstructorMappingTestCase.java new file mode 100644 index 00000000..1d5aecdb --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/constructor/ConstructorMappingTestCase.java @@ -0,0 +1,614 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.constructor; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingException; +import ma.glasnost.orika.constructor.ConstructorResolverStrategy; +import ma.glasnost.orika.constructor.PrefixParamConstructorResolverStrategy; +import ma.glasnost.orika.converter.builtin.DateToStringConverter; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.test.MappingUtil; +import ma.glasnost.orika.test.common.types.TestCaseClasses.Author; +import ma.glasnost.orika.test.common.types.TestCaseClasses.AuthorDTO; +import ma.glasnost.orika.test.common.types.TestCaseClasses.AuthorImpl; +import ma.glasnost.orika.test.common.types.TestCaseClasses.AuthorNested; +import ma.glasnost.orika.test.common.types.TestCaseClasses.Book; +import ma.glasnost.orika.test.common.types.TestCaseClasses.BookDTO; +import ma.glasnost.orika.test.common.types.TestCaseClasses.BookImpl; +import ma.glasnost.orika.test.common.types.TestCaseClasses.BookNested; +import ma.glasnost.orika.test.common.types.TestCaseClasses.Library; +import ma.glasnost.orika.test.common.types.TestCaseClasses.LibraryDTO; +import ma.glasnost.orika.test.common.types.TestCaseClasses.LibraryImpl; +import ma.glasnost.orika.test.common.types.TestCaseClasses.LibraryNested; +import ma.glasnost.orika.test.common.types.TestCaseClasses.Name; +import ma.glasnost.orika.test.common.types.TestCaseClasses.PrimitiveHolder; +import ma.glasnost.orika.test.common.types.TestCaseClasses.PrimitiveHolderDTO; +import ma.glasnost.orika.test.common.types.TestCaseClasses.PrimitiveWrapperHolder; +import ma.glasnost.orika.test.common.types.TestCaseClasses.PrimitiveWrapperHolderDTO; +import ma.glasnost.orika.test.constructor.TestCaseClasses.Holder; +import ma.glasnost.orika.test.constructor.TestCaseClasses.NestedPrimitiveHolder; +import ma.glasnost.orika.test.constructor.TestCaseClasses.Person; +import ma.glasnost.orika.test.constructor.TestCaseClasses.PersonVO; +import ma.glasnost.orika.test.constructor.TestCaseClasses.PersonVO2; +import ma.glasnost.orika.test.constructor.TestCaseClasses.PersonVO3; +import ma.glasnost.orika.test.constructor.TestCaseClasses.PersonVO4; +import ma.glasnost.orika.test.constructor.TestCaseClasses.PrimitiveNumberHolder; +import ma.glasnost.orika.test.constructor.TestCaseClasses.WrapperHolder; +import org.junit.Assert; +import org.junit.Test; + +import java.net.URL; +import java.net.URLStreamHandler; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +public class ConstructorMappingTestCase { + + private static final String DATE_CONVERTER = "dateConverter"; + private static final String DATE_PATTERN = "dd/MM/yyyy"; + + @Test + public void testSimpleCase() throws Throwable { + + final SimpleDateFormat df = new SimpleDateFormat(DATE_PATTERN); + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.classMap(PersonVO.class, Person.class) + .fieldMap("dateOfBirth", "date") + .converter(DATE_CONVERTER) + .add() + .byDefault() + .register(); + + factory.getConverterFactory().registerConverter(DATE_CONVERTER, new DateToStringConverter(DATE_PATTERN)); + + Person person = new Person(); + person.setFirstName("Abdelkrim"); + person.setLastName("EL KHETTABI"); + person.setDate(df.parse("01/01/1980")); + person.setAge(31L); + + PersonVO vo = factory.getMapperFacade().map(person, PersonVO.class); + + Assert.assertEquals(person.getFirstName(), vo.getFirstName()); + Assert.assertEquals(person.getLastName(), vo.getLastName()); + Assert.assertTrue(person.getAge() == vo.getAge()); + Assert.assertEquals("01/01/1980", vo.getDateOfBirth()); + } + + + @Test + public void testFindConstructor() throws Throwable { + final SimpleDateFormat df = new SimpleDateFormat(DATE_PATTERN); + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.classMap(PersonVO3.class, Person.class) + .fieldMap("dateOfBirth", "date").converter(DATE_CONVERTER).add() + .byDefault() + .register(); + factory.getConverterFactory().registerConverter(DATE_CONVERTER, new DateToStringConverter(DATE_PATTERN)); + + + Person person = new Person(); + person.setFirstName("Abdelkrim"); + person.setLastName("EL KHETTABI"); + person.setDate(df.parse("01/01/1980")); + person.setAge(31L); + + PersonVO3 vo = factory.getMapperFacade().map(person, PersonVO3.class); + + Assert.assertEquals(person.getFirstName(), vo.getFirstName()); + Assert.assertEquals(person.getLastName(), vo.getLastName()); + Assert.assertTrue(person.getAge() == vo.getAge()); + Assert.assertEquals("01/01/1980", vo.getDateOfBirth()); + } + + public static long yearsDifference(final Date start, final Date end) { + long diff = end.getTime() - start.getTime(); + return diff / TimeUnit.SECONDS.toMillis(60*60*24*365); + } + + @Test + public void testFindConstructor2() throws Throwable { + final SimpleDateFormat df = new SimpleDateFormat(DATE_PATTERN); + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.classMap(PersonVO3.class, Person.class) + .field("firstName", "firstName") + .field("lastName", "lastName") + .field("dateOfBirth", "date") + .register(); + factory.getConverterFactory().registerConverter(DATE_CONVERTER, new DateToStringConverter(DATE_PATTERN)); + + Person person = new Person(); + person.setFirstName("Abdelkrim"); + person.setLastName("EL KHETTABI"); + person.setDate(df.parse("01/01/1980")); + + Calendar c = Calendar.getInstance(); + c.set(Calendar.YEAR, 1980); + c.set(Calendar.MONTH, 0); + c.set(Calendar.DAY_OF_MONTH, 1); + + person.setAge(yearsDifference(c.getTime(), new Date())); + + PersonVO3 vo = factory.getMapperFacade().map(person, PersonVO3.class); + + Assert.assertEquals(person.getFirstName(), vo.getFirstName()); + Assert.assertEquals(person.getLastName(), vo.getLastName()); + Assert.assertTrue(person.getAge() == vo.getAge()); + Assert.assertEquals("01/01/1980", vo.getDateOfBirth()); + } + + @Test + public void testAutomaticCaseWithHint() throws Throwable { + + final SimpleDateFormat df = new SimpleDateFormat(DATE_PATTERN); + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.registerDefaultFieldMapper((fromProperty, fromPropertyType) -> { + if ("dateOfBirth".equals(fromProperty)) { + return "date"; + } else if("date".equals(fromProperty)) { + return "dateOfBirth"; + } + return null; + }); + + factory.getConverterFactory().registerConverter(new DateToStringConverter(DATE_PATTERN)); + + + Person person = new Person(); + person.setFirstName("Abdelkrim"); + person.setLastName("EL KHETTABI"); + person.setDate(df.parse("01/01/1980")); + person.setAge(31L); + + PersonVO vo = factory.getMapperFacade().map(person, PersonVO.class); + + Assert.assertEquals(person.getFirstName(), vo.getFirstName()); + Assert.assertEquals(person.getLastName(), vo.getLastName()); + Assert.assertTrue(person.getAge() == vo.getAge()); + Assert.assertEquals("01/01/1980", vo.getDateOfBirth()); + } + + @Test + public void testPrimitiveToPrimitiveTypes() { + + PrimitiveHolder primitiveHolder = + new PrimitiveHolder( + Short.MAX_VALUE, + Integer.MAX_VALUE, + Long.MAX_VALUE, + Float.MAX_VALUE, + Double.MAX_VALUE, + Character.MAX_VALUE, + true, + Byte.MAX_VALUE); + + MapperFactory factory = MappingUtil.getMapperFactory(); + + PrimitiveHolderDTO dto = factory.getMapperFacade().map(primitiveHolder, PrimitiveHolderDTO.class); + + assertValidMapping(primitiveHolder,dto); + + PrimitiveHolder mapBack = factory.getMapperFacade().map(dto, PrimitiveHolder.class); + + assertValidMapping(mapBack, dto); + } + + @Test + public void testPrimitiveToWrapperTypes() { + + PrimitiveHolder primitiveHolder = + new PrimitiveHolder( + Short.MAX_VALUE, + Integer.MAX_VALUE, + Long.MAX_VALUE, + Float.MAX_VALUE, + Double.MAX_VALUE, + Character.MAX_VALUE, + true, + Byte.MAX_VALUE); + + MapperFactory factory = MappingUtil.getMapperFactory(); + + PrimitiveWrapperHolder wrapper = factory.getMapperFacade().map(primitiveHolder, PrimitiveWrapperHolder.class); + + assertValidMapping(wrapper, primitiveHolder); + + PrimitiveHolder mapBack = factory.getMapperFacade().map(wrapper, PrimitiveHolder.class); + + assertValidMapping(wrapper, mapBack); + } + + @Test + public void testWrapperToWrapperTypes() { + + PrimitiveWrapperHolder primitiveHolder = + new PrimitiveWrapperHolder( + Short.MAX_VALUE, + Integer.MAX_VALUE, + Long.MAX_VALUE, + Float.MAX_VALUE, + Double.MAX_VALUE, + Character.MAX_VALUE, + true, + Byte.MAX_VALUE); + + MapperFactory factory = MappingUtil.getMapperFactory(); + + PrimitiveWrapperHolderDTO dto = factory.getMapperFacade().map(primitiveHolder, PrimitiveWrapperHolderDTO.class); + + assertValidMapping(primitiveHolder, dto); + + PrimitiveWrapperHolder mapBack = factory.getMapperFacade().map(dto, PrimitiveWrapperHolder.class); + + assertValidMapping(mapBack, dto); + } + + @Test + public void testPrimitivePropertiesWithWrapperConstructor() throws Throwable { + + final SimpleDateFormat df = new SimpleDateFormat(DATE_PATTERN); + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.registerDefaultFieldMapper((fromProperty, fromPropertyType) -> { + if ("dateOfBirth".equals(fromProperty)) { + return "date"; + } else if("date".equals(fromProperty)) { + return "dateOfBirth"; + } + return null; + }); + + factory.getConverterFactory().registerConverter(new DateToStringConverter(DATE_PATTERN)); + + Person person = new Person(); + person.setFirstName("Abdelkrim"); + person.setLastName("EL KHETTABI"); + person.setDate(df.parse("01/01/1980")); + person.setAge(31L); + + PersonVO2 vo = factory.getMapperFacade().map(person, PersonVO2.class); + + Assert.assertEquals(person.getFirstName(), vo.getFirstName()); + Assert.assertEquals(person.getLastName(), vo.getLastName()); + Assert.assertTrue(person.getAge() == vo.getAge()); + Assert.assertEquals("01/01/1980", vo.getDateOfBirth()); + + } + + @Test + public void testBaseCaseWithCollectionTypes() { + + List books = new ArrayList<>(4); + + Author author1 = new AuthorImpl("Author #1"); + Author author2 = new AuthorImpl("Author #2"); + + books.add(new BookImpl("Book #1", author1)); + books.add(new BookImpl("Book #2", author1)); + books.add(new BookImpl("Book #3", author2)); + books.add(new BookImpl("Book #4", author2)); + + Library library = new LibraryImpl("Library #1", books); + + MapperFactory factory = MappingUtil.getMapperFactory(); + MapperFacade mapper = factory.getMapperFacade(); + + LibraryDTO mapped = mapper.map(library, LibraryDTO.class); + + assertValidMapping(library,mapped); + + Library libraryMapBack = mapper.map(mapped, LibraryImpl.class); + + assertValidMapping(libraryMapBack,mapped); + + } + + @Test + public void testMappingNestedTypes() { + + List books = new ArrayList<>(4); + + AuthorNested author1 = new AuthorNested(new Name("Abdelkrim","EL KHETTABI")); + AuthorNested author2 = new AuthorNested(new Name("Bill","Shakespeare")); + + books.add(new BookNested("Book #1", author1)); + books.add(new BookNested("Book #2", author1)); + books.add(new BookNested("Book #3", author2)); + books.add(new BookNested("Book #4", author2)); + + LibraryNested library = new LibraryNested("Library #1", books); + + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.classMap(AuthorNested.class, AuthorDTO.class) + .field("name.fullName", "name") + .byDefault() + .register(); + + MapperFacade mapper = factory.getMapperFacade(); + + LibraryDTO mapped = mapper.map(library, LibraryDTO.class); + + assertValidMapping(library,mapped); + + /* + // this situation is a bit too complicated to handle normally; + // how would Orika even know how to create a Name object which takes + // in multiple parameters it cannot find on the source object? + LibraryNested libraryMapBack = mapper.map(mapped, LibraryNested.class); + + assertValidMapping(libraryMapBack,mapped); + + */ + } + + + @Test + public void testComplexMappingNestedTypes() { + + + PrimitiveNumberHolder numbers = + new PrimitiveNumberHolder( + Short.MAX_VALUE, + Integer.MAX_VALUE, + Long.MAX_VALUE, + Float.MAX_VALUE, + Double.MAX_VALUE); + + NestedPrimitiveHolder primitiveHolder = new NestedPrimitiveHolder(numbers, Character.MAX_VALUE, Boolean.TRUE, Byte.MAX_VALUE); + + Holder holder = new Holder(primitiveHolder); + + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.classMap(NestedPrimitiveHolder.class, PrimitiveWrapperHolder.class) + .field("numbers.shortValue", "shortValue") + .field("numbers.intValue", "intValue") + .field("numbers.longValue", "longValue") + .field("numbers.floatValue", "floatValue") + .field("numbers.doubleValue", "doubleValue") + .byDefault() + .register(); + + WrapperHolder wrapper = factory.getMapperFacade().map(holder, WrapperHolder.class); + + assertValidMapping(holder, wrapper); + + } + + + public static class URLDto1 { + public String protocolX; + public String hostX; + public int portX; + public String fileX; + } + + public static class URLDto2 { + public String protocol; + public String host; + public String file; + } + + public static class URLDto3 { + public String protocol; + public String host; + public int port; + public String file; + public URLStreamHandler handler; + } + + public static class URLDto4 { + public URL context; + public String spec; + } + + @Test + public void testConstructorsWithoutDebugInfo() { + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.classMap(URLDto1.class, URL.class) + .field("protocolX", "protocol") + .field("hostX", "host") + .field("portX", "port") + .field("fileX", "file") + .register(); + MapperFacade mapper = factory.getMapperFacade(); + + URLDto1 dto1 = new URLDto1(); + dto1.protocolX = "http"; + dto1.hostX = "somewhere.com"; + dto1.portX = 8080; + dto1.fileX = "index.html"; + + URL url = mapper.map(dto1, URL.class); + Assert.assertNotNull(url); + Assert.assertEquals(dto1.protocolX, url.getProtocol()); + Assert.assertEquals(dto1.hostX, url.getHost()); + Assert.assertEquals(dto1.portX, url.getPort()); + + } + + @Test + public void testFindConstructor_mapParamNames_ok() { + ConstructorResolverStrategy constructorStrategy = new PrefixParamConstructorResolverStrategy(); + DefaultMapperFactory.Builder builder = new DefaultMapperFactory.Builder(); + builder.constructorResolverStrategy(constructorStrategy); + MapperFactory factory = builder.build(); + + testPersonV04Mapping(factory); + } + + @Test(expected = MappingException.class) + public void testFindConstructor_doNotMapParamNames_ex() { + testPersonV04Mapping(MappingUtil.getMapperFactory()); + } + + private void testPersonV04Mapping(MapperFactory factory) { + Person person = newPerson(); + + PersonVO4 vo = factory.getMapperFacade().map(person, PersonVO4.class); + + Assert.assertEquals(person.getFirstName(), vo.getFirstName()); + Assert.assertEquals(person.getLastName(), vo.getLastName()); + Assert.assertTrue(person.getAge() == vo.getAge()); + } + + private Person newPerson() { + Person person = new Person(); + person.setFirstName("Abdelkrim"); + person.setLastName("EL KHETTABI"); + person.setAge(31L); + return person; + } + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Common mapping validations + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + private void assertValidMapping(Holder holder, WrapperHolder dto) { + assertValidMapping(holder.getNested(), dto.getNested()); + } + + private void assertValidMapping(NestedPrimitiveHolder nested, PrimitiveWrapperHolder wrapper) { + assertEquals(nested.getNumbers().getShortValue(), wrapper.getShortValue().shortValue()); + assertEquals(nested.getNumbers().getIntValue(), wrapper.getIntValue().intValue()); + assertEquals(nested.getNumbers().getLongValue(), wrapper.getLongValue().longValue()); + assertEquals(nested.getNumbers().getFloatValue(), wrapper.getFloatValue(), 1.0f); + assertEquals(nested.getNumbers().getDoubleValue(), wrapper.getDoubleValue(), 1.0d); + assertEquals(nested.getCharValue(), wrapper.getCharValue().charValue()); + assertEquals(nested.isBooleanValue(), wrapper.getBooleanValue()); + assertEquals(nested.getByteValue(), wrapper.getByteValue().byteValue()); + } + + private void assertValidMapping(PrimitiveHolder primitiveHolder, PrimitiveHolderDTO dto) { + assertEquals(primitiveHolder.getShortValue(), dto.getShortValue()); + assertEquals(primitiveHolder.getIntValue(), dto.getIntValue()); + assertEquals(primitiveHolder.getLongValue(), dto.getLongValue()); + assertEquals(primitiveHolder.getFloatValue(), dto.getFloatValue(), 1.0f); + assertEquals(primitiveHolder.getDoubleValue(), dto.getDoubleValue(), 1.0d); + assertEquals(primitiveHolder.getCharValue(), dto.getCharValue()); + assertEquals(primitiveHolder.isBooleanValue(), dto.isBooleanValue()); + assertEquals(primitiveHolder.getByteValue(), dto.getByteValue()); + } + + private void assertValidMapping(PrimitiveWrapperHolder primitiveHolder, PrimitiveWrapperHolderDTO dto) { + assertEquals(primitiveHolder.getShortValue(), dto.getShortValue()); + assertEquals(primitiveHolder.getIntValue(), dto.getIntValue()); + assertEquals(primitiveHolder.getLongValue(), dto.getLongValue()); + assertEquals(primitiveHolder.getFloatValue(), dto.getFloatValue(), 1.0f); + assertEquals(primitiveHolder.getDoubleValue(), dto.getDoubleValue(), 1.0d); + assertEquals(primitiveHolder.getCharValue(), dto.getCharValue()); + assertEquals(primitiveHolder.getBooleanValue(), dto.getBooleanValue()); + assertEquals(primitiveHolder.getByteValue(), dto.getByteValue()); + } + + private void assertValidMapping(PrimitiveWrapperHolder wrappers, PrimitiveHolder primitives) { + assertEquals(wrappers.getShortValue().shortValue(), primitives.getShortValue()); + assertEquals(wrappers.getIntValue().intValue(), primitives.getIntValue()); + assertEquals(wrappers.getLongValue().longValue(), primitives.getLongValue()); + assertEquals(wrappers.getFloatValue(), primitives.getFloatValue(), 1.0f); + assertEquals(wrappers.getDoubleValue(), primitives.getDoubleValue(), 1.0d); + assertEquals(wrappers.getCharValue().charValue(), primitives.getCharValue()); + assertEquals(wrappers.getBooleanValue(), primitives.isBooleanValue()); + assertEquals(wrappers.getByteValue().byteValue(), primitives.getByteValue()); + } + + + private void assertValidMapping(Library library, LibraryDTO dto) { + + assertNotNull(library); + assertNotNull(dto); + + assertNotNull(library.getBooks()); + assertNotNull(dto.getBooks()); + + List sortedBooks =library.getBooks(); + + List sortedDTOs = dto.getBooks(); + + assertEquals(sortedBooks.size(), sortedDTOs.size()); + + for (int i = 0, count=sortedBooks.size(); i < count; ++i) { + Book book = sortedBooks.get(i); + BookDTO bookDto = sortedDTOs.get(i); + assertValidMapping(book,bookDto); + } + } + + private void assertValidMapping(LibraryNested library, LibraryDTO dto) { + + assertNotNull(library); + assertNotNull(dto); + + assertNotNull(library.getBooks()); + assertNotNull(dto.getBooks()); + + List sortedBooks = library.getBooks(); + + List sortedDTOs = dto.getBooks(); + + assertEquals(sortedBooks.size(), sortedDTOs.size()); + + for (int i = 0, count=sortedBooks.size(); i < count; ++i) { + BookNested book = sortedBooks.get(i); + BookDTO bookDto = sortedDTOs.get(i); + assertValidMapping(book,bookDto); + } + } + + private void assertValidMapping(Book book, BookDTO dto) { + assertNotNull(book); + assertNotNull(dto); + assertEquals(book.getTitle(), dto.getTitle()); + assertValidMapping(book.getAuthor(), dto.getAuthor()); + } + + private void assertValidMapping(BookNested book, BookDTO dto) { + assertNotNull(book); + assertNotNull(dto); + assertEquals(book.getTitle(), dto.getTitle()); + assertValidMapping(book.getAuthor(), dto.getAuthor()); + } + + private void assertValidMapping(Author author, AuthorDTO authorDTO) { + assertNotNull(author); + assertNotNull(authorDTO); + assertEquals(author.getName(),authorDTO.getName()); + } + + private void assertValidMapping(AuthorNested author, AuthorDTO authorDTO) { + assertNotNull(author); + assertNotNull(authorDTO); + assertEquals(author.getName().getFullName(),authorDTO.getName()); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/constructor/TestCaseClasses.java b/core/src/test/java/ma/glasnost/orika/test/constructor/TestCaseClasses.java new file mode 100644 index 00000000..9725bcb1 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/constructor/TestCaseClasses.java @@ -0,0 +1,345 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.constructor; + +import ma.glasnost.orika.test.common.types.TestCaseClasses.PrimitiveWrapperHolder; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +public interface TestCaseClasses { + + class Person { + private String firstName; + private String lastName; + + private Long age; + private Date date; + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public Long getAge() { + return age; + } + + public void setAge(Long age) { + this.age = age; + } + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } + + } + + class PersonVO { + private final String firstName; + private final String lastName; + + private final long age; + private final String dateOfBirth; + + public PersonVO(String firstName, String lastName, long age, String dateOfBirth) { + this.firstName = firstName; + this.lastName = lastName; + this.age = age; + this.dateOfBirth = dateOfBirth; + } + + public String getFirstName() { + return firstName; + } + + public String getLastName() { + return lastName; + } + + public long getAge() { + return age; + } + + public String getDateOfBirth() { + return dateOfBirth; + } + } + + class PersonVO2 { + + private final String firstName; + private final String lastName; + + private final long age; + private final String dateOfBirth; + + public PersonVO2(String firstName, String lastName, Long age, String dateOfBirth) { + this.firstName = firstName; + this.lastName = lastName; + this.age = age!=null ? age : 0; + this.dateOfBirth = dateOfBirth; + } + + public String getFirstName() { + return firstName; + } + + public String getLastName() { + return lastName; + } + + public long getAge() { + return age; + } + + public String getDateOfBirth() { + return dateOfBirth; + } + } + + + class PersonVO3 { + + private final String firstName; + private final String lastName; + + private final long age; + private final String dateOfBirth; + + public PersonVO3(String dateOfBirth, Long age, String lastName, String firstName) { + this(firstName, lastName, age, dateOfBirth); + } + + public PersonVO3(String firstName, String lastName, Long age, String dateOfBirth) { + this.firstName = firstName; + this.lastName = lastName; + this.age = age!=null ? age : 0; + this.dateOfBirth = dateOfBirth; + } + + public PersonVO3(String firstName, String lastName, Date dateOfBirth) { + this(firstName, lastName, yearsDifference(dateOfBirth, new Date()), + new SimpleDateFormat("dd/MM/yyyy").format(dateOfBirth)); + } + + public static long yearsDifference(final Date start, final Date end) { + long diff = end.getTime() - start.getTime(); + return diff / TimeUnit.SECONDS.toMillis(60*60*24*365); + } + + public String getFirstName() { + return firstName; + } + + public String getLastName() { + return lastName; + } + + public long getAge() { + return age; + } + + public String getDateOfBirth() { + return dateOfBirth; + } + } + + class PersonVO4 { + + private final String firstName; + private final String lastName; + private final long age; + + public PersonVO4(String pFirstName, String pLastName, long pAge) { + firstName = pFirstName; + lastName = pLastName; + age = pAge; + } + + public String getFirstName() { + return firstName; + } + + public String getLastName() { + return lastName; + } + + public long getAge() { + return age; + } + } + + class NestedPrimitiveHolder { + + private final char charValue; + private final boolean booleanValue; + private final byte byteValue; + private final PrimitiveNumberHolder numbers; + + public NestedPrimitiveHolder(PrimitiveNumberHolder numbers, char charValue, boolean booleanValue, byte byteValue) { + super(); + this.charValue = charValue; + this.booleanValue = booleanValue; + this.byteValue = byteValue; + this.numbers = numbers; + } + + public PrimitiveNumberHolder getNumbers() { + return numbers; + } + + public char getCharValue() { + return charValue; + } + + public boolean isBooleanValue() { + return booleanValue; + } + + public byte getByteValue() { + return byteValue; + } + + public boolean equals(Object that) { + if (that == this) return true; + if (!(that instanceof NestedPrimitiveHolder)) { + return false; + } + NestedPrimitiveHolder nph = (NestedPrimitiveHolder) that; + return Objects.equals(getCharValue(), nph.getCharValue()) && + Objects.equals(isBooleanValue(), nph.isBooleanValue()) && + Objects.equals(getByteValue(), nph.getByteValue()) && + Objects.equals(getNumbers(), nph.getNumbers()); + } + + public int hashCode() { + return Objects.hash(charValue, booleanValue, byteValue, numbers); + } + + @Override + public String toString() { + return "NestedPrimitiveHolder [charValue=" + charValue + ", booleanValue=" + booleanValue + ", byteValue=" + + byteValue + ", numbers=" + numbers + "]"; + } + } + + class PrimitiveNumberHolder { + private final short shortValue; + private final int intValue; + private final long longValue; + private final float floatValue; + private final double doubleValue; + + public PrimitiveNumberHolder(short shortValue, int intValue, long longValue, + float floatValue, double doubleValue) { + super(); + this.shortValue = shortValue; + this.intValue = intValue; + this.longValue = longValue; + this.floatValue = floatValue; + this.doubleValue = doubleValue; + } + + public short getShortValue() { + return shortValue; + } + + public int getIntValue() { + return intValue; + } + + public long getLongValue() { + return longValue; + } + + public float getFloatValue() { + return floatValue; + } + + public double getDoubleValue() { + return doubleValue; + } + + @Override + public String toString() { + return "PrimitiveNumberHolder [shortValue=" + shortValue + ", intValue=" + intValue + ", longValue=" + + longValue + ", floatValue=" + floatValue + ", doubleValue=" + doubleValue + "]"; + } + + @Override + public boolean equals(final Object other) { + if (!(other instanceof PrimitiveNumberHolder)) { + return false; + } + PrimitiveNumberHolder castOther = (PrimitiveNumberHolder) other; + return Objects.equals(shortValue, castOther.shortValue) && Objects.equals(intValue, castOther.intValue) + && Objects.equals(longValue, castOther.longValue) + && Objects.equals(floatValue, castOther.floatValue) + && Objects.equals(doubleValue, castOther.doubleValue); + } + + @Override + public int hashCode() { + return Objects.hash(shortValue, intValue, longValue, floatValue, doubleValue); + } + } + + class Holder { + private final NestedPrimitiveHolder nested; + + public Holder(NestedPrimitiveHolder nestedHolder) { + super(); + this.nested = nestedHolder; + } + + public NestedPrimitiveHolder getNested() { + return nested; + } + } + + class WrapperHolder { + private PrimitiveWrapperHolder nested; + + public PrimitiveWrapperHolder getNested() { + return nested; + } + + public void setNested(PrimitiveWrapperHolder nested) { + this.nested = nested; + } + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/converter/CloneableConverterNoSetAccessibleTestCase.java b/core/src/test/java/ma/glasnost/orika/test/converter/CloneableConverterNoSetAccessibleTestCase.java new file mode 100644 index 00000000..be0fc70c --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/converter/CloneableConverterNoSetAccessibleTestCase.java @@ -0,0 +1,134 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.converter; + +import java.sql.Timestamp; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.Objects; + +import javax.xml.datatype.DatatypeConfigurationException; +import javax.xml.datatype.DatatypeFactory; +import javax.xml.datatype.XMLGregorianCalendar; + +import org.junit.Assert; +import org.junit.Test; + +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.converter.builtin.CloneableConverter; +import ma.glasnost.orika.test.MappingUtil; + +public class CloneableConverterNoSetAccessibleTestCase { + + @Test + public void cloneableConverterWithoutSetAccessible() throws DatatypeConfigurationException { + + final SecurityManager initialSm = System.getSecurityManager(); + try { + System.setSecurityManager(new SecurityManager() { + public void checkPermission(java.security.Permission perm) { + if ("suppressAccessChecks".equals(perm.getName())) { + for (StackTraceElement ste: new Throwable().getStackTrace()) { + if (ste.getClassName().equals(CloneableConverter.class.getCanonicalName())) { + throw new SecurityException("not permitted"); + } + } + } + } + }); + + + CloneableConverter cc = new CloneableConverter(SampleCloneable.class); + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(cc); + + GregorianCalendar cal = new GregorianCalendar(); + cal.add(Calendar.YEAR, 10); + XMLGregorianCalendar xmlCal = DatatypeFactory.newInstance().newXMLGregorianCalendar((GregorianCalendar)cal); + cal.add(Calendar.MONTH, 3); + + ClonableHolder source = new ClonableHolder(); + source.value = new SampleCloneable(); + source.value.id = 5L; + source.date = new Date(System.currentTimeMillis() + 100000); + source.timestamp = new Timestamp(System.currentTimeMillis() + 50000); + source.calendar = cal; + source.xmlCalendar = xmlCal; + + ClonableHolder dest = factory.getMapperFacade().map(source, ClonableHolder.class); + Assert.assertEquals(source.value, dest.value); + Assert.assertNotSame(source.value, dest.value); + Assert.assertEquals(source.date, dest.date); + Assert.assertNotSame(source.date, dest.date); + Assert.assertEquals(source.timestamp, dest.timestamp); + Assert.assertNotSame(source.timestamp, dest.timestamp); + Assert.assertEquals(source.calendar, dest.calendar); + Assert.assertNotSame(source.calendar, dest.calendar); + Assert.assertEquals(source.xmlCalendar, dest.xmlCalendar); + Assert.assertNotSame(source.xmlCalendar, dest.xmlCalendar); + } finally { + System.setSecurityManager(initialSm); + } + } + + public static class ClonableHolder { + public SampleCloneable value; + public Date date; + public java.sql.Timestamp timestamp; + public Calendar calendar; + public XMLGregorianCalendar xmlCalendar; + } + + + public static class SampleCloneable implements Cloneable { + private Long id; + + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Object clone() { + SampleCloneable clone; + try { + clone = (SampleCloneable) super.clone(); + clone.id = id; + } catch (CloneNotSupportedException e) { + throw new IllegalStateException(e); + } + + return clone; + } + + public boolean equals(Object that) { + return Objects.equals(id, ((SampleCloneable) that).id); + } + + public int hashCode() { + return Objects.hash(id); + } + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/converter/CloneableConverterTestCase.java b/core/src/test/java/ma/glasnost/orika/test/converter/CloneableConverterTestCase.java new file mode 100644 index 00000000..fce0cf1c --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/converter/CloneableConverterTestCase.java @@ -0,0 +1,272 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.converter; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.converter.builtin.CloneableConverter; +import ma.glasnost.orika.converter.builtin.PassThroughConverter; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.test.MappingUtil; +import org.junit.Assert; +import org.junit.Test; + +import javax.xml.datatype.DatatypeConfigurationException; +import javax.xml.datatype.DatatypeFactory; +import javax.xml.datatype.XMLGregorianCalendar; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.List; +import java.util.Objects; + +public class CloneableConverterTestCase { + + @Test + public void cloneableConverter() throws DatatypeConfigurationException { + + CloneableConverter cc = new CloneableConverter(SampleCloneable.class); + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(cc); + + GregorianCalendar cal = new GregorianCalendar(); + cal.add(Calendar.YEAR, 10); + XMLGregorianCalendar xmlCal = DatatypeFactory.newInstance().newXMLGregorianCalendar((GregorianCalendar)cal); + cal.add(Calendar.MONTH, 3); + + ClonableHolder source = new ClonableHolder(); + source.value = new SampleCloneable(); + source.value.id = 5L; + source.date = new Date(System.currentTimeMillis() + 100000); + source.timestamp = new Timestamp(System.currentTimeMillis() + 50000); + source.calendar = cal; + source.xmlCalendar = xmlCal; + + ClonableHolder dest = factory.getMapperFacade().map(source, ClonableHolder.class); + Assert.assertEquals(source.value, dest.value); + Assert.assertNotSame(source.value, dest.value); + Assert.assertEquals(source.date, dest.date); + Assert.assertNotSame(source.date, dest.date); + Assert.assertEquals(source.timestamp, dest.timestamp); + Assert.assertNotSame(source.timestamp, dest.timestamp); + Assert.assertEquals(source.calendar, dest.calendar); + Assert.assertNotSame(source.calendar, dest.calendar); + Assert.assertEquals(source.xmlCalendar, dest.xmlCalendar); + Assert.assertNotSame(source.xmlCalendar, dest.xmlCalendar); + } + + @Test + public void cloneableConverterNullSource() throws DatatypeConfigurationException { + MapperFactory factory = new DefaultMapperFactory.Builder().build(); + factory.classMap(ComplexSource.class, ComplexDest.class) + .field("someDate.dateHolder{date}", "meaningfulDate{date}") + .byDefault().register(); + MapperFacade facade = factory.getMapperFacade(); + + Date date1 = new Date(System.currentTimeMillis() + 100001); + Date date2 = new Date(System.currentTimeMillis() + 100002); + ArrayOfDates arrayOfDate = new ArrayOfDates(); + arrayOfDate.getDateHolder().add(new SourceDateHolder(date1)); + arrayOfDate.getDateHolder().add(new SourceDateHolder(date2)); + + ComplexSource complexSource = new ComplexSource(arrayOfDate); + ComplexDest complexDest = facade.map(complexSource, ComplexDest.class); + + Assert.assertEquals(complexSource.getSomeDate().getDateHolder().size(), complexDest.getMeaningfulDate().size()); + + Assert.assertEquals(date1, complexDest.getMeaningfulDate().get(0).getDate()); + Assert.assertNotSame(date1, complexDest.getMeaningfulDate().get(0).getDate()); + + Assert.assertEquals(date2, complexDest.getMeaningfulDate().get(1).getDate()); + Assert.assertNotSame(date2, complexDest.getMeaningfulDate().get(1).getDate()); + + complexSource.getSomeDate().getDateHolder().add(new SourceDateHolder(null)); + + // use cached clone method here without checking if source is null causes a NullPointerException + complexDest = facade.map(complexSource, ComplexDest.class); + Assert.assertEquals(complexSource.getSomeDate().getDateHolder().size(), complexDest.getMeaningfulDate().size()); + + Assert.assertNull(complexDest.getMeaningfulDate().get(2).getDate()); + } + + + /** + * This test method demonstrates that you can decide to treat one of the default cloneable types + * as immutable if desired by registering your own PassThroughConverter for that type + * + * @throws DatatypeConfigurationException + */ + @Test + public void overrideDefaultCloneableToImmutable() throws DatatypeConfigurationException { + + PassThroughConverter cc = new PassThroughConverter(Date.class, Calendar.class); + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(cc); + + GregorianCalendar cal = new GregorianCalendar(); + cal.add(Calendar.YEAR, 10); + XMLGregorianCalendar xmlCal = DatatypeFactory.newInstance().newXMLGregorianCalendar((GregorianCalendar)cal); + cal.add(Calendar.MONTH, 3); + + ClonableHolder source = new ClonableHolder(); + source.value = new SampleCloneable(); + source.value.id = 5L; + source.date = new Date(System.currentTimeMillis() + 100000); + source.calendar = cal; + source.xmlCalendar = xmlCal; + + ClonableHolder dest = factory.getMapperFacade().map(source, ClonableHolder.class); + Assert.assertEquals(source.value, dest.value); + Assert.assertNotSame(source.value, dest.value); + Assert.assertEquals(source.date, dest.date); + Assert.assertSame(source.date, dest.date); + Assert.assertEquals(source.calendar, dest.calendar); + Assert.assertSame(source.calendar, dest.calendar); + Assert.assertEquals(source.xmlCalendar, dest.xmlCalendar); + Assert.assertNotSame(source.xmlCalendar, dest.xmlCalendar); + + } + + + + public static class ClonableHolder { + public SampleCloneable value; + public Date date; + public java.sql.Timestamp timestamp; + public Calendar calendar; + public XMLGregorianCalendar xmlCalendar; + } + + + public static class SampleCloneable implements Cloneable { + private Long id; + + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Object clone() { + SampleCloneable clone; + try { + clone = (SampleCloneable) super.clone(); + clone.id = id; + } catch (CloneNotSupportedException e) { + throw new IllegalStateException(e); + } + + return clone; + } + + public boolean equals(Object that) { + return Objects.equals(id, ((SampleCloneable) that).id); + } + + public int hashCode() { + return Objects.hash(id); + } + + } + + public static class ComplexSource { + private ArrayOfDates someDate; + + public ComplexSource() {} + + public ComplexSource(ArrayOfDates someDate) { + this.someDate = someDate; + } + + public ArrayOfDates getSomeDate() { + return someDate; + } + + public void setSomeDate(ArrayOfDates someDate) { + this.someDate = someDate; + } + } + + public static class ArrayOfDates { + protected List dateHolder; + + public List getDateHolder() { + if (dateHolder == null) { + dateHolder = new ArrayList<>(); + } + return this.dateHolder; + } + } + + public static class SourceDateHolder { + private Date date; + + public SourceDateHolder() {} + + public SourceDateHolder(Date date) { + this.date = date; + } + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } + } + + public static class ComplexDest { + private List meaningfulDate = new ArrayList<>(); + + public List getMeaningfulDate() { + return meaningfulDate; + } + + public void setMeaningfulDate(List meaningfulDate) { + this.meaningfulDate = meaningfulDate; + } + } + + public static class DestDateHolder { + private Date date; + + public DestDateHolder() {} + + public DestDateHolder(Date date) { + this.date = date; + } + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/converter/ConstructorConverterTestCase.java b/core/src/test/java/ma/glasnost/orika/test/converter/ConstructorConverterTestCase.java new file mode 100644 index 00000000..ea5361d5 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/converter/ConstructorConverterTestCase.java @@ -0,0 +1,97 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.converter; + +import java.math.BigDecimal; +import java.net.URL; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.converter.builtin.ConstructorConverter; +import ma.glasnost.orika.test.MappingUtil; + +import org.junit.Test; +import org.junit.Assert; + + +/** + * ConstructorConverter will converter from one type to another if there + * exists a constructor for the destinationType with a single argument + * matching the type of the source. + * + * @author matt.deboer@gmail.com + * + */ +public class ConstructorConverterTestCase { + + @Test + public void testStringBasedConstructor() { + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(new ConstructorConverter()); + MapperFacade mapper = factory.getMapperFacade(); + + String urlString = "http://localhost:80/index.html"; + URL url = mapper.map(urlString, URL.class); + Assert.assertNotNull(url); + Assert.assertEquals(urlString, url.toExternalForm()); + } + + @Test + public void testPrimitiveConstructor() { + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(new ConstructorConverter()); + MapperFacade mapper = factory.getMapperFacade(); + + Double doubleValue = Double.valueOf("4.99"); + BigDecimal bd = mapper.map(doubleValue, BigDecimal.class); + Assert.assertNotNull(bd); + Assert.assertEquals(doubleValue, bd.doubleValue(), 0.0001); + } + + @Test + public void testRegisterdAsBuiltinConverterAndWorksWithCustomType() { + MapperFactory factory = MappingUtil.getMapperFactory(); + MapperFacade mapper = factory.getMapperFacade(); + + StringContainer strCont = mapper.map("test", StringContainer.class); + Assert.assertNotNull(strCont); + Assert.assertEquals("test", strCont.getString()); + } + + public static class StringContainer { + private String string; + + public StringContainer() { + super(); + } + + public StringContainer(String string) { + super(); + this.string = string; + } + + public String getString() { + return string; + } + + public void setString(String string) { + this.string = string; + } + + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/converter/ConverterInheritanceTestCase.java b/core/src/test/java/ma/glasnost/orika/test/converter/ConverterInheritanceTestCase.java new file mode 100644 index 00000000..8341264a --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/converter/ConverterInheritanceTestCase.java @@ -0,0 +1,119 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.converter; + +import ma.glasnost.orika.CustomConverter; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.MappingException; +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.metadata.TypeBuilder; +import ma.glasnost.orika.metadata.TypeFactory; +import ma.glasnost.orika.test.MappingUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class ConverterInheritanceTestCase { + + public static class ListConverter extends CustomConverter, PersonGroup> { + + public PersonGroup convert(Collection source, Type destinationType, MappingContext context) { + return new PersonGroup(source); + } + + } + + public static class Person { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + } + + public static class PersonGroup { + + private final List people; + + public PersonGroup(Collection people) { + this.people = new ArrayList<>(people); + } + + public List getPeople() { + return people; + } + } + + /** + * Note: mapping by raw type doesn't work, because there's no way to know at + * runtime that an ArrayList has been parameterized by 'Person'; it just + * looks like an ArrayList of 'Object' + */ + @Test(expected = MappingException.class) + public void testConverterInheritanceRaw() { + ArrayList people = new ArrayList<>(); + Person person = new Person(); + person.setName("A"); + people.add(person); + person = new Person(); + person.setName("B"); + people.add(person); + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(new ListConverter()); + + PersonGroup group = factory.getMapperFacade().map(people, PersonGroup.class); + Assert.assertNotNull(group); + Assert.assertTrue(people.containsAll(group.getPeople())); + Assert.assertTrue(group.getPeople().containsAll(people)); + } + + @Test + public void testConverterInheritanceGenerics() { + ArrayList people = new ArrayList<>(); + Person person = new Person(); + person.setName("A"); + people.add(person); + person = new Person(); + person.setName("B"); + people.add(person); + + Type> personCollectionType = new TypeBuilder>() { + }.build(); + Type personGroupType = TypeFactory.valueOf(PersonGroup.class); + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(new ListConverter()); + + PersonGroup group = factory.getMapperFacade().map(people, personCollectionType, personGroupType); + Assert.assertNotNull(group); + Assert.assertTrue(people.containsAll(group.getPeople())); + Assert.assertTrue(group.getPeople().containsAll(people)); + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/converter/ConverterResolutionTestCase.java b/core/src/test/java/ma/glasnost/orika/test/converter/ConverterResolutionTestCase.java new file mode 100644 index 00000000..2739bcc1 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/converter/ConverterResolutionTestCase.java @@ -0,0 +1,134 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.converter; + +import java.util.Calendar; +import java.util.Date; + +import ma.glasnost.orika.Converter; +import ma.glasnost.orika.CustomConverter; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.converter.ConverterFactory; +import ma.glasnost.orika.converter.builtin.BuiltinConverters; +import ma.glasnost.orika.converter.builtin.PassThroughConverter; +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.metadata.TypeFactory; +import ma.glasnost.orika.test.MappingUtil; + +import org.junit.Assert; +import org.junit.Test; + +/** + * This test case is intended to assert the resolution behavior for converters + * with respect to the order in which they are registered, and their relation to + * the source/destination types (w/respect to class hierarchy). + * + * @author matt.deboer@gmail.com + * + */ +public class ConverterResolutionTestCase { + + @Test + public void testResolveSingleConverter() { + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.getConverterFactory().registerConverter(new NameToStringConverter()); + + Converter converter = factory.getConverterFactory().getConverter(TypeFactory.valueOf(Name.class), + TypeFactory.valueOf(String.class)); + + Assert.assertEquals(NameToStringConverter.class, converter.getClass()); + } + + @Test + public void testResolveMultipleConverters() { + MapperFactory factory = MappingUtil.getMapperFactory(); + + ConverterFactory converterFactory = factory.getConverterFactory(); + converterFactory.registerConverter(new ExtendedNameToStringConverter()); + converterFactory.registerConverter(new NameToStringConverter()); + + Converter converter = converterFactory.getConverter(TypeFactory.valueOf(ExtendedName.class), + TypeFactory.valueOf(String.class)); + + Assert.assertEquals(ExtendedNameToStringConverter.class, converter.getClass()); + } + + @Test + public void testResolveMultipleConvertersOutOfOrder() { + MapperFactory factory = MappingUtil.getMapperFactory(); + + ConverterFactory converterFactory = factory.getConverterFactory(); + converterFactory.registerConverter(new NameToStringConverter()); + converterFactory.registerConverter(new ExtendedNameToStringConverter()); + + Converter converter = converterFactory.getConverter(TypeFactory.valueOf(ExtendedName.class), + TypeFactory.valueOf(String.class)); + + Assert.assertEquals(ExtendedNameToStringConverter.class, converter.getClass()); + } + + public static class Name { + public String first; + public String last; + public String middle; + } + + public static class ExtendedName extends Name { + public String title; + public String salutation; + } + + public static class NameToStringConverter extends CustomConverter { + + /* + * (non-Javadoc) + * + * @see ma.glasnost.orika.Converter#convert(java.lang.Object, + * ma.glasnost.orika.metadata.Type) + */ + public String convert(Name source, Type destinationType, MappingContext context) { + return source.first + " " + source.middle + " " + source.last; + } + } + + public static class ExtendedNameToStringConverter extends CustomConverter { + + /* + * (non-Javadoc) + * + * @see ma.glasnost.orika.Converter#convert(java.lang.Object, + * ma.glasnost.orika.metadata.Type) + */ + public String convert(ExtendedName source, Type destinationType, MappingContext context) { + return source.salutation + " " + source.first + " " + source.middle + " " + source.last + ", " + source.title; + } + } + + @Test + public void testResolveOverriddenConverter() { + PassThroughConverter cc = new PassThroughConverter(Date.class, Calendar.class); + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(cc); + BuiltinConverters.register(factory.getConverterFactory()); + Assert.assertSame(cc, factory.getConverterFactory().getConverter(TypeFactory.valueOf(Date.class), TypeFactory.valueOf(Date.class))); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/converter/ConverterTestCase.java b/core/src/test/java/ma/glasnost/orika/test/converter/ConverterTestCase.java new file mode 100644 index 00000000..b1e90d13 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/converter/ConverterTestCase.java @@ -0,0 +1,73 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.converter; + +import org.junit.Assert; +import org.junit.Test; + +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.test.MappingUtil; + +public class ConverterTestCase { + + @Test + public void testConvertLongString() { + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.getConverterFactory().registerConverter(new LongToStringConverter()); + + factory.classMap(A.class, B.class).field("id", "string") + .register(); + + + A source = new A(); + source.setId(42L); + + B destination = factory.getMapperFacade().map(source, B.class); + + Assert.assertEquals("42", destination.getString()); + + } + + public static class A { + private Long id; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + } + + public static class B { + private String string; + + public String getString() { + return string; + } + + public void setString(String string) { + this.string = string; + } + + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/converter/ConverterWithNestedPropertyTestCase.java b/core/src/test/java/ma/glasnost/orika/test/converter/ConverterWithNestedPropertyTestCase.java new file mode 100644 index 00000000..16c2285a --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/converter/ConverterWithNestedPropertyTestCase.java @@ -0,0 +1,169 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.converter; + +import ma.glasnost.orika.CustomConverter; +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.test.MappingUtil; + +import org.junit.Assert; +import org.junit.Test; + +public class ConverterWithNestedPropertyTestCase { + + @Test + public void testConverterWithNestedProperty() { + MapperFactory mapperFactory = MappingUtil.getMapperFactory(); + + mapperFactory.getConverterFactory().registerConverter(new CustomConverter() { + public String convert(Address source, Type destinationClass, MappingContext context) { + return source.getLine1() + " " + source.getLine2(); + } + }); + + mapperFactory.classMap(Order.class, OrderDTO.class).fieldMap("customer.address", "shippingAddress").add().byDefault().register(); + + Address address = new Address(); + address.setLine1("5 rue Blida"); + address.setLine2("Casablanca"); + + Customer customer = new Customer(); + customer.setName("Sidi Mohammed El Aatifi"); + customer.setAddress(address); + + Order order = new Order(); + order.setNumber("CPC6128"); + order.setCustomer(customer); + + MapperFacade mapperFacade = mapperFactory.getMapperFacade(); + OrderDTO orderDto = mapperFacade.map(order, OrderDTO.class); + + Assert.assertEquals(address.line1 + " " + address.line2, orderDto.getShippingAddress()); + } + + public static class Address { + + private String line1; + + private String line2; + + public String getLine1() { + return line1; + } + + public void setLine1(String line1) { + this.line1 = line1; + } + + public String getLine2() { + return line2; + } + + public void setLine2(String line2) { + this.line2 = line2; + } + + } + + public static class Customer { + + private String name; + + private Address address; + + 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 static class Order { + + private String number; + + private Customer customer; + + public String getNumber() { + return number; + } + + public void setNumber(String number) { + this.number = number; + } + + public Customer getCustomer() { + return customer; + } + + public void setCustomer(Customer customer) { + this.customer = customer; + } + + } + + public static class OrderDTO { + + public String getNumber() { + return number; + } + + public void setNumber(String number) { + this.number = number; + } + + public String getCustomerName() { + return customerName; + } + + public void setCustomerName(String customerName) { + this.customerName = customerName; + } + + public String getShippingAddress() { + return shippingAddress; + } + + public void setShippingAddress(String shippingAddress) { + this.shippingAddress = shippingAddress; + } + + private String number; + + private String customerName; + + private String shippingAddress; + + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/converter/DateAndTimeConvertersTestCase.java b/core/src/test/java/ma/glasnost/orika/test/converter/DateAndTimeConvertersTestCase.java new file mode 100644 index 00000000..ddd8d5dc --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/converter/DateAndTimeConvertersTestCase.java @@ -0,0 +1,336 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.converter; + +import java.sql.Time; +import java.sql.Timestamp; +import java.util.Calendar; +import java.util.Date; + +import javax.xml.datatype.XMLGregorianCalendar; + +import org.junit.Assert; +import org.junit.Test; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.converter.builtin.DateAndTimeConverters.DateToCalendarConverter; +import ma.glasnost.orika.converter.builtin.DateAndTimeConverters.DateToXmlGregorianCalendarConverter; +import ma.glasnost.orika.test.MappingUtil; + +/** + * DateAndTimeConverters provides a set of individual converters + * for conversion between the below listed enumeration of commonly used data/time + * representations: + *
    + *
  • java.util.Date + *
  • java.util.Calendar + *
  • java.lang.Long or long + *
  • javax.xml.datatype.XMLGregorianCalendar + *
+ * + * @author matt.deboer@gmail.com + * + */ +public class DateAndTimeConvertersTestCase { + + + @Test + public void testDateToCalendarConverter() { + MapperFactory factory = MappingUtil.getMapperFactory(); + MapperFacade mapper = factory.getMapperFacade(); + + Date now = new Date(); + Calendar cal = mapper.map(now, Calendar.class); + Assert.assertEquals(now, cal.getTime()); + + Date reverse = mapper.map(cal, Date.class); + Assert.assertEquals(now, reverse); + } + + @Test + public void testSqlDateToCalendarConverter() { + MapperFactory factory = MappingUtil.getMapperFactory(); + MapperFacade mapper = factory.getMapperFacade(); + + java.sql.Date now = new java.sql.Date(System.currentTimeMillis()); + Calendar cal = mapper.map(now, Calendar.class); + Assert.assertEquals(now.getTime(), cal.getTime().getTime()); + + Date reverse = mapper.map(cal, Date.class); + Assert.assertEquals(now, reverse); + } + + @Test + public void testDateToTimeConverter() { + MapperFactory factory = MappingUtil.getMapperFactory(); + MapperFacade mapper = factory.getMapperFacade(); + + Date now = new Date(); + Time time = mapper.map(now, Time.class); + Assert.assertEquals(now.getTime(), time.getTime()); + + Date reverse = mapper.map(time, Date.class); + Assert.assertEquals(now, reverse); + } + + @Test + public void testSqlDateToTimeConverter() { + MapperFactory factory = MappingUtil.getMapperFactory(); + MapperFacade mapper = factory.getMapperFacade(); + + java.sql.Date now = new java.sql.Date(System.currentTimeMillis()); + Time time = mapper.map(now, Time.class); + Assert.assertEquals(now.getTime(), time.getTime()); + + java.sql.Date reverse = mapper.map(time, java.sql.Date.class); + Assert.assertEquals(now, reverse); + } + + @Test + public void testSqlDateToDateConverter() { + MapperFactory factory = MappingUtil.getMapperFactory(); + MapperFacade mapper = factory.getMapperFacade(); + + java.sql.Date now = new java.sql.Date(System.currentTimeMillis()); + Date date = mapper.map(now, Date.class); + Assert.assertEquals(now.getTime(), date.getTime()); + + java.sql.Date reverse = mapper.map(date, java.sql.Date.class); + Assert.assertEquals(now, reverse); + } + + @Test + public void testDateToXmlGregorianCalendarConverter() { + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(new DateToXmlGregorianCalendarConverter()); + MapperFacade mapper = factory.getMapperFacade(); + + Date now = new Date(); + XMLGregorianCalendar xml = mapper.map(now, XMLGregorianCalendar.class); + Assert.assertEquals(now, xml.toGregorianCalendar().getTime()); + + Date reverse = mapper.map(xml, Date.class); + Assert.assertEquals(now, reverse); + } + + @Test + public void testTimeToXmlGregorianCalendarConverter() { + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(new DateToXmlGregorianCalendarConverter()); + MapperFacade mapper = factory.getMapperFacade(); + + Time now = new Time(System.currentTimeMillis()); + XMLGregorianCalendar xml = mapper.map(now, XMLGregorianCalendar.class); + Assert.assertEquals(now.getTime(), xml.toGregorianCalendar().getTime().getTime()); + + Date reverse = mapper.map(xml, Date.class); + Assert.assertEquals(now, reverse); + } + + @Test + public void testSqlDateToXmlGregorianCalendarConverter() { + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(new DateToXmlGregorianCalendarConverter()); + MapperFacade mapper = factory.getMapperFacade(); + + java.sql.Date now = new java.sql.Date(System.currentTimeMillis()); + XMLGregorianCalendar xml = mapper.map(now, XMLGregorianCalendar.class); + Assert.assertEquals(now.getTime(), xml.toGregorianCalendar().getTime().getTime()); + + java.sql.Date reverse = mapper.map(xml, java.sql.Date.class); + Assert.assertEquals(now, reverse); + } + + @Test + public void testTimeToCalendarConverter() { + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(new DateToCalendarConverter()); + MapperFacade mapper = factory.getMapperFacade(); + + Time now = new Time(System.currentTimeMillis()); + Calendar xml = mapper.map(now, Calendar.class); + Assert.assertEquals(now.getTime(), xml.getTime().getTime()); + + Date reverse = mapper.map(xml, Date.class); + Assert.assertEquals(now, reverse); + } + + + @Test + public void testCalendarToXmlGregorianCalendarConverter() { + MapperFactory factory = MappingUtil.getMapperFactory(); + MapperFacade mapper = factory.getMapperFacade(); + + Calendar cal = Calendar.getInstance(); + XMLGregorianCalendar xml = mapper.map(cal, XMLGregorianCalendar.class); + Assert.assertEquals(cal.getTime(), xml.toGregorianCalendar().getTime()); + + Calendar reverse = mapper.map(xml, Calendar.class); + Assert.assertEquals(cal, reverse); + } + + @Test + public void testLongToXmlGregorianCalendarConverter() { + MapperFactory factory = MappingUtil.getMapperFactory(); + MapperFacade mapper = factory.getMapperFacade(); + + long now = System.currentTimeMillis(); + XMLGregorianCalendar xml = mapper.map(now, XMLGregorianCalendar.class); + + Assert.assertEquals(now, xml.toGregorianCalendar().getTimeInMillis()); + + long reverse = mapper.map(xml, Long.class); + Assert.assertEquals(now, reverse); + } + + @Test + public void testLongToDateConverter() { + MapperFactory factory = MappingUtil.getMapperFactory(); + MapperFacade mapper = factory.getMapperFacade(); + + long now = System.currentTimeMillis(); + Date date = mapper.map(now, Date.class); + Assert.assertEquals(now, date.getTime()); + + long reverse = mapper.map(date, Long.class); + Assert.assertEquals(now, reverse); + } + + @Test + public void testLongToTimeConverter() { + MapperFactory factory = MappingUtil.getMapperFactory(); + MapperFacade mapper = factory.getMapperFacade(); + + long now = System.currentTimeMillis(); + Time date = mapper.map(now, Time.class); + Assert.assertEquals(now, date.getTime()); + + long reverse = mapper.map(date, Long.class); + Assert.assertEquals(now, reverse); + } + + @Test + public void testLongToSqlDateConverter() { + MapperFactory factory = MappingUtil.getMapperFactory(); + MapperFacade mapper = factory.getMapperFacade(); + + long now = System.currentTimeMillis(); + java.sql.Date date = mapper.map(now, java.sql.Date.class); + Assert.assertEquals(now, date.getTime()); + + long reverse = mapper.map(date, Long.class); + Assert.assertEquals(now, reverse); + } + + @Test + public void testLongToCalendarConverter() { + MapperFactory factory = MappingUtil.getMapperFactory(); + MapperFacade mapper = factory.getMapperFacade(); + + long now = System.currentTimeMillis(); + Calendar cal = mapper.map(now, Calendar.class); + Assert.assertEquals(now, cal.getTimeInMillis()); + + long reverse = mapper.map(cal, Long.class); + Assert.assertEquals(now, reverse); + } + + @Test + public void testLongToTimestampConverter() { + MapperFactory factory = MappingUtil.getMapperFactory(); + MapperFacade mapper = factory.getMapperFacade(); + + long now = System.currentTimeMillis(); + Timestamp tstamp = mapper.map(now, Timestamp.class); + Assert.assertEquals(now, tstamp.getTime()); + + long reverse = mapper.map(tstamp, Long.class); + Assert.assertEquals(now, reverse); + } + + + @Test + public void testTimestampToXmlGregorianCalendarConverter() { + MapperFactory factory = MappingUtil.getMapperFactory(); + MapperFacade mapper = factory.getMapperFacade(); + + Timestamp now = new Timestamp(System.currentTimeMillis()); + XMLGregorianCalendar xml = mapper.map(now, XMLGregorianCalendar.class); + + Assert.assertEquals(now.getTime(), xml.toGregorianCalendar().getTimeInMillis()); + + Timestamp reverse = mapper.map(xml, Timestamp.class); + Assert.assertEquals(now, reverse); + } + + @Test + public void testTimestampToDateConverter() { + MapperFactory factory = MappingUtil.getMapperFactory(); + MapperFacade mapper = factory.getMapperFacade(); + + Timestamp now = new Timestamp(System.currentTimeMillis()); + Date date = mapper.map(now, Date.class); + Assert.assertEquals(now.getTime(), date.getTime()); + + Timestamp reverse = mapper.map(date, Timestamp.class); + Assert.assertEquals(now, reverse); + } + + @Test + public void testTimestampToTimeConverter() { + MapperFactory factory = MappingUtil.getMapperFactory(); + MapperFacade mapper = factory.getMapperFacade(); + + Timestamp now = new Timestamp(System.currentTimeMillis()); + Time date = mapper.map(now, Time.class); + Assert.assertEquals(now.getTime(), date.getTime()); + + Timestamp reverse = mapper.map(date, Timestamp.class); + Assert.assertEquals(now, reverse); + } + + @Test + public void testTimestampToSqlDateConverter() { + MapperFactory factory = MappingUtil.getMapperFactory(); + MapperFacade mapper = factory.getMapperFacade(); + + Timestamp now = new Timestamp(System.currentTimeMillis()); + java.sql.Date date = mapper.map(now, java.sql.Date.class); + Assert.assertEquals(now.getTime(), date.getTime()); + + Timestamp reverse = mapper.map(date, Timestamp.class); + Assert.assertEquals(now, reverse); + } + + @Test + public void testTimestampToCalendarConverter() { + MapperFactory factory = MappingUtil.getMapperFactory(); + MapperFacade mapper = factory.getMapperFacade(); + + Timestamp now = new Timestamp(System.currentTimeMillis()); + Calendar cal = mapper.map(now, Calendar.class); + Assert.assertEquals(now.getTime(), cal.getTimeInMillis()); + + Timestamp reverse = mapper.map(cal, Timestamp.class); + Assert.assertEquals(now, reverse); + } + + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/converter/FieldLevelConverterClasses.java b/core/src/test/java/ma/glasnost/orika/test/converter/FieldLevelConverterClasses.java new file mode 100644 index 00000000..92007554 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/converter/FieldLevelConverterClasses.java @@ -0,0 +1,62 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.converter; + +import java.util.Date; + +public class FieldLevelConverterClasses { + + public static class A { + private String date; + + public String getDate() { + return date; + } + + public void setDate(String date) { + this.date = date; + } + } + + // Date format dd/MM/yyyy + public static class B { + private Date date; + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } + } + + // Date format dd-MM-yyyy + public static class C { + private Date date; + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/converter/FieldLevelConverterTestCase.java b/core/src/test/java/ma/glasnost/orika/test/converter/FieldLevelConverterTestCase.java new file mode 100644 index 00000000..cc815431 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/converter/FieldLevelConverterTestCase.java @@ -0,0 +1,66 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.converter; + +import java.text.SimpleDateFormat; +import java.util.Date; + +import org.junit.Assert; +import org.junit.Test; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.converter.ConverterFactory; +import ma.glasnost.orika.converter.builtin.DateToStringConverter; +import ma.glasnost.orika.test.MappingUtil; +import ma.glasnost.orika.test.converter.FieldLevelConverterClasses.A; +import ma.glasnost.orika.test.converter.FieldLevelConverterClasses.B; +import ma.glasnost.orika.test.converter.FieldLevelConverterClasses.C; + +public class FieldLevelConverterTestCase { + + @Test + public void testDateToString() { + MapperFactory factory = MappingUtil.getMapperFactory(); + + ConverterFactory converterFactory = factory.getConverterFactory(); + converterFactory.registerConverter("dateConverter1", new DateToStringConverter("dd/MM/yyyy")); + converterFactory.registerConverter("dateConverter2", new DateToStringConverter("dd-MM-yyyy")); + + factory.registerClassMap(factory.classMap(A.class, B.class).fieldMap("date").converter("dateConverter1").add().toClassMap()); + factory.registerClassMap(factory.classMap(A.class, C.class).fieldMap("date").converter("dateConverter2").add().toClassMap()); + + MapperFacade mapperFacade = factory.getMapperFacade(); + + C c = new C(); + c.setDate(new Date()); + + A a = mapperFacade.map(c, A.class); + + Assert.assertEquals(new SimpleDateFormat("dd-MM-yyyy").format(c.getDate()), a.getDate()); + + B b = new B(); + b.setDate(new Date()); + + a = mapperFacade.map(b, A.class); + + Assert.assertEquals(new SimpleDateFormat("dd/MM/yyyy").format(b.getDate()), a.getDate()); + + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/converter/FromStringConverterTestCase.java b/core/src/test/java/ma/glasnost/orika/test/converter/FromStringConverterTestCase.java new file mode 100644 index 00000000..9754421a --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/converter/FromStringConverterTestCase.java @@ -0,0 +1,73 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.converter; + +import org.junit.Assert; +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.converter.builtin.FromStringConverter; +import ma.glasnost.orika.test.MappingUtil; + +import org.junit.Test; + + +/** + * + */ +public class FromStringConverterTestCase { + + @Test + public void testConvertToEnum() { + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(new FromStringConverter()); + MapperFacade mapper = factory.getMapperFacade(); + + Fruit fruit = mapper.map("TOMATO", Fruit.class); + Assert.assertEquals(Fruit.TOMATO, fruit); + + } + + @Test + public void testConvertToPrimitive() { + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(new FromStringConverter()); + MapperFacade mapper = factory.getMapperFacade(); + + int age = mapper.map("21", int.class); + Assert.assertEquals(21, age); + } + + @Test + public void testConvertToWrapper() { + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(new FromStringConverter()); + MapperFacade mapper = factory.getMapperFacade(); + + Integer age = mapper.map("21", Integer.class); + Assert.assertEquals(Integer.valueOf(21), age); + } + + enum Fruit { + APPLE, + ORANGE, + BANANA, + TOMATO + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/converter/LongToStringConverter.java b/core/src/test/java/ma/glasnost/orika/test/converter/LongToStringConverter.java new file mode 100644 index 00000000..9efa4720 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/converter/LongToStringConverter.java @@ -0,0 +1,43 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.converter; + +import ma.glasnost.orika.CustomConverter; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.metadata.Type; + +public class LongToStringConverter extends CustomConverter { + + public boolean canConvert(Class sourceClass, Class destinationClass) { + return Long.class.equals(sourceClass) && String.class.equals(destinationClass); + } + + /* + * (non-Javadoc) + * + * @see ma.glasnost.orika.Converter#convert(java.lang.Object, + * ma.glasnost.orika.metadata.Type) + */ + public String convert(Long source, Type destinationType, MappingContext context) { + if (source != null) { + return source.toString(); + } + return null; + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/converter/NumericConvertersTestCase.java b/core/src/test/java/ma/glasnost/orika/test/converter/NumericConvertersTestCase.java new file mode 100644 index 00000000..6eb1d0fb --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/converter/NumericConvertersTestCase.java @@ -0,0 +1,399 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.converter; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingException; +import ma.glasnost.orika.converter.builtin.NumericConverters.BigDecimalToDoubleConverter; +import ma.glasnost.orika.converter.builtin.NumericConverters.BigDecimalToFloatConverter; +import ma.glasnost.orika.converter.builtin.NumericConverters.BigIntegerToIntegerConverter; +import ma.glasnost.orika.converter.builtin.NumericConverters.BigIntegerToLongConverter; +import ma.glasnost.orika.converter.builtin.NumericConverters.DoubleToIntegerConverter; +import ma.glasnost.orika.converter.builtin.NumericConverters.DoubleToLongConverter; +import ma.glasnost.orika.converter.builtin.NumericConverters.DoubleToShortConverter; +import ma.glasnost.orika.converter.builtin.NumericConverters.FloatToIntegerConverter; +import ma.glasnost.orika.converter.builtin.NumericConverters.FloatToLongConverter; +import ma.glasnost.orika.converter.builtin.NumericConverters.FloatToShortConverter; +import ma.glasnost.orika.converter.builtin.NumericConverters.IntegerToShortConverter; +import ma.glasnost.orika.converter.builtin.NumericConverters.LongToIntegerConverter; +import ma.glasnost.orika.converter.builtin.NumericConverters.LongToShortConverter; +import ma.glasnost.orika.test.MappingUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.math.BigDecimal; +import java.math.BigInteger; + +/** + * DateAndTimeConverters provides a set of individual converters for conversion + * between the below listed enumeration of commonly used data/time + * representations: + *
    + *
  • java.util.Date + *
  • java.util.Calendar + *
  • java.lang.Long or long + *
  • javax.xml.datatype.XMLGregorianCalendar + *
+ * + * @author matt.deboer@gmail.com + * + */ +public class NumericConvertersTestCase { + + private static final double DELTA = 0.000000001; + + @Test + public void testBigDecimalToDoubleConverter() { + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(new BigDecimalToDoubleConverter()); + MapperFacade mapper = factory.getMapperFacade(); + + BigDecimal bd = new BigDecimal("5423.51478"); + Double db = mapper.map(bd, Double.class); + Assert.assertEquals(bd.doubleValue(), db, 0.00001d); + + BigDecimal reverse = mapper.map(db, BigDecimal.class); + Assert.assertEquals(bd.doubleValue(), reverse.doubleValue(), 0.00001d); + } + + @Test + public void testBigDecimalToFloatConverter() { + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(new BigDecimalToFloatConverter()); + MapperFacade mapper = factory.getMapperFacade(); + + BigDecimal bd = new BigDecimal("5423.51"); + Float ft = mapper.map(bd, Float.class); + Assert.assertEquals(bd.floatValue(), ft, 0.01d); + + BigDecimal reverse = mapper.map(ft, BigDecimal.class); + Assert.assertEquals(bd.doubleValue(), reverse.doubleValue(), 0.01d); + } + + @Test + public void testBigIntegerToLongConverter() { + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(new BigIntegerToLongConverter(false)); + MapperFacade mapper = factory.getMapperFacade(); + + BigInteger bi = new BigInteger("" + Long.MAX_VALUE); + Long lg = mapper.map(bi, Long.class); + Assert.assertEquals(bi.longValue(), lg.longValue()); + + BigInteger reverse = mapper.map(lg, BigInteger.class); + Assert.assertEquals(bi.longValue(), reverse.longValue()); + } + + @Test + public void testBigIntegerToIntegerConverter() { + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(new BigIntegerToIntegerConverter(false)); + MapperFacade mapper = factory.getMapperFacade(); + + BigInteger bi = new BigInteger("" + Integer.MAX_VALUE); + Integer i = mapper.map(bi, Integer.class); + Assert.assertEquals(bi.longValue(), i.longValue()); + + BigInteger reverse = mapper.map(i, BigInteger.class); + Assert.assertEquals(bi.longValue(), reverse.longValue()); + } + + @Test(expected = MappingException.class) + public void testBigIntegerToLongConverter_Overflow() { + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(new BigIntegerToLongConverter(false)); + MapperFacade mapper = factory.getMapperFacade(); + + BigInteger bi = new BigInteger("1" + Long.MAX_VALUE); + Long lg = mapper.map(bi, Long.class); + Assert.assertEquals(bi.longValue(), lg.longValue()); + + BigInteger reverse = mapper.map(lg, BigInteger.class); + Assert.assertEquals(bi.longValue(), reverse.longValue()); + } + + @Test(expected = MappingException.class) + public void testBigIntegerToIntegerConverter_Overflow() { + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(new BigIntegerToIntegerConverter(false)); + MapperFacade mapper = factory.getMapperFacade(); + + BigInteger bi = new BigInteger("1" + Long.MAX_VALUE); + Integer i = mapper.map(bi, Integer.class); + Assert.assertEquals(bi.longValue(), i.longValue()); + + BigInteger reverse = mapper.map(i, BigInteger.class); + Assert.assertEquals(bi.longValue(), reverse.longValue()); + } + + @Test + public void testLongToShortConverter() { + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(new LongToShortConverter(false)); + MapperFacade mapper = factory.getMapperFacade(); + + Long value = (long) Short.MAX_VALUE; + Short result = mapper.map(value, Short.class); + Assert.assertEquals(value.longValue(), result.longValue()); + + Long reverse = mapper.map(result, Long.class); + Assert.assertEquals(result.longValue(), reverse.longValue()); + } + + @Test + public void testLongToIntegerConverter() { + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(new LongToIntegerConverter(false)); + MapperFacade mapper = factory.getMapperFacade(); + + Long value = (long) Integer.MAX_VALUE; + Integer result = mapper.map(value, Integer.class); + Assert.assertEquals(value.longValue(), result.longValue()); + + Long reverse = mapper.map(result, Long.class); + Assert.assertEquals(result.longValue(), reverse.longValue()); + } + + @Test + public void testIntegerToShortConverter() { + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(new IntegerToShortConverter(false)); + MapperFacade mapper = factory.getMapperFacade(); + + Integer value = (int) Short.MAX_VALUE; + Short result = mapper.map(value, Short.class); + Assert.assertEquals(value.intValue(), result.intValue()); + + Integer reverse = mapper.map(result, Integer.class); + Assert.assertEquals(result.intValue(), reverse.intValue()); + } + + @Test + public void testDoubleToShortConverter() { + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(new DoubleToShortConverter(false)); + MapperFacade mapper = factory.getMapperFacade(); + + Double value = (double) Short.MAX_VALUE; + Short result = mapper.map(value, Short.class); + Assert.assertEquals(value, result.doubleValue(), DELTA); + + Double reverse = mapper.map(result, Double.class); + Assert.assertEquals(result.doubleValue(), reverse, DELTA); + } + + @Test + public void testDoubleToIntegerConverter() { + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(new DoubleToIntegerConverter(false)); + MapperFacade mapper = factory.getMapperFacade(); + + Double value = (double) Integer.MAX_VALUE; + Integer result = mapper.map(value, Integer.class); + Assert.assertEquals(value, result.doubleValue(), DELTA); + + Double reverse = mapper.map(result, Double.class); + Assert.assertEquals(result.doubleValue(), reverse, DELTA); + } + + @Test + public void testDoubleToLongConverter() { + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(new DoubleToLongConverter(false)); + MapperFacade mapper = factory.getMapperFacade(); + + Double value = (double) Long.MAX_VALUE; + Long result = mapper.map(value, Long.class); + Assert.assertEquals(value, result.doubleValue(), DELTA); + + Double reverse = mapper.map(result, Double.class); + Assert.assertEquals(result.doubleValue(), reverse, DELTA); + } + + @Test + public void testFloatToShortConverter() { + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(new FloatToShortConverter(false)); + MapperFacade mapper = factory.getMapperFacade(); + + Float value = (float) Short.MAX_VALUE; + Short result = mapper.map(value, Short.class); + Assert.assertEquals(value, result.floatValue(), DELTA); + + Float reverse = mapper.map(result, Float.class); + Assert.assertEquals(result.floatValue(), reverse, DELTA); + } + + @Test + public void testFloatToIntegerConverter() { + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(new FloatToIntegerConverter(false)); + MapperFacade mapper = factory.getMapperFacade(); + + Float value = (float) Integer.MAX_VALUE; + Integer result = mapper.map(value, Integer.class); + Assert.assertEquals(value, result.floatValue(), DELTA); + + Float reverse = mapper.map(result, Float.class); + Assert.assertEquals(result.floatValue(), reverse, DELTA); + } + + @Test + public void testFloatToLongConverter() { + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(new FloatToLongConverter(false)); + MapperFacade mapper = factory.getMapperFacade(); + + Float value = (float) Long.MAX_VALUE; + Long result = mapper.map(value, Long.class); + Assert.assertEquals(value, result.floatValue(), DELTA); + + Float reverse = mapper.map(result, Float.class); + Assert.assertEquals(result.floatValue(), reverse, DELTA); + } + + // ~ overflow exceptions + + @Test(expected = MappingException.class) + public void testLongToShortConverter_overflow() { + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(new LongToShortConverter(false)); + MapperFacade mapper = factory.getMapperFacade(); + + Long value = (long) Short.MAX_VALUE + 1; + Short result = mapper.map(value, Short.class); + Assert.assertEquals(value.longValue(), result.longValue()); + + Long reverse = mapper.map(result, Long.class); + Assert.assertEquals(result.longValue(), reverse.longValue()); + } + + @Test(expected = MappingException.class) + public void testLongToIntegerConverter_overflow() { + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(new LongToIntegerConverter(false)); + MapperFacade mapper = factory.getMapperFacade(); + + Long value = (long) Integer.MAX_VALUE + 1; + Integer result = mapper.map(value, Integer.class); + Assert.assertEquals(value.longValue(), result.longValue()); + + Long reverse = mapper.map(result, Long.class); + Assert.assertEquals(result.longValue(), reverse.longValue()); + } + + @Test(expected = MappingException.class) + public void testIntegerToShortConverter_overflow() { + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(new IntegerToShortConverter(false)); + MapperFacade mapper = factory.getMapperFacade(); + + Integer value = Short.MAX_VALUE + 1; + Short result = mapper.map(value, Short.class); + Assert.assertEquals(value.intValue(), result.intValue()); + + Integer reverse = mapper.map(result, Integer.class); + Assert.assertEquals(result.intValue(), reverse.intValue()); + } + + @Test(expected = MappingException.class) + public void testDoubleToShortConverter_overflow() { + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(new DoubleToShortConverter(false)); + MapperFacade mapper = factory.getMapperFacade(); + + Double value = (double) Short.MAX_VALUE + 1; + Short result = mapper.map(value, Short.class); + Assert.assertEquals(value, result.doubleValue(), DELTA); + + Double reverse = mapper.map(result, Double.class); + Assert.assertEquals(result.doubleValue(), reverse, DELTA); + } + + @Test(expected = MappingException.class) + public void testDoubleToIntegerConverter_overflow() { + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(new DoubleToIntegerConverter(false)); + MapperFacade mapper = factory.getMapperFacade(); + + Double value = (double) Integer.MAX_VALUE + 1; + Integer result = mapper.map(value, Integer.class); + Assert.assertEquals(value, result.doubleValue(), DELTA); + + Double reverse = mapper.map(result, Double.class); + Assert.assertEquals(result.doubleValue(), reverse, DELTA); + } + + @Test(expected = MappingException.class) + public void testDoubleToLongConverter_overflow() { + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(new DoubleToLongConverter(false)); + MapperFacade mapper = factory.getMapperFacade(); + + Double value = Long.MAX_VALUE + 10000.0; + Long result = mapper.map(value, Long.class); + Assert.assertEquals(value, result.doubleValue(), DELTA); + + Double reverse = mapper.map(result, Double.class); + Assert.assertEquals(result.doubleValue(), reverse, DELTA); + } + + @Test(expected = MappingException.class) + public void testFloatToShortConverter_overflow() { + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(new FloatToShortConverter(false)); + MapperFacade mapper = factory.getMapperFacade(); + + Float value = (Short.MAX_VALUE) * 1.1f; + Short result = mapper.map(value, Short.class); + Assert.assertEquals(value, result.floatValue(), DELTA); + + Float reverse = mapper.map(result, Float.class); + Assert.assertEquals(result.floatValue(), reverse, DELTA); + } + + @Test(expected = MappingException.class) + public void testFloatToIntegerConverter_overflow() { + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(new FloatToIntegerConverter(false)); + MapperFacade mapper = factory.getMapperFacade(); + + Float value = (Integer.MAX_VALUE) * 1.1f; + Integer result = mapper.map(value, Integer.class); + Assert.assertEquals(value, result.floatValue(), DELTA); + + Float reverse = mapper.map(result, Float.class); + Assert.assertEquals(result.floatValue(), reverse, DELTA); + } + + @Test(expected = MappingException.class) + public void testFloatToLongConverter_overflow() { + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(new FloatToLongConverter(false)); + MapperFacade mapper = factory.getMapperFacade(); + + Float value = (Long.MAX_VALUE) * 1.1f; + Long result = mapper.map(value, Long.class); + Assert.assertEquals(value, result.floatValue(), DELTA); + + Float reverse = mapper.map(result, Float.class); + Assert.assertEquals(result.floatValue(), reverse, DELTA); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/converter/PassThroughConverterTestCase.java b/core/src/test/java/ma/glasnost/orika/test/converter/PassThroughConverterTestCase.java new file mode 100644 index 00000000..7fddc7dd --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/converter/PassThroughConverterTestCase.java @@ -0,0 +1,323 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.converter; + +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.converter.builtin.PassThroughConverter; +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.metadata.TypeBuilder; +import ma.glasnost.orika.test.MappingUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Objects; + +public class PassThroughConverterTestCase { + + @Test + public void testPassThroughConverter() { + + PassThroughConverter ptc = new PassThroughConverter(A.class); + + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.getConverterFactory().registerConverter(ptc); + + A a = new A(); + a.setId(42L); + B b = new B(); + b.setString("Hello"); + C c = new C(); + c.setA(a); + c.setB(b); + + D d = factory.getMapperFacade().map(c, D.class); + + Assert.assertEquals(c.getA(), d.getA()); + Assert.assertEquals(c.getB(), d.getB()); + Assert.assertSame(c.getA(), d.getA()); + Assert.assertNotSame(c.getB(), d.getB()); + + } + + @Test + public void testPassThroughConverterGenerics() { + + /* + * Note: we register the generic Holder and pass it a + * Holder> we expect that it should be passed-through + */ + PassThroughConverter ptc = new PassThroughConverter(new TypeBuilder>() { + }.build()); + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.getConverterFactory().registerConverter(ptc); + + B b = new B(); + b.setString("Hello"); + Holder holder = new Holder<>(); + holder.setHeld(b); + Wrapper> wrapper = new Wrapper<>(); + wrapper.setHeld(holder); + + Type>> fromType = new TypeBuilder>>() { + }.build(); + Type>> toType = new TypeBuilder>>() { + }.build(); + + Decorator> d = factory.getMapperFacade().map(wrapper, fromType, toType); + + Assert.assertEquals(wrapper.getHeld(), d.getHeld()); + Assert.assertSame(wrapper.getHeld(), d.getHeld()); + } + + @Test + public void testPassThroughConverterGenerics2() { + + /* + * Note: we register the specific Holder> and pass it a + * Holder>; we expect that it should not be passed through + */ + PassThroughConverter ptc = new PassThroughConverter(new TypeBuilder>>() { + }.build()); + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.getConverterFactory().registerConverter(ptc); + + B b = new B(); + b.setString("Hello"); + Holder holder = new Holder<>(); + holder.setHeld(b); + Wrapper> wrapper = new Wrapper<>(); + wrapper.setHeld(holder); + + Type>> fromType = new TypeBuilder>>() { + }.build(); + Type>> toType = new TypeBuilder>>() { + }.build(); + + Decorator> d = factory.getMapperFacade().map(wrapper, fromType, toType); + + Assert.assertEquals(wrapper.getHeld(), d.getHeld()); + Assert.assertNotSame(wrapper.getHeld(), d.getHeld()); + } + + public static class A { + private Long id; + + public Long getId() { + return id; + } + + public void setId(final Long id) { + this.id = id; + } + + @Override + public boolean equals(final Object that) { + return Objects.equals(id, ((A) that).id); + } + + @Override + public int hashCode() { + return Objects.hash(id); + } + + } + + public static class B { + private String string; + + public String getString() { + return string; + } + + public void setString(final String string) { + this.string = string; + } + + @Override + public boolean equals(final Object that) { + return Objects.equals(string, ((B) that).string); + } + + @Override + public int hashCode() { + return Objects.hash(string); + } + + } + + public static class C { + + private A a; + private B b; + + public A getA() { + return a; + } + + public void setA(final A a) { + this.a = a; + } + + public B getB() { + return b; + } + + public void setB(final B b) { + this.b = b; + } + + @Override + public boolean equals(final Object that) { + return Objects.equals(a, ((C) that).a) && Objects.equals(b, ((C) that).b); + } + + @Override + public int hashCode() { + return Objects.hash(a,b); + } + } + + public static class D { + + private A a; + private B b; + + public A getA() { + return a; + } + + public void setA(final A a) { + this.a = a; + } + + public B getB() { + return b; + } + + public void setB(final B b) { + this.b = b; + } + + @Override + public boolean equals(final Object that) { + return Objects.equals(a, ((D) that).a) && Objects.equals(b, ((D) that).b); + } + + @Override + public int hashCode() { + return Objects.hash(a,b); + } + } + + public static class Holder { + + private T held; + + public T getHeld() { + return held; + } + + public void setHeld(final T held) { + this.held = held; + } + + @Override + public boolean equals(final Object that) { + return Objects.equals(held, ((Holder) that).held); + } + + @Override + public int hashCode() { + return Objects.hash(held); + } + } + + public static class Container { + + private T held; + + public T getHeld() { + return held; + } + + public void setHeld(final T held) { + this.held = held; + } + + @Override + public boolean equals(final Object that) { + return Objects.equals(held, ((Container) that).held); + } + + @Override + public int hashCode() { + return Objects.hash(held); + } + } + + public static class Wrapper { + + private T held; + + public T getHeld() { + return held; + } + + public void setHeld(final T held) { + this.held = held; + } + + @Override + public boolean equals(final Object that) { + return Objects.equals(held, ((Wrapper) that).held); + } + + @Override + public int hashCode() { + return Objects.hash(held); + } + } + + public static class Decorator { + + private T held; + + public T getHeld() { + return held; + } + + public void setHeld(final T held) { + this.held = held; + } + + @Override + public boolean equals(final Object that) { + return Objects.equals(held, ((Decorator) that).held); + } + + @Override + public int hashCode() { + return Objects.hash(held); + } + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/converter/PrimitiveConversionTestCase.java b/core/src/test/java/ma/glasnost/orika/test/converter/PrimitiveConversionTestCase.java new file mode 100644 index 00000000..63aac0cd --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/converter/PrimitiveConversionTestCase.java @@ -0,0 +1,86 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.converter; + +import java.math.BigDecimal; + +import ma.glasnost.orika.CustomConverter; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.test.MappingUtil; + +import org.junit.Assert; +import org.junit.Test; + +public class PrimitiveConversionTestCase { + + @Test + public void testPrimitiveToWrapper() { + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(new CustomConverter() { + + public BigDecimal convert(Double source, Type destinationType, MappingContext context) { + return BigDecimal.valueOf(source); + } + }); + + factory.getConverterFactory().registerConverter(new CustomConverter() { + + public Double convert(BigDecimal source, Type destinationType, MappingContext context) { + return source.doubleValue(); + } + }); + + factory.classMap(A.class, B.class).byDefault().register(); + + A source = new A(); + source.setValue(BigDecimal.TEN); + + B target = factory.getMapperFacade().map(source, B.class); + + Assert.assertTrue(target.getValue() == 10.0); + } + + public static class A { + private BigDecimal value; + + public BigDecimal getValue() { + return value; + } + + public void setValue(BigDecimal value) { + this.value = value; + } + + } + + public static class B { + private double value; + + public double getValue() { + return value; + } + + public void setValue(double value) { + this.value = value; + } + + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/converter/ToStringConverterTestCase.java b/core/src/test/java/ma/glasnost/orika/test/converter/ToStringConverterTestCase.java new file mode 100644 index 00000000..d81976c8 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/converter/ToStringConverterTestCase.java @@ -0,0 +1,55 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.converter; + +import java.util.Date; + +import org.junit.Assert; +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingException; +import ma.glasnost.orika.converter.builtin.ToStringConverter; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.test.MappingUtil; + +import org.junit.Test; + + +public class ToStringConverterTestCase { + + @Test(expected=MappingException.class) + public void testToString_withoutConverter() { + MapperFactory factory = new DefaultMapperFactory.Builder().useBuiltinConverters(false).build(); + MapperFacade mapper = factory.getMapperFacade(); + + Date now = new Date(); + String string = mapper.map(now, String.class); + Assert.assertFalse(now.toString().equals(string)); + } + + @Test + public void testToString() { + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(new ToStringConverter()); + MapperFacade mapper = factory.getMapperFacade(); + + Date now = new Date(); + String string = mapper.map(now, String.class); + Assert.assertEquals(now.toString(), string); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/crossfeatures/PolicyElementsTestCase.java b/core/src/test/java/ma/glasnost/orika/test/crossfeatures/PolicyElementsTestCase.java new file mode 100644 index 00000000..085b4a1a --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/crossfeatures/PolicyElementsTestCase.java @@ -0,0 +1,117 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.crossfeatures; + +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.test.MappingUtil; +import ma.glasnost.orika.test.crossfeatures.PolicyElementsTestCaseClasses.CustomerElement; +import ma.glasnost.orika.test.crossfeatures.PolicyElementsTestCaseClasses.CustomerElementDTO; +import ma.glasnost.orika.test.crossfeatures.PolicyElementsTestCaseClasses.OneOtherElement; +import ma.glasnost.orika.test.crossfeatures.PolicyElementsTestCaseClasses.OneOtherElementDTO; +import ma.glasnost.orika.test.crossfeatures.PolicyElementsTestCaseClasses.OtherElement; +import ma.glasnost.orika.test.crossfeatures.PolicyElementsTestCaseClasses.OtherElementDTO; +import ma.glasnost.orika.test.crossfeatures.PolicyElementsTestCaseClasses.Policy; +import ma.glasnost.orika.test.crossfeatures.PolicyElementsTestCaseClasses.PolicyDTO; +import ma.glasnost.orika.test.crossfeatures.PolicyElementsTestCaseClasses.PolicyElement; +import ma.glasnost.orika.test.crossfeatures.PolicyElementsTestCaseClasses.PolicyElementDTO; +import ma.glasnost.orika.test.crossfeatures.PolicyElementsTestCaseClasses.PolicyElementProxy; +import ma.glasnost.orika.test.crossfeatures.PolicyElementsTestCaseClasses.ProductElement; +import ma.glasnost.orika.test.crossfeatures.PolicyElementsTestCaseClasses.ProductElementDTO; +import ma.glasnost.orika.unenhance.UnenhanceStrategy; +import org.junit.Assert; +import org.junit.Test; + +import java.util.HashSet; +import java.util.Set; + +public class PolicyElementsTestCase { + + @Test + public void test() { + MapperFactory factory = MappingUtil.getMapperFactory(); + configureMapperFactory(factory); + + Policy policy = new Policy(); + Set elements = new HashSet<>(); + elements.add(new CustomerElement()); + elements.add(new ProductElement()); + elements.add(new OtherElement()); + elements.add(new OneOtherElement()); + + policy.setElements(elements); + + PolicyDTO dto = factory.getMapperFacade().map(policy, PolicyDTO.class); + + Assert.assertEquals(elements.size(), dto.getElements().size()); + } + + private void configureMapperFactory(MapperFactory factory) { + + factory.registerClassMap(factory.classMap(Policy.class, PolicyDTO.class).byDefault().toClassMap()); + factory.registerClassMap(factory.classMap(CustomerElement.class, CustomerElementDTO.class).byDefault().toClassMap()); + factory.registerClassMap(factory.classMap(ProductElement.class, ProductElementDTO.class).byDefault().toClassMap()); + factory.registerClassMap(factory.classMap(OtherElement.class, OtherElementDTO.class).byDefault().toClassMap()); + factory.registerClassMap(factory.classMap(OneOtherElement.class, OneOtherElementDTO.class).byDefault().toClassMap()); + } + + @Test + public void testHibernateProxyLike() { + MapperFactory factory = new DefaultMapperFactory.Builder().unenhanceStrategy(new UnenhanceStrategy() { + @SuppressWarnings("unchecked") + public Type unenhanceType(T object, Type type) { + if (object instanceof PolicyElementProxy) + return (Type) ((PolicyElementProxy) object).getTargetClass(); + return type; + } + + @SuppressWarnings("unchecked") + public T unenhanceObject(T object, Type type) { + if (object instanceof PolicyElementProxy) + return (T) ((PolicyElementProxy) object).getTarget(); + return object; + } + + }).build(); + configureMapperFactory(factory); + + Policy policy = new Policy(); + Set elements = new HashSet<>(); + CustomerElement target = new CustomerElement(); + target.setName("Adil"); + elements.add(new PolicyElementProxy(target)); + elements.add(new ProductElement()); + elements.add(new OtherElement()); + elements.add(new OneOtherElement()); + + policy.setElements(elements); + + PolicyDTO dto = factory.getMapperFacade().map(policy, PolicyDTO.class); + + Assert.assertEquals(elements.size(), dto.getElements().size()); + + for (PolicyElementDTO element: dto.getElements()) { + if (element instanceof CustomerElementDTO) { + Assert.assertEquals("Adil", ((CustomerElementDTO) element).getName()); + } + } + + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/crossfeatures/PolicyElementsTestCaseClasses.java b/core/src/test/java/ma/glasnost/orika/test/crossfeatures/PolicyElementsTestCaseClasses.java new file mode 100644 index 00000000..8abc1245 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/crossfeatures/PolicyElementsTestCaseClasses.java @@ -0,0 +1,133 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.crossfeatures; + +import java.util.Set; + +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.metadata.TypeFactory; + +public class PolicyElementsTestCaseClasses { + + public static class Policy { + + private Set elements; + + public Set getElements() { + return elements; + } + + public void setElements(Set elements) { + this.elements = elements; + } + + } + + public static abstract class PolicyElement { + + } + + public static class CustomerElement extends PolicyElement { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + public static class ProductElement extends PolicyElement { + + } + + public static class OtherElement extends PolicyElement { + + } + + public static class OneOtherElement extends PolicyElement { + + } + + public static class PolicyDTO { + + private Set elements; + + public Set getElements() { + return elements; + } + + public void setElements(Set elements) { + this.elements = elements; + } + + } + + public static abstract class PolicyElementDTO { + + } + + public static class CustomerElementDTO extends PolicyElementDTO { + + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + } + + public static class ProductElementDTO extends PolicyElementDTO { + + } + + public static class OtherElementDTO extends PolicyElementDTO { + + } + + public static class OneOtherElementDTO extends PolicyElementDTO { + + } + + // Hibernate will generate a proxy for PolicyElement class and not + // for childs classes + public static class PolicyElementProxy extends PolicyElement { + private final PolicyElement target; + + public PolicyElementProxy(PolicyElement target) { + super(); + this.target = target; + } + + public Type getTargetClass() { + return TypeFactory.valueOf(target.getClass()); + } + + public Object getTarget() { + return target; + } + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/customconverter/CustomConverterTestCase.java b/core/src/test/java/ma/glasnost/orika/test/customconverter/CustomConverterTestCase.java new file mode 100644 index 00000000..dce4fdbc --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/customconverter/CustomConverterTestCase.java @@ -0,0 +1,118 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.customconverter; + +import ma.glasnost.orika.CustomConverter; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.test.MappingUtil; + +import org.junit.Assert; +import org.junit.Test; + +public class CustomConverterTestCase { + + public static class MyCustomConverter extends CustomConverter { + + /* + * (non-Javadoc) + * + * @see ma.glasnost.orika.Converter#convert(java.lang.Object, + * ma.glasnost.orika.metadata.Type) + */ + public String convert(Long source, Type destinationType, MappingContext context) { + return "long{" + source + "}"; + } + } + + public static class MyCustomConverter2 extends CustomConverter { + /* + * (non-Javadoc) + * + * @see ma.glasnost.orika.Converter#convert(java.lang.Object, + * ma.glasnost.orika.metadata.Type) + */ + public String convert(String source, Type destinationType, MappingContext context) { + return "string: " + source; + } + } + + @Test + public void testConvertLongString() { + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(new MyCustomConverter()); + factory.classMap(A.class, B.class).field("id", "string").register(); + + A source = new A(); + source.setId(42L); + + B destination = factory.getMapperFacade().map(source, B.class); + + Assert.assertEquals("long{42}", destination.getString()); + + } + + @Test + public void testConvertStringToString() { + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(new MyCustomConverter2()); + factory.classMap(A.class, B.class).field("id", "string").register(); + + B source = new B(); + source.setString("hello"); + + C destination = factory.getMapperFacade().map(source, C.class); + + Assert.assertEquals("string: hello", destination.string); + + } + + public static class A { + private Long id; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + } + + public static class B { + private String string; + + public String getString() { + return string; + } + + public void setString(String string) { + this.string = string; + } + + } + + public static class C { + public String string; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/custommapper/CustomMappingTestCase.java b/core/src/test/java/ma/glasnost/orika/test/custommapper/CustomMappingTestCase.java new file mode 100644 index 00000000..90fcdd5e --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/custommapper/CustomMappingTestCase.java @@ -0,0 +1,147 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.custommapper; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +import java.util.Collection; + +import ma.glasnost.orika.CustomMapper; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.test.MappingUtil; + +import org.junit.Assert; +import org.junit.Test; + +public class CustomMappingTestCase { + + @Test + public void testCustomMapping() { + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.classMap(PersonDTO.class, Person.class).customize(new CustomMapper() { + @Override + public void mapBtoA(Person b, PersonDTO a, MappingContext context) { + a.setName(b.getFirstName() + " " + b.getLastName()); + } + + }).register(); + + Person person = new Person(); + person.setFirstName("Abdelkrim"); + person.setLastName("EL KHETTABI"); + + PersonDTO dto = factory.getMapperFacade().map(person, PersonDTO.class); + + Assert.assertEquals(dto.getName(), person.getFirstName() + " " + person.getLastName()); + } + + @Test + public void testCustomInheritedMapping() { + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.classMap(PersonDTO.class, Person.class).customize(new CustomPersonMapper() { + @Override + public void mapBtoA(Person b, PersonDTO a, MappingContext context) { + a.setName(b.getFirstName() + " " + b.getLastName()); + } + + }).register(); + + Person person = new Person(); + person.setFirstName("Abdelkrim"); + person.setLastName("EL KHETTABI"); + + PersonDTO dto = factory.getMapperFacade().map(person, PersonDTO.class); + + Assert.assertEquals(dto.getName(), person.getFirstName() + " " + person.getLastName()); + } + + @Test + public void testCustomGenericCollectionMapping() { + CustomGenericCollectionMapper mapper = new CustomGenericCollectionMapper(); + + assertThat(mapper.getAType().toString(), is("Collection")); + assertThat(mapper.getBType().toString(), is("Collection")); + } + + @Test + public void testCustomCollectionWildcardMapping() { + CustomCollectionWithWildcardsMapper mapper = new CustomCollectionWithWildcardsMapper(); + + assertThat(mapper.getAType().toString(), is("Collection")); // ? super PersonDTO + assertThat(mapper.getBType().toString(), is("Collection")); // ? extends Person + } + @Test + public void testCustomDeepInheritedMapping() { + CustomDeepInheritedPersonMapper mapper = new CustomDeepInheritedPersonMapper(); + + assertThat(mapper.getAType().toString(), is("PersonDTO")); + assertThat(mapper.getBType().toString(), is("Person")); + } + + public static class CustomCollectionWithWildcardsMapper + extends CustomMapper, Collection> {/* do nothing impl */} + + public static class CustomGenericCollectionMapper + extends CustomMapper, Collection> {/* do nothing impl */} + + public static class CustomPersonMapper extends CustomMapper {/* do nothing impl */} + + public static class CustomInheritedPersonMapper extends CustomPersonMapper {/* do nothing impl */} + + public static class CustomDeepInheritedPersonMapper extends CustomInheritedPersonMapper {/* do nothing impl */} + + + public static class PersonDTO { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + } + + public static class Person { + private String firstName; + private String lastName; + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/enums/EnumsTestCase.java b/core/src/test/java/ma/glasnost/orika/test/enums/EnumsTestCase.java new file mode 100644 index 00000000..92b1b80a --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/enums/EnumsTestCase.java @@ -0,0 +1,132 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.enums; + +import ma.glasnost.orika.CustomConverter; +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.test.MappingUtil; +import ma.glasnost.orika.test.enums.EnumsTestCaseClasses.Book; +import ma.glasnost.orika.test.enums.EnumsTestCaseClasses.BookDTOWithAltCaseEnum; +import ma.glasnost.orika.test.enums.EnumsTestCaseClasses.BookDTOWithAlternateEnum; +import ma.glasnost.orika.test.enums.EnumsTestCaseClasses.BookDTOWithParallelEnum; +import ma.glasnost.orika.test.enums.EnumsTestCaseClasses.BookDTOWithSameEnum; +import ma.glasnost.orika.test.enums.EnumsTestCaseClasses.BookImpl; +import ma.glasnost.orika.test.enums.EnumsTestCaseClasses.PublicationFormat; +import ma.glasnost.orika.test.enums.EnumsTestCaseClasses.PublicationFormatDTOAltCase; +import ma.glasnost.orika.test.enums.EnumsTestCaseClasses.PublicationFormatDTOAlternate; + +import org.junit.Assert; +import org.junit.Test; + +public class EnumsTestCase { + + private Book createBook() { + Book book = new BookImpl(); + book.setTitle("The Prophet"); + book.setFormat(PublicationFormat.EBOOK); + return book; + } + + @Test + public void testMapSharedEnum() { + MapperFactory factory = MappingUtil.getMapperFactory(); + MapperFacade mapper = factory.getMapperFacade(); + + Book book = createBook(); + BookDTOWithSameEnum mappedBook = mapper.map(book, BookDTOWithSameEnum.class); + + Assert.assertEquals(book.getTitle(), mappedBook.getTitle()); + Assert.assertEquals(book.getFormat(), mappedBook.getFormat()); + } + + @Test + public void testMapParallelEnum() { + MapperFactory factory = MappingUtil.getMapperFactory(); + MapperFacade mapper = factory.getMapperFacade(); + + Book book = createBook(); + BookDTOWithParallelEnum mappedBook = mapper.map(book, BookDTOWithParallelEnum.class); + + Assert.assertEquals(book.getTitle(), mappedBook.getTitle()); + Assert.assertEquals(book.getFormat().name(), mappedBook.getFormat().name()); + } + + @Test + public void testMapAltCaseEnumWithConverter() { + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.getConverterFactory().registerConverter(new CustomConverter() { + + public PublicationFormatDTOAltCase convert(PublicationFormat source, + Type destinationType, MappingContext context) { + switch (source) { + case HARDBACK: + return PublicationFormatDTOAltCase.hardBack; + case SOFTBACK: + return PublicationFormatDTOAltCase.softBack; + case EBOOK: + return PublicationFormatDTOAltCase.eBook; + default: + return null; + } + } + }); + + MapperFacade mapper = factory.getMapperFacade(); + + Book book = createBook(); + BookDTOWithAltCaseEnum mappedBook = mapper.map(book, BookDTOWithAltCaseEnum.class); + + Assert.assertEquals(book.getTitle(), mappedBook.getTitle()); + Assert.assertEquals(book.getFormat().toString().toUpperCase(), mappedBook.getFormat().toString().toUpperCase()); + } + + @Test + public void testMapAlternateEnumWithConverter() { + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(new CustomConverter() { + + public PublicationFormatDTOAlternate convert(PublicationFormat source, + Type destinationType, MappingContext context) { + switch (source) { + case HARDBACK: + return PublicationFormatDTOAlternate.PUB_HARDBACK; + case SOFTBACK: + return PublicationFormatDTOAlternate.PUB_SOFTBACK; + case EBOOK: + return PublicationFormatDTOAlternate.PUB_EBOOK; + default: + return null; + } + } + }); + + MapperFacade mapper = factory.getMapperFacade(); + + Book book = createBook(); + BookDTOWithAlternateEnum mappedBook = mapper.map(book, BookDTOWithAlternateEnum.class); + + Assert.assertEquals(book.getTitle(), mappedBook.getTitle()); + Assert.assertEquals("PUB_" + book.getFormat().toString(), mappedBook.getFormat().toString()); + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/enums/EnumsTestCaseClasses.java b/core/src/test/java/ma/glasnost/orika/test/enums/EnumsTestCaseClasses.java new file mode 100644 index 00000000..8157b54a --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/enums/EnumsTestCaseClasses.java @@ -0,0 +1,167 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.enums; + + +public interface EnumsTestCaseClasses { + + enum PublicationFormat { + HARDBACK, SOFTBACK, EBOOK + } + + enum PublicationFormatDTO { + HARDBACK, SOFTBACK, EBOOK; + + @Override + public String toString() { + return name()+ordinal(); + } + } + + enum PublicationFormatDTOAltCase { + hardBack, softBack, eBook + } + + enum PublicationFormatDTOAlternate { + PUB_HARDBACK, PUB_SOFTBACK, PUB_EBOOK + } + + interface Book { + + String getTitle(); + + void setTitle(String title); + + PublicationFormat getFormat(); + + void setFormat(PublicationFormat format); + } + + class BookImpl implements Book { + + private String title; + private PublicationFormat format; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public PublicationFormat getFormat() { + return format; + } + + public void setFormat(PublicationFormat format) { + this.format = format; + } + } + + + class BookDTOWithSameEnum { + + private String title; + private PublicationFormat format; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public PublicationFormat getFormat() { + return format; + } + + public void setFormat(PublicationFormat format) { + this.format = format; + } + } + + class BookDTOWithParallelEnum { + + private String title; + private PublicationFormatDTO format; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public PublicationFormatDTO getFormat() { + return format; + } + + public void setFormat(PublicationFormatDTO format) { + this.format = format; + } + } + + class BookDTOWithAltCaseEnum { + + private String title; + private PublicationFormatDTOAltCase format; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public PublicationFormatDTOAltCase getFormat() { + return format; + } + + public void setFormat(PublicationFormatDTOAltCase format) { + this.format = format; + } + } + + class BookDTOWithAlternateEnum { + + private String title; + private PublicationFormatDTOAlternate format; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public PublicationFormatDTOAlternate getFormat() { + return format; + } + + public void setFormat(PublicationFormatDTOAlternate format) { + this.format = format; + } + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/extensibility/ClassMapBuilderExtensibilityTestCase.java b/core/src/test/java/ma/glasnost/orika/test/extensibility/ClassMapBuilderExtensibilityTestCase.java new file mode 100644 index 00000000..5278764f --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/extensibility/ClassMapBuilderExtensibilityTestCase.java @@ -0,0 +1,69 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.extensibility; + +import ma.glasnost.orika.DefaultFieldMapper; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.metadata.ClassMapBuilder; +import ma.glasnost.orika.metadata.ClassMapBuilderFactory; +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.property.PropertyResolverStrategy; + +/** + * This test case demonstrates how one could extend ClassMapBuilder to define + * your own method for matching fields up between types.
+ * This example uses a scoring mechanism to rank how "close" two fields are to + * each other based on their names, and starts by mapping the closest matches + * first. + * + * + * @author matt.deboer@gmail.com + * + */ +public class ClassMapBuilderExtensibilityTestCase { + + public static class ExtendedClassMapBuilder extends ClassMapBuilder { + + public static class Factory extends ClassMapBuilderFactory { + + protected ClassMapBuilder newClassMapBuilder(Type aType, Type bType, MapperFactory mapperFactory, + PropertyResolverStrategy propertyResolver, DefaultFieldMapper[] defaults) { + return new ExtendedClassMapBuilder<>(aType, bType, mapperFactory, propertyResolver, defaults); + } + } + + protected ExtendedClassMapBuilder(Type aType, Type bType, MapperFactory mapperFactory, + PropertyResolverStrategy propertyResolver, DefaultFieldMapper[] defaults) { + super(aType, bType, mapperFactory, propertyResolver, defaults); + } + + /* (non-Javadoc) + * @see ma.glasnost.orika.metadata.ClassMapBuilder#byDefault(ma.glasnost.orika.DefaultFieldMapper[]) + */ + @Override + public ClassMapBuilder byDefault(DefaultFieldMapper... withDefaults) { + return super.byDefault(withDefaults); + + + + } + + + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/extensibility/DefaultMapperFactoryExtensibilityTestCase.java b/core/src/test/java/ma/glasnost/orika/test/extensibility/DefaultMapperFactoryExtensibilityTestCase.java new file mode 100644 index 00000000..fccf9a4c --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/extensibility/DefaultMapperFactoryExtensibilityTestCase.java @@ -0,0 +1,161 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.extensibility; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.test.common.types.TestCaseClasses.Author; +import ma.glasnost.orika.test.common.types.TestCaseClasses.AuthorDTO; +import ma.glasnost.orika.test.common.types.TestCaseClasses.AuthorImpl; +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.Arrays; + +/** + * This test verifies (demonstrates) the capability of DefaultMapperFactory + * to be extended + * + * @author matt.deboer@gmail.com + * + */ +public class DefaultMapperFactoryExtensibilityTestCase { + + + public static class MyMapperFactory extends DefaultMapperFactory { + + private static final Logger LOGGER = LoggerFactory.getLogger(MyMapperFactory.class); + private volatile MapperFacade mapperFacadeProxy; + + /** + * We extend the builder of DefaultMapperFactory for one which + * can create instances of our own MapperFactory type. + * + */ + public static class Builder extends MapperFactoryBuilder { + + protected boolean traceMethodCalls = true; + + protected Builder self() { + return this; + } + + public Builder traceMethodCalls(boolean trace) { + this.traceMethodCalls = trace; + return self(); + } + + public MyMapperFactory build() { + return new MyMapperFactory(this); + } + } + + /** + * Since DefaultMapperFactory uses (some form of) the Builder pattern, we + * need to provide a constructor which can accept an appropriate builder + * and pass it to the super constructor. + * + * @param builder + */ + protected MyMapperFactory(Builder builder) { + super(builder); + } + + /* (non-Javadoc) + * @see ma.glasnost.orika.impl.DefaultMapperFactory#getMapperFacade() + */ + public MapperFacade getMapperFacade() { + if (mapperFacadeProxy == null) { + synchronized(this) { + if (mapperFacadeProxy == null) { + /* + * Provide our own instance as a method-tracing proxy + */ + mapperFacadeProxy = TracingMapperFacade.proxyFor(super.getMapperFacade()); + } + } + } + return mapperFacadeProxy; + } + + + /** + * TracingMapperFacade provides custom wrappers around MapperFacade + * which log all method calls against it. + * + * @author matt.deboer@gmail.com + * + */ + private static class TracingMapperFacade implements InvocationHandler { + + private final MapperFacade delegate; + + public static MapperFacade proxyFor(MapperFacade delegate) { + return (MapperFacade) Proxy.newProxyInstance( + TracingMapperFacade.class.getClassLoader(), + new Class[]{MapperFacade.class}, + new TracingMapperFacade(delegate)); + } + + private TracingMapperFacade(MapperFacade delegate) { + this.delegate = delegate; + } + /* (non-Javadoc) + * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[]) + */ + public Object invoke(Object proxy, Method method, Object[] args) + throws Throwable { + try { + /* + * Sure, you could probably do this better with AOP, but + * we needed an example, right? + */ + final String methodName = delegate.getClass().getCanonicalName() + + "#" + method.getName(); + long start = System.currentTimeMillis(); + LOGGER.info("\n---BEGIN: " + methodName + "( " + Arrays.toString(args) + ")"); + Object result = method.invoke(delegate, args); + long elapsed = System.currentTimeMillis() - start; + LOGGER.info("\n---END: " + methodName + ": elapsed[" +elapsed + "ms]"); + return result; + } catch (InvocationTargetException e) { + throw e.getTargetException(); + } + } + } + + } + + + @Test + public void testExtendedMapper() { + MyMapperFactory factory = new MyMapperFactory.Builder().useAutoMapping(true).traceMethodCalls(true).build(); + Author author = new AuthorImpl("Test Author"); + + AuthorDTO mapped = factory.getMapperFacade().map(author, AuthorDTO.class); + Assert.assertNotNull(mapped); + Assert.assertEquals(author.getName(), mapped.getName()); + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/extensibility/MappingContextFactoryExtensibilityTestCase.java b/core/src/test/java/ma/glasnost/orika/test/extensibility/MappingContextFactoryExtensibilityTestCase.java new file mode 100644 index 00000000..02196af1 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/extensibility/MappingContextFactoryExtensibilityTestCase.java @@ -0,0 +1,384 @@ +package ma.glasnost.orika.test.extensibility; + +import ma.glasnost.orika.BoundMapperFacade; +import ma.glasnost.orika.CustomConverter; +import ma.glasnost.orika.CustomMapper; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.MappingContextFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.metadata.TypeFactory; +import ma.glasnost.orika.test.community.issue137.CustomFactory; +import org.junit.Assert; +import org.junit.Test; + +import java.util.HashSet; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsInAnyOrder; + +public class MappingContextFactoryExtensibilityTestCase { + + @Test + public void testMappingContext_withCustomMapper() { + MyMappingContext.Factory contextFactory = new MyMappingContext.Factory(); + final MapperFactory factory = new DefaultMapperFactory.Builder() + .mappingContextFactory(contextFactory) + .build(); + + factory.classMap(Person.class, Person.class).customize(new CustomMapper() { + @Override + public void mapAtoB(Person a, Person b, MappingContext context) { + b.setName(a.getName()); + b.setDependsOn(factory.getMapperFacade().map(a.getDependsOn(), Person.class, context)); + } + + @Override + public void mapBtoA(Person b, Person a, MappingContext context) { + super.mapAtoB(b, a, context); + } + + }).register(); + factory.classMap(Man.class, Man.class).use(Person.class, Person.class).byDefault().register(); + factory.classMap(Woman.class, Woman.class).use(Person.class, Person.class).byDefault().register(); + + Man person = createComplexPerson(); + + Man mapped = factory.getMapperFacade().map(person, Man.class); + + assertComplexPerson(mapped); + } + + @Test + public void testMappingContext_withDefaultMapper() { + MyMappingContext.Factory contextFactory = new MyMappingContext.Factory(); + final MapperFactory factory = new DefaultMapperFactory.Builder() + .mappingContextFactory(contextFactory) + .build(); + + factory.classMap(Man.class, Man.class).byDefault().register(); + factory.classMap(Woman.class, Woman.class).byDefault().register(); + + Person person = createComplexPerson(); + + Person mapped = factory.getMapperFacade().map(person, Person.class); + + assertComplexPerson(mapped); + } + + @Test + public void testMappingContext_withFieldMapper() { + MyMappingContext.Factory contextFactory = new MyMappingContext.Factory(); + final MapperFactory factory = new DefaultMapperFactory.Builder() + .mappingContextFactory(contextFactory) + .build(); + + factory.classMap(Person.class, Person.class) + .field("name", "name") + .field("dependsOn", "dependsOn") + .register(); + factory.classMap(Man.class, Man.class).use(Person.class, Person.class).field("children", "children").register(); + factory.classMap(Woman.class, Woman.class).use(Person.class, Person.class).field("children", "children").register(); + + Man person = createComplexPerson(); + + Man mapped = factory.getMapperFacade().map(person, Man.class); + + assertComplexPerson(mapped); + } + + @Test + public void testMappingContext_withBoundMapperFacade() { + MyMappingContext.Factory contextFactory = new MyMappingContext.Factory(); + final MapperFactory factory = new DefaultMapperFactory.Builder() + .mappingContextFactory(contextFactory) + .build(); + + + factory.getConverterFactory().registerConverter(new CustomConverter() { + + public Person convert(Person source, Type destType, MappingContext mappingContext) { + final BoundMapperFacade boundMapperFacadePerson = factory.getMapperFacade(Person.class, Person.class); + final BoundMapperFacade boundMapperFacadeChild = factory.getMapperFacade(Child.class, Child.class); + Person destination = boundMapperFacadePerson.newObject(source, mappingContext); + destination.setName(source.getName()); + destination.setDependsOn(boundMapperFacadePerson.map(source.getDependsOn(), mappingContext)); + if (source instanceof Parent && destination instanceof Parent) { + Set srcChildren = ((Parent) source).getChildren(); + Set destChildren = ((Parent) destination).getChildren(); + for (Child srcChild : srcChildren) { + destChildren.add(boundMapperFacadeChild.map(srcChild, mappingContext)); + } + + } + return destination; + } + }); + factory.registerObjectFactory(new CustomFactory() { + + @Override + public Person create(Object o, MappingContext mappingContext) { + if (o instanceof Woman) { + return new Woman(); + } else if (o instanceof Man) { + return new Man(); + } else if (o instanceof Child) { + return new Child(); + } else { + return null; + } + } + }, TypeFactory.valueOf(Person.class)); + factory.classMap(Man.class, Man.class).byDefault().register(); + factory.classMap(Woman.class, Woman.class).byDefault().register(); + factory.classMap(Parent.class, Parent.class).byDefault().register(); + + // factory.classMap(Person.class, Person.class).byDefault().register(); + final BoundMapperFacade boundMapperFacadePerson = factory.getMapperFacade(Person.class, Person.class); + + Person person = createComplexPerson(); + + Person mapped = boundMapperFacadePerson.map(person); + + assertComplexPerson(mapped); + } + + @Test + public void testMappingContext_withCustomConverter() { + MyMappingContext.Factory contextFactory = new MyMappingContext.Factory(); + final MapperFactory factory = new DefaultMapperFactory.Builder() + .mappingContextFactory(contextFactory) + .build(); + + factory.getConverterFactory().registerConverter(new CustomConverter() { + + public Person convert(Person source, Type destType, MappingContext mappingContext) { + Person destination = factory.getMapperFacade().newObject(source, destinationType, mappingContext); + destination.setName(source.getName()); + destination.setDependsOn(factory.getMapperFacade().map(source.getDependsOn(), Person.class, mappingContext)); + if (source instanceof Parent && destination instanceof Parent) { + Parent srcParent = (Parent) source; + Parent destParent = (Parent) destination; + Type childType = TypeFactory.valueOf(Child.class); + factory.getMapperFacade().mapAsCollection(srcParent.getChildren(), destParent.getChildren(), + childType, childType, mappingContext); + } + return destination; + } + }); + factory.registerObjectFactory(new CustomFactory() { + + @Override + public Person create(Object o, MappingContext mappingContext) { + if (o instanceof Woman) { + return new Woman(); + } else if (o instanceof Man) { + return new Man(); + } else if (o instanceof Child) { + return new Child(); + } else { + return null; + } + } + }, TypeFactory.valueOf(Person.class)); + factory.classMap(Man.class, Man.class).byDefault().register(); + factory.classMap(Woman.class, Woman.class).byDefault().register(); + + factory.classMap(Person.class, Person.class).byDefault().register(); + + Person person = createComplexPerson(); + + Person mapped = factory.getMapperFacade().map(person, Person.class); + + assertComplexPerson(mapped); + } + + private Man createComplexPerson() { + Man maxi = new Man("Maxi"); + Woman susi = new Woman("Susi"); + Man hansi = new Man("Hansi"); + Child hensl = new Child("Hensl"); + Child kretl = new Child("Kretl"); + maxi.setDependsOn(susi); + susi.setDependsOn(hansi); + susi.getChildren().add(hensl); + susi.getChildren().add(kretl); + return maxi; + } + + private void assertComplexPerson(Person mapped) { + Assert.assertEquals("Maxi", mapped.getName()); + Assert.assertEquals("Susi", mapped.getDependsOn().getName()); + Assert.assertEquals("Hansi", mapped.getDependsOn().getDependsOn().getName()); + Assert.assertTrue("Maxi must be a Man but was: " + mapped.getClass().getSimpleName(), mapped instanceof Man); + Assert.assertTrue("Susi must be a Woman but was: " + mapped.getDependsOn().getClass().getSimpleName(), + mapped.getDependsOn() instanceof Woman); + Assert.assertTrue("Hansi must be a Man but was: " + mapped.getDependsOn().getDependsOn().getClass().getSimpleName(), + mapped.getDependsOn().getDependsOn() instanceof Man); + + Parent susi = (Parent) mapped.getDependsOn(); + assertThat(susi.getChildren(), containsInAnyOrder(new Child("Hensl"), new Child("Kretl"))); + } + + public static class MyMappingContext extends MappingContext + { + public MyMappingContext(Map globalProperties) { + super(globalProperties); + } + + public static class Factory implements MappingContextFactory { + private final ConcurrentHashMap globalProperties = new ConcurrentHashMap<>(); + private final ThreadLocal threadLocalMappingContext = new ThreadLocal<>(); + + @Override + public MappingContext getContext() { + if (threadLocalMappingContext.get() != null) { + throw new IllegalStateException("During this Thread only one MappingContext is allowed to be created."); + } + MappingContext myMappingContext = new MyMappingContext(globalProperties); + threadLocalMappingContext.set(myMappingContext); + return myMappingContext; + } + + @Override + public void release(MappingContext context) { + context.reset(); + threadLocalMappingContext.remove(); + } + + @Override + public Map getGlobalProperties() { + return globalProperties; + } + + } + + } + + public static class Person + { + private String name; + private Person dependsOn; + + public Person() { + super(); + } + + public Person(String name) { + super(); + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Person getDependsOn() { + return dependsOn; + } + + public void setDependsOn(Person dependsOn) { + this.dependsOn = dependsOn; + } + + @Override + public int hashCode() { + return Objects.hash(getName()); + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (obj == this) { + return true; + } + if (obj.getClass() != getClass()) { + return false; + } + Person rhs = (Person) obj; + + return Objects.equals(getName(), rhs.getName()); + } + + @Override + public String toString() { + return String.format("%s(%s)", getClass().getSimpleName(), getName()); + } + + } + + public static final class Man extends Person implements Parent { + private Set children = new HashSet<>(); + + public Man() { + super(); + } + + public Man(String name) { + super(name); + } + + public Set getChildren() { + return children; + } + + public void setChildren(Set children) { + this.children = children; + } + + } + + public static final class Woman extends Person implements Parent { + private Set children = new HashSet<>(); + + public Woman() { + super(); + } + + public Woman(String name) { + super(name); + } + + @Override + public Set getChildren() { + return children; + } + + @Override + public void setChildren(Set children) { + this.children = children; + } + + } + + public interface Parent { + + Set getChildren(); + + void setChildren(Set children); + + } + + public static final class Child extends Person { + + public Child() { + super(); + } + + public Child(String name) { + super(name); + } + + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/extensibility/PooledInstancesTestCase.java b/core/src/test/java/ma/glasnost/orika/test/extensibility/PooledInstancesTestCase.java new file mode 100644 index 00000000..0f4cc3ad --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/extensibility/PooledInstancesTestCase.java @@ -0,0 +1,230 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.extensibility; + +import ma.glasnost.orika.BoundMapperFacade; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.metadata.Type; +import org.junit.Assert; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +public class PooledInstancesTestCase { + + public static class MyMapperFactory extends DefaultMapperFactory { + public static class Builder extends + MapperFactoryBuilder { + + protected Builder self() { + return this; + } + + public MyMapperFactory build() { + return new MyMapperFactory(this); + } + } + + private static class PoolingBoundMapperFacade implements + BoundMapperFacade { + private final BoundMapperFacade wrapped; + private final Map pool; + + public PoolingBoundMapperFacade(BoundMapperFacade wrapped, + Map pool) { + this.wrapped = wrapped; + this.pool = pool; + } + + @SuppressWarnings("unchecked") + public B map(A instanceA) { + return (B) pool.get(((SourcePoolView) instanceA).getName()); + } + + public Type getAType() { + return wrapped.getAType(); + } + + public Type getBType() { + return wrapped.getBType(); + } + + @SuppressWarnings("unchecked") + public B map(A instanceA, MappingContext context) { + return (B) pool.get(((SourcePoolView) instanceA).getName()); + } + + public A mapReverse(B instanceB) { + return wrapped.mapReverse(instanceB); + } + + public A mapReverse(B instanceB, MappingContext context) { + return wrapped.mapReverse(instanceB, context); + } + + @SuppressWarnings("unchecked") + public B map(A instanceA, B instanceB) { + return (B) pool.get(((SourcePoolView) instanceA).getName()); + } + + @SuppressWarnings("unchecked") + public B map(A instanceA, B instanceB, MappingContext context) { + return (B) pool.get(((SourcePoolView) instanceA).getName()); + } + + public A mapReverse(B instanceB, A instanceA) { + return wrapped.mapReverse(instanceB, instanceA); + } + + public A mapReverse(B instanceB, A instanceA, MappingContext context) { + return wrapped.mapReverse(instanceB, instanceA, context); + } + + public B newObject(A source, MappingContext context) { + return wrapped.newObject(source, context); + } + + public A newObjectReverse(B source, MappingContext context) { + return wrapped.newObjectReverse(source, context); + } + } + + /** + * Since DefaultMapperFactory uses (some form of) the Builder pattern, + * we need to provide a constructor which can accept an appropriate + * builder and pass it to the super constructor. + * + * @param builder + */ + protected MyMapperFactory(Builder builder) { + super(builder); + pool.put("A", new Pooled("A")); + pool.put("B", new Pooled("B")); + pool.put("C", new Pooled("C")); + } + + private final Map pool = new HashMap(); + + public Map getPool() { + return pool; + } + + public BoundMapperFacade getMapperFacade( + Type sourceType, Type destinationType, + boolean containsCycles) { + BoundMapperFacade ret = super.getMapperFacade(sourceType, + destinationType, containsCycles); + if (sourceType.getRawType().equals(SourcePoolView.class) + && destinationType.getRawType().equals(Pooled.class)) { + ret = new PoolingBoundMapperFacade(ret, pool); + } + return ret; + } + } + + @Test + public void testExtendedMapper() { + MyMapperFactory factory = new MyMapperFactory.Builder().build(); + factory.registerClassMap(factory + .classMap(SourcePoolView.class, Pooled.class).byDefault() + .toClassMap()); + factory.registerClassMap(factory + .classMap(SourceObject.class, DestObject.class).byDefault() + .toClassMap()); + + SourceObject source1 = new SourceObject(); + source1.setPooled(new SourcePoolView("A")); + DestObject dest1 = factory.getMapperFacade().map(source1, + DestObject.class); + + SourceObject source2 = new SourceObject(); + source2.setPooled(new SourcePoolView("A")); + DestObject dest2 = factory.getMapperFacade().map(source2, + DestObject.class); + Assert.assertEquals(dest2.getPooled(), dest1.getPooled()); + + SourceObject source3 = new SourceObject(); + source3.setPooled(new SourcePoolView("A")); + DestObject dest3 = new DestObject(); + dest3.setPooled(factory.getPool().get("C")); + factory.getMapperFacade().map(source3, dest3); + Assert.assertEquals(dest3.getPooled(), dest1.getPooled()); + } + + public static class SourcePoolView { + private String name; + + public SourcePoolView(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + public static class SourceObject { + private SourcePoolView pooled; + + public SourcePoolView getPooled() { + return pooled; + } + + public void setPooled(SourcePoolView pooled) { + this.pooled = pooled; + } + } + + public static class Pooled { + private String name; + + public Pooled() { + } + + public Pooled(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + public static class DestObject { + private Pooled pooled; + + public Pooled getPooled() { + return pooled; + } + + public void setPooled(Pooled pooled) { + this.pooled = pooled; + } + } +} \ No newline at end of file diff --git a/core/src/test/java/ma/glasnost/orika/test/extensibility/PropertyResolverExtensibilityTestCase.java b/core/src/test/java/ma/glasnost/orika/test/extensibility/PropertyResolverExtensibilityTestCase.java new file mode 100644 index 00000000..1c26f7a6 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/extensibility/PropertyResolverExtensibilityTestCase.java @@ -0,0 +1,133 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.extensibility; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingException; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.metadata.Property; +import ma.glasnost.orika.property.IntrospectorPropertyResolver; +import org.junit.Assert; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author matt.deboer@gmail.com + * + */ +public class PropertyResolverExtensibilityTestCase { + + /** + * For my next trick, this is a custom Property Resolver which automatically + * attempts a dynamic definition of type Element (after normal resolution + * has failed) + * + * @author matt.deboer@gmail.com + * + */ + public static class ElementPropertyResolver extends IntrospectorPropertyResolver { + + protected Property getProperty(java.lang.reflect.Type type, String expr, boolean isNestedLookup, Property owner) + throws MappingException { + Property property = null; + try { + property = super.getProperty(type, expr, isNestedLookup, null); + } catch (MappingException e) { + try { + property = super.resolveInlineProperty(type, expr + ":{getAttribute(\"" + expr + "\")|setAttribute(\"" + expr + + "\",%s)|type=" + (isNestedLookup ? Element.class.getName() : "Object") + "}"); + } catch (MappingException e2) { + throw e; // throw the original exception + } + } + return property; + } + } + + /** + * This test demonstrates how you might implement a custom property resolver + * which provides a proprietary definition of properties + */ + @Test + public void testAdHocResolution_integration_customResolverUsingDeclarativeProperties() { + + MapperFactory factory = new DefaultMapperFactory.Builder().propertyResolverStrategy(new ElementPropertyResolver()).build(); + + factory.classMap(Element.class, Person.class) + .field("employment.jobTitle", "jobTitle") + .field("employment.salary", "salary") + .field("name.first", "firstName") + .field("name.last", "lastName") + .register(); + + MapperFacade mapper = factory.getMapperFacade(); + + Element person = new Element(); + Element employment = new Element(); + employment.setAttribute("jobTitle", "manager"); + employment.setAttribute("salary", 50000L); + person.setAttribute("employment", employment); + Element name = new Element(); + name.setAttribute("first", "Chuck"); + name.setAttribute("last", "Testa"); + person.setAttribute("name", name); + + Person result = mapper.map(person, Person.class); + + Assert.assertEquals(((Element) person.getAttribute("name")).getAttribute("first"), result.firstName); + Assert.assertEquals(((Element) person.getAttribute("name")).getAttribute("last"), result.lastName); + Assert.assertEquals(((Element) person.getAttribute("employment")).getAttribute("salary") + "", result.salary); + Assert.assertEquals(((Element) person.getAttribute("employment")).getAttribute("jobTitle"), result.jobTitle); + + Element mapBack = mapper.map(result, Element.class); + + Assert.assertEquals(((Element) person.getAttribute("name")).getAttribute("first"), + ((Element) mapBack.getAttribute("name")).getAttribute("first")); + Assert.assertEquals(((Element) person.getAttribute("name")).getAttribute("last"), + ((Element) mapBack.getAttribute("name")).getAttribute("last")); + Assert.assertEquals(((Element) person.getAttribute("employment")).getAttribute("salary") + "", + ((Element) mapBack.getAttribute("employment")).getAttribute("salary")); + Assert.assertEquals(((Element) person.getAttribute("employment")).getAttribute("jobTitle"), + ((Element) mapBack.getAttribute("employment")).getAttribute("jobTitle")); + + } + + public static class Element { + + Map attributes = new HashMap<>(); + + public Object getAttribute(String name) { + return attributes.get(name); + } + + public void setAttribute(String name, Object value) { + attributes.put(name, value); + } + } + + public static class Person { + public String firstName; + public String lastName; + public String jobTitle; + public String salary; + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/favorsextension/FavorsExtensionTestCase.java b/core/src/test/java/ma/glasnost/orika/test/favorsextension/FavorsExtensionTestCase.java new file mode 100644 index 00000000..d9cd4ef8 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/favorsextension/FavorsExtensionTestCase.java @@ -0,0 +1,243 @@ +package ma.glasnost.orika.test.favorsextension; + +import static ma.glasnost.orika.metadata.TypeFactory.valueOf; +import ma.glasnost.orika.Mapper; +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.impl.GeneratedMapperBase; +import ma.glasnost.orika.metadata.MapperKey; +import ma.glasnost.orika.test.MappingUtil; + +import org.junit.Assert; +import org.junit.Test; + +public class FavorsExtensionTestCase { + + + @Test + public void favorsExtension() throws Throwable { + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.classMap(Animal.class, AnimalDto.class) + .field("category", "type") + .field("name", "qualifier") + .favorExtension(true) + .register(); + + MapperFacade mapper = factory.getMapperFacade(); + + Bird src = new Bird(); + src.category = "falcon"; + src.name = "Falcor"; + src.wingSpanInCm = 120; + + BirdDto dest = mapper.map(src, BirdDto.class); + Assert.assertEquals(src.category, dest.type); + Assert.assertEquals(src.name, dest.qualifier); + Assert.assertEquals(src.wingSpanInCm, dest.wingSpanInCm); + + Cat cat = new Cat(); + cat.category = "tiger"; + cat.name = "Tigger"; + cat.striped = true; + + CatDto dest2 = mapper.map(cat, CatDto.class); + Assert.assertEquals(cat.category, dest2.type); + Assert.assertEquals(cat.name, dest2.qualifier); + Assert.assertEquals(cat.striped, dest2.striped); + } + + @Test + public void favorsExtensionGlobally() throws Throwable { + + MapperFactory factory = new DefaultMapperFactory.Builder().favorExtension(true).build(); + factory.classMap(Animal.class, AnimalDto.class) + .field("category", "type") + .field("name", "qualifier") + .register(); + + MapperFacade mapper = factory.getMapperFacade(); + + Bird src = new Bird(); + src.category = "falcon"; + src.name = "Falcor"; + src.wingSpanInCm = 120; + + BirdDto dest = mapper.map(src, BirdDto.class); + Assert.assertEquals(src.category, dest.type); + Assert.assertEquals(src.name, dest.qualifier); + Assert.assertEquals(src.wingSpanInCm, dest.wingSpanInCm); + + Cat cat = new Cat(); + cat.category = "tiger"; + cat.name = "Tigger"; + cat.striped = true; + + CatDto dest2 = mapper.map(cat, CatDto.class); + Assert.assertEquals(cat.category, dest2.type); + Assert.assertEquals(cat.name, dest2.qualifier); + Assert.assertEquals(cat.striped, dest2.striped); + } + + @Test + public void favorsExtensionMultiLevel() throws Throwable { + + MapperFactory factory = new DefaultMapperFactory.Builder().favorExtension(true).build(); + + factory.classMap(Animal.class, AnimalDto.class) + .field("category", "type") + .field("name", "qualifier") + .register(); + + factory.classMap(Reptile.class, ReptileDto.class) + .field("weightInKg", "weightKg") + .register(); + + MapperFacade mapper = factory.getMapperFacade(); + + Salamander src = new Salamander(); + src.category = "falcon"; + src.name = "Falcor"; + src.tailLengthInCm = 23.0f; + src.weightInKg = 12.5f; + + SalamanderDto dest = mapper.map(src, SalamanderDto.class); + Assert.assertEquals(src.category, dest.type); + Assert.assertEquals(src.name, dest.qualifier); + Assert.assertEquals(src.weightInKg, dest.weightKg, 0.1); + Assert.assertEquals(src.tailLengthInCm, dest.tailLengthInCm, 0.1); + } + + @Test + public void discoverUsedMappersWithoutDuplicates() throws Throwable { + + MapperFactory factory = new DefaultMapperFactory.Builder().favorExtension(true).build(); + + factory.classMap(Animal.class, AnimalDto.class) + .field("category", "type") + .field("name", "qualifier") + .register(); + + factory.classMap(Reptile.class, ReptileDto.class) + .field("weightInKg", "weightKg") + .register(); + + MapperFacade mapperFacade = factory.getMapperFacade(); + /* + * Cause Salamander<->SalamanderDto mapper to be created + */ + mapperFacade.map(new Salamander(), SalamanderDto.class); + Mapper mapper = factory.lookupMapper(new MapperKey(valueOf(Salamander.class), valueOf(SalamanderDto.class))); + + /* + * Proceed through the hierarchy, assuring that no mapper is seen more than once + */ + Mapper[] usedMappers = ((GeneratedMapperBase)mapper).getUsedMappers(); + for (int i=0, len=usedMappers.length; i < len; ++i) { + for (int j=0; j < len; ++j) { + if (i != j) { + Assert.assertFalse(usedMappers[i] + " is a used by " + usedMappers[j], + GeneratedMapperBase.isUsedMapperOf(usedMappers[i], usedMappers[j])); + } + } + } + + } + + @Test + public void withoutFavorsExtension() throws Throwable { + + /* + * Note: without using 'favorsExtension', the result is that Orika + * uses the Animal <-> AnimalDto mapping that was registered without + * generating a dynamic mapping for the downstream classes + */ + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.classMap(Animal.class, AnimalDto.class) + .field("category", "type") + .field("name", "qualifier") + .register(); + + MapperFacade mapper = factory.getMapperFacade(); + + Bird src = new Bird(); + src.category = "falcon"; + src.name = "Falcor"; + src.wingSpanInCm = 120; + + BirdDto dest = mapper.map(src, BirdDto.class); + Assert.assertEquals(src.category, dest.type); + Assert.assertEquals(src.name, dest.qualifier); + Assert.assertNotEquals(src.wingSpanInCm, dest.wingSpanInCm); + + Cat cat = new Cat(); + cat.category = "tiger"; + cat.name = "Tigger"; + cat.striped = true; + + CatDto dest2 = mapper.map(cat, CatDto.class); + Assert.assertEquals(cat.category, dest2.type); + Assert.assertEquals(cat.name, dest2.qualifier); + Assert.assertNotEquals(cat.striped, dest2.striped); + + /* + * But after we explicitly register the mapping, and + * declare that it should 'use' the Animal to AnimalDto + * mapper, it works as expected + */ + factory.classMap(Bird.class, BirdDto.class) + .byDefault() + .use(Animal.class, AnimalDto.class) + .register(); + + dest = mapper.map(src, BirdDto.class); + Assert.assertEquals(src.category, dest.type); + Assert.assertEquals(src.name, dest.qualifier); + Assert.assertEquals(src.wingSpanInCm, dest.wingSpanInCm); + + } + + public static class Animal { + public String category; + public String name; + } + + public static class Bird extends Animal { + public int wingSpanInCm; + } + + public static class Cat extends Animal { + public boolean striped; + } + + public static class Reptile extends Animal { + public float weightInKg; + } + + public static class Salamander extends Reptile { + public float tailLengthInCm; + } + + public static class AnimalDto { + public String type; + public String qualifier; + } + + public static class BirdDto extends AnimalDto { + public int wingSpanInCm; + } + + public static class CatDto extends AnimalDto { + public boolean striped; + } + + public static class ReptileDto extends AnimalDto { + public float weightKg; + } + + public static class SalamanderDto extends ReptileDto { + public float tailLengthInCm; + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/fieldmap/NestedExpressionTestCase.java b/core/src/test/java/ma/glasnost/orika/test/fieldmap/NestedExpressionTestCase.java new file mode 100644 index 00000000..84e46d93 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/fieldmap/NestedExpressionTestCase.java @@ -0,0 +1,141 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.fieldmap; + +import org.junit.Assert; +import org.junit.Test; + +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.test.MappingUtil; + +public class NestedExpressionTestCase { + + @Test + public void testNestedProperty() { + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.registerClassMap(factory.classMap(Order.class, OrderDTO.class).field("product.state.type.label", "stateLabel") + .field("product.name", "productName").toClassMap()); + + StateType type = new StateType(); + type.setLabel("Open"); + + State state = new State(); + state.setType(type); + + Product product = new Product(); + product.setState(state); + product.setName("Glasnost Platform"); + + Order order = new Order(); + order.setProduct(product); + + OrderDTO dto = factory.getMapperFacade().map(order, OrderDTO.class); + + Assert.assertEquals("Open", dto.getStateLabel()); + + Order object = factory.getMapperFacade().map(dto, Order.class); + + Assert.assertEquals("Open", object.getProduct().getState().getType().getLabel()); + + } + + public static class StateType { + private String label; + + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.label = label; + } + + } + + public static class State { + private StateType type; + + public StateType getType() { + return type; + } + + public void setType(StateType type) { + this.type = type; + } + + } + + public static class Product { + private State state; + private String name; + + public State getState() { + return state; + } + + public void setState(State state) { + this.state = state; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + } + + public static class Order { + private Product product; + + public Product getProduct() { + return product; + } + + public void setProduct(Product product) { + this.product = product; + } + } + + public static class OrderDTO { + private String stateLabel; + private String productName; + + public String getStateLabel() { + return stateLabel; + } + + public void setStateLabel(String stateLabel) { + this.stateLabel = stateLabel; + } + + public String getProductName() { + return productName; + } + + public void setProductName(String productName) { + this.productName = productName; + } + + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/fieldmap/NestedPropertyTestCase.java b/core/src/test/java/ma/glasnost/orika/test/fieldmap/NestedPropertyTestCase.java new file mode 100644 index 00000000..bef6283e --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/fieldmap/NestedPropertyTestCase.java @@ -0,0 +1,162 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.fieldmap; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.metadata.ClassMap; +import ma.glasnost.orika.test.MappingUtil; + +public class NestedPropertyTestCase { + + private MapperFactory mapperFactory; + + @Before + public void setUp() { + mapperFactory = MappingUtil.getMapperFactory(); + + ClassMap classMap = mapperFactory.classMap(LineDTO.class, Line.class).field("x0", "start.x").field("y0", "start.y") + .field("x1", "end.x").field("y1", "end.y").toClassMap(); + mapperFactory.registerClassMap(classMap); + } + + @Test + public void testNestedProperty() { + + Point start = new Point(2, 4); + Point end = new Point(8, 9); + + Line line = new Line(start, end); + + LineDTO dto = mapperFactory.getMapperFacade().map(line, LineDTO.class); + + Assert.assertEquals(start.getX(), dto.getX0()); + Assert.assertEquals(start.getY(), dto.getY0()); + Assert.assertEquals(end.getX(), dto.getX1()); + Assert.assertEquals(end.getY(), dto.getY1()); + } + + @Test + public void testNestedNullProperty() { + + Point start = new Point(2, 4); + + Line line = new Line(start, null); + + LineDTO dto = mapperFactory.getMapperFacade().map(line, LineDTO.class); + + Assert.assertEquals(start.getX(), dto.getX0()); + Assert.assertEquals(start.getY(), dto.getY0()); + Assert.assertEquals(0, dto.getX1()); + Assert.assertEquals(0, dto.getY1()); + } + + public static class Point { + private int x, y; + + public Point(int x, int y) { + super(); + this.x = x; + this.y = y; + } + + public int getX() { + return x; + } + + public void setX(int x) { + this.x = x; + } + + public int getY() { + return y; + } + + public void setY(int y) { + this.y = y; + } + } + + public static class Line { + private Point start; + private Point end; + + public Line(Point start, Point end) { + super(); + this.start = start; + this.end = end; + } + + public Point getStart() { + return start; + } + + public void setStart(Point start) { + this.start = start; + } + + public Point getEnd() { + return end; + } + + public void setEnd(Point end) { + this.end = end; + } + } + + public static class LineDTO { + private int x0, y0, x1, y1; + + public int getX0() { + return x0; + } + + public void setX0(int x0) { + this.x0 = x0; + } + + public int getY0() { + return y0; + } + + public void setY0(int y0) { + this.y0 = y0; + } + + public int getX1() { + return x1; + } + + public void setX1(int x1) { + this.x1 = x1; + } + + public int getY1() { + return y1; + } + + public void setY1(int y1) { + this.y1 = y1; + } + + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/fieldmap/OverrideFieldNameTestCase.java b/core/src/test/java/ma/glasnost/orika/test/fieldmap/OverrideFieldNameTestCase.java new file mode 100644 index 00000000..5938f679 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/fieldmap/OverrideFieldNameTestCase.java @@ -0,0 +1,94 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.fieldmap; + +import org.junit.Assert; +import org.junit.Test; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.metadata.ClassMap; +import ma.glasnost.orika.test.MappingUtil; + +public class OverrideFieldNameTestCase { + + @Test + public void testSimpleFieldMap() { + MapperFactory factory = MappingUtil.getMapperFactory(); + + ClassMap classMap = factory.classMap(Address.class, AddressDTO.class).field("country", "countryName") + .field("city", "cityName").toClassMap(); + factory.registerClassMap(classMap); + + MapperFacade mapper = factory.getMapperFacade(); + + Address adress = new Address(); + adress.setCountry("Morocco"); + adress.setCity("Marrakesh"); + + AddressDTO adressDTO = mapper.map(adress, AddressDTO.class); + + Assert.assertEquals(adress.getCountry(), adressDTO.getCountryName()); + Assert.assertEquals(adress.getCity(), adressDTO.getCityName()); + } + + public static class Address { + private String country; + private String city; + + public String getCountry() { + return country; + } + + public void setCountry(String country) { + this.country = country; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + } + + public static class AddressDTO { + private String countryName; + private String cityName; + + public String getCountryName() { + return countryName; + } + + public void setCountryName(String countryName) { + this.countryName = countryName; + } + + public String getCityName() { + return cityName; + } + + public void setCityName(String cityName) { + this.cityName = cityName; + } + + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/filters/FilterTestCase.java b/core/src/test/java/ma/glasnost/orika/test/filters/FilterTestCase.java new file mode 100644 index 00000000..008e63d1 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/filters/FilterTestCase.java @@ -0,0 +1,360 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.filters; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.NullFilter; +import ma.glasnost.orika.metadata.Property; +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.test.MappingUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.math.BigDecimal; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class FilterTestCase { + + @Test + public void testFiltering() { + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.classMap(Source.class, Destination.class) + .field("address.street", "street") + .field("address.city", "city") + .byDefault().register(); + factory.registerFilter(new SecurityFilter()); + + MapperFacade mapper = factory.getMapperFacade(); + + Source source = new Source(); + source.name = new SourceName(); + source.name.first = "Joe"; + source.name.last = "Smith"; + source.id = 2L; + source.age = 35; + source.cost = 12.34d; + source.creditCardNumber = "5432109876543210"; + source.address = new SourceAddress(); + source.address.street = "ashbury"; + source.address.city = "SF"; + + Destination dest = mapper.map(source, Destination.class); + + Assert.assertEquals(source.name.first, dest.name.first); + Assert.assertEquals(source.name.last, dest.name.last); + Assert.assertNull(dest.age); + Assert.assertEquals(source.cost, dest.cost.doubleValue(), 0.01d); + Assert.assertEquals("************3210", dest.creditCardNumber); + Assert.assertNull(dest.street); + Assert.assertEquals(source.address.city, dest.city); + + } + + public static class SecurityFilter extends NullFilter { + + private final String MASK = "*************"; + + public boolean filtersDestination() { + return true; + } + + public boolean shouldMap(final Type sourceType, final String sourceName, final S source, final Type destType, final String destName, + final D dest, final MappingContext mappingContext) { + if ("age".equals(sourceName) || "address.street".equals(sourceName)) { + return false; + } + return true; + } + + @SuppressWarnings("unchecked") + public D filterDestination(D destinationValue, final Type sourceType, final String sourceName, final Type destType, + final String destName, final MappingContext mappingContext) { + if ("creditCardNumber".equals(sourceName)) { + String cardMask = (String) destinationValue; + destinationValue = (D) (MASK.substring(0, cardMask.length() - 4) + cardMask.substring(cardMask.length() - 4)); + } + return destinationValue; + + } + } + + public static class SecurityFilter2 extends NullFilter { + + public boolean filtersDestination() { + return true; + } + + public boolean shouldMap(final Type sourceType, final String sourceName, final S source, final Type destType, final String destName, + final D dest, final MappingContext mappingContext) { + if ("age".equals(sourceName) || "address.street".equals(sourceName)) { + return false; + } + return true; + } + + @SuppressWarnings("unchecked") + public D filterDestination(D destinationValue, final Type sourceType, final String sourceName, final Type destType, + final String destName, final MappingContext mappingContext) { + if ("creditCardNumber".equals(sourceName)) { + String cardMask = (String) destinationValue; + destinationValue = (D) cardMask.replace("*", "-"); + } + return destinationValue; + } + } + + @Test + public void testFilterAppliesTo() { + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.classMap(Source.class, Destination.class).byDefault().register(); + factory.registerFilter(new CostFilter()); + + MapperFacade mapper = factory.getMapperFacade(); + + Source source = new Source(); + source.age = 35; + source.cost = 12.34d; + source.creditCardNumber = "cc"; + + Destination dest = mapper.map(source, Destination.class); + + Assert.assertEquals(source.age, (int) dest.age); + Assert.assertEquals(source.cost * 2, dest.cost.doubleValue(), 0.01d); + Assert.assertEquals(source.creditCardNumber, dest.creditCardNumber); + } + + private static class CostFilter extends NullFilter { + @Override + public boolean appliesTo(Property source, Property destination) { + return super.appliesTo(source, destination) && source.getName().equals("cost"); + } + + @Override + public boolean filtersSource() { + return true; + } + + @SuppressWarnings("unchecked") + @Override + public S filterSource(S sourceValue, final Type sourceType, final String sourceName, final Type destType, + final String destName, final MappingContext mappingContext) { + return (S) new BigDecimal(((Double) sourceValue) * 2); + } + } + + @Test + public void testMultiOccurenceFiltering() { + // run without filter + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.classMap(Source.class, Destination.class) + .field("infoMap{key}", "infos{item}") + .field("infoMap{value}", "infos{info}") + .byDefault().register(); + + MapperFacade mapper = factory.getMapperFacade(); + + Source source = new Source(); + source.age = 35; + source.infoMap = new HashMap<>(); + source.infoMap.put("weather", "nice"); + + Destination dest = mapper.map(source, Destination.class); + + Assert.assertEquals(source.age, (int) dest.age); + Assert.assertEquals(1, dest.infos.size()); + Info info = dest.infos.get(0); + Assert.assertEquals("weather", info.item); + Assert.assertEquals("nice", info.info); + + // run with filter + factory = MappingUtil.getMapperFactory(); + factory.classMap(Source.class, Destination.class) + .field("infoMap{key}", "infos{item}") + .field("infoMap{value}", "infos{info}") + .byDefault().register(); + factory.registerFilter(new InfoFilter()); + mapper = factory.getMapperFacade(); + + dest = mapper.map(source, Destination.class); + + Assert.assertEquals(source.age, (int) dest.age); + Assert.assertNull(dest.infos); + } + + @Test + public void mapDestinationIfNull() throws Throwable { + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.classMap(Source.class, Destination.class) + .field("address.street", "street") + .field("address.city", "city") + .byDefault().register(); + + factory.registerFilter(new OverwriteProtectionFilter()); + factory.registerFilter(new SecurityFilter()); + + MapperFacade mapper = factory.getMapperFacade(); + + Source source = new Source(); + source.name = new SourceName(); + source.name.first = "Joe"; + source.name.last = "Smith"; + source.id = 2L; + source.age = 35; + source.cost = 12.34d; + source.creditCardNumber = "5432109876543210"; + source.address = new SourceAddress(); + source.address.street = "ashbury"; + source.address.city = "SF"; + + Destination dest = new Destination(); + dest.city = "NY"; + dest.creditCardNumber = "************4444"; + + mapper.map(source, dest); + + /* + * We expect that dest.city and dest.creditCardNumber should + * not have been changed because they were non-null + */ + + Assert.assertEquals(source.name.first, dest.name.first); + Assert.assertEquals(source.name.last, dest.name.last); + Assert.assertNull(dest.age); + Assert.assertEquals(source.cost, dest.cost.doubleValue(), 0.01d); + Assert.assertEquals("************4444", dest.creditCardNumber); + Assert.assertNull(dest.street); + Assert.assertEquals("NY", dest.city); + } + + + @Test + public void filtersAreAppliedInRegisteredOrder() throws Throwable { + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.classMap(Source.class, Destination.class) + .field("address.street", "street") + .field("address.city", "city") + .byDefault().register(); + + factory.registerFilter(new SecurityFilter()); + factory.registerFilter(new SecurityFilter2()); + + MapperFacade mapper = factory.getMapperFacade(); + + Source source = new Source(); + source.name = new SourceName(); + source.name.first = "Joe"; + source.name.last = "Smith"; + source.id = 2L; + source.age = 35; + source.cost = 12.34d; + source.creditCardNumber = "5432109876543210"; + source.address = new SourceAddress(); + source.address.street = "ashbury"; + source.address.city = "SF"; + + Destination dest = mapper.map(source, Destination.class); + + Assert.assertEquals(source.name.first, dest.name.first); + Assert.assertEquals(source.name.last, dest.name.last); + Assert.assertNull(dest.age); + Assert.assertEquals(source.cost, dest.cost.doubleValue(), 0.01d); + Assert.assertEquals("------------3210", dest.creditCardNumber); + Assert.assertNull(dest.street); + Assert.assertEquals("SF", dest.city); + } + + /** + * OverwriteProtectionFilter is a filter that only allows a mapping to take + * place if the destination value is null. + */ + private static class OverwriteProtectionFilter extends NullFilter { + + @Override + public boolean shouldMap(Type sourceType, String sourceName, + S source, Type destType, String destName, D dest, + MappingContext mappingContext) { + return dest == null; + } + + @Override + public boolean appliesTo(Property source, Property destination) { + return !destination.isPrimitive(); + } + + } + + + private static class InfoFilter extends NullFilter, List> { + @Override + public , D extends List> boolean shouldMap(final Type sourceType, final String sourceName, final S source, final Type destType, final String destName, + final D dest, final MappingContext mappingContext) { + if (sourceName.equals("infoMap")) { + return false; + } + return true; + } + } + + public static class Source { + public SourceName name; + public Long id; + public int age; + public double cost; + public String creditCardNumber; + public SourceAddress address; + public Map infoMap; + } + + public static class SourceName { + public String first; + public String last; + } + + public static class SourceAddress { + public String street; + public String city; + } + + public static class Destination { + public DestinationName name; + public Long id; + public Integer age; + public BigDecimal cost; + public String creditCardNumber; + public String street; + public String city; + public List infos; + } + + public static class DestinationName { + public String first; + public String last; + } + + public static class Info { + public String item; + public String info; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/filters/NestedPropertyFilterTest.java b/core/src/test/java/ma/glasnost/orika/test/filters/NestedPropertyFilterTest.java new file mode 100644 index 00000000..bc428b40 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/filters/NestedPropertyFilterTest.java @@ -0,0 +1,99 @@ +package ma.glasnost.orika.test.filters; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingException; +import ma.glasnost.orika.NullFilter; +import ma.glasnost.orika.test.MappingUtil; + +import org.junit.Assert; +import org.junit.Test; + +public class NestedPropertyFilterTest { + + public static class A_Source { + + Integer value; + + public Integer getValue() { + return value; + } + + public void setValue(Integer value) { + this.value = value; + } + } + + public static class A1_Destination { + A2_Destination a2; + + public A2_Destination getA2() { + return a2; + } + + public void setA2(A2_Destination a2) { + this.a2 = a2; + } + } + + public static class A2_Destination { + A3_Destination a3; + + public A3_Destination getA3() { + return a3; + } + + public void setA3(A3_Destination a3) { + this.a3 = a3; + } + } + + public static class A3_Destination { + + A4_Destination a4; + + public A4_Destination getA4() { + return a4; + } + + public void setA4(A4_Destination a4) { + this.a4 = a4; + } + } + + public static class A4_Destination { + + Integer value; + + public Integer getValue() { + return value; + } + + public void setValue(Integer value) { + this.value = value; + } + } + + @Test + public void test() { + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.registerClassMap(factory.classMap(A_Source.class, A1_Destination.class) + .field("value", "a2.a3.a4.value") + ); + factory.registerFilter(new NullFilter()); + + MapperFacade mapper = factory.getMapperFacade(); + + A_Source a = new A_Source(); + a.setValue(null); + + try { + A1_Destination a1Destination = mapper.map(a, A1_Destination.class); + + Assert.assertEquals(null, a1Destination.getA2()); + } catch (MappingException e) { + Assert.fail(); + } + + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/filters/SourceNestedFilterTest.java b/core/src/test/java/ma/glasnost/orika/test/filters/SourceNestedFilterTest.java new file mode 100644 index 00000000..dc57db23 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/filters/SourceNestedFilterTest.java @@ -0,0 +1,68 @@ +package ma.glasnost.orika.test.filters; + +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import org.junit.Assert; +import org.junit.Test; + +/** + * @author: Ilya Krokhmalyov + * @email jad7kii@gmail.com + * @since: 5/6/14 + */ + +public class SourceNestedFilterTest { + + public static class A_Source { + private A1_Source a1_source; + + public A1_Source getA1_source() { + return a1_source; + } + + public void setA1_source(A1_Source a1_source) { + this.a1_source = a1_source; + } + } + + public static class A1_Source { + private Integer id; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + } + + public static class A_Destination { + private Integer id; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + } + + @Test + public void test() { + MapperFactory mapperFactory = new DefaultMapperFactory.Builder().captureFieldContext(true).build(); + + + mapperFactory.classMap(A_Source.class, A_Destination.class) + .field("a1_source.id", "id") + .register(); + + A_Source a_source = new A_Source(); + a_source.a1_source = new A1_Source(); + a_source.a1_source.id = 10; + + A_Destination map = mapperFactory.getMapperFacade().map(a_source, A_Destination.class); + Assert.assertEquals(map.getId(), Integer.valueOf(10)); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/generator/BeanToArrayGenerationTestCase.java b/core/src/test/java/ma/glasnost/orika/test/generator/BeanToArrayGenerationTestCase.java new file mode 100644 index 00000000..0d070c15 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/generator/BeanToArrayGenerationTestCase.java @@ -0,0 +1,154 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.generator; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.test.MappingUtil; + +import org.junit.Assert; +import org.junit.Test; + +public class BeanToArrayGenerationTestCase { + + private final double DELTA = 0.00001; + + @Test + public void testBeanToArrayGeneration() throws Exception { + + + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.classMap(Student.class, Object[].class) + .field("grade.letter", "0") + .field("grade.point", "1") + .field("grade.percentage", "2") + .field("name.first", "3") + .field("name.last", "4") + .byDefault() + .register(); + + MapperFacade mapper = factory.getMapperFacade(); + + Student student = new Student(); + student.id = "1"; + student.email = "test@test.com"; + student.name = new Name(); + student.name.first = "Chuck"; + student.name.last = "Testa"; + student.grade = new Grade(); + student.grade.letter = "B-"; + student.grade.percentage = 81.5; + student.grade.point = 2.7; + + Object[] result = mapper.map(student, Object[].class); + + int index = -1; + Assert.assertEquals(student.grade.letter, result[++index]); + Assert.assertEquals(student.grade.point, result[++index]); + Assert.assertEquals(student.grade.percentage, result[++index]); + Assert.assertEquals(student.name.first, result[++index]); + Assert.assertEquals(student.name.last, result[++index]); + Assert.assertEquals(student.id, result[++index]); + Assert.assertEquals(student.email, result[++index]); + + + Student mapBack = mapper.map(result, Student.class); + + Assert.assertEquals(student.id, mapBack.id); + Assert.assertEquals(student.email, mapBack.email); + Assert.assertEquals(student.name.first, mapBack.name.first); + Assert.assertEquals(student.name.last, mapBack.name.last); + Assert.assertEquals(student.grade.letter, mapBack.grade.letter); + Assert.assertEquals(student.grade.percentage, mapBack.grade.percentage, DELTA); + Assert.assertEquals(student.grade.point, mapBack.grade.point, DELTA); + + } + + @Test + public void testBeanToStringArrayGeneration() throws Exception { + + + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.classMap(Student.class, String[].class) + .field("grade.letter", "0") + .field("grade.point", "1") + .field("grade.percentage", "2") + .field("name.first", "3") + .field("name.last", "4") + .byDefault() + .register(); + + MapperFacade mapper = factory.getMapperFacade(); + + Student student = new Student(); + student.id = "1"; + student.email = "test@test.com"; + student.name = new Name(); + student.name.first = "Chuck"; + student.name.last = "Testa"; + student.grade = new Grade(); + student.grade.letter = "B-"; + student.grade.percentage = 81.5; + student.grade.point = 2.7; + + String[] result = mapper.map(student, String[].class); + + int index = -1; + Assert.assertEquals(student.grade.letter, result[++index]); + Assert.assertEquals("" + student.grade.point, result[++index]); + Assert.assertEquals("" + student.grade.percentage, result[++index]); + Assert.assertEquals(student.name.first, result[++index]); + Assert.assertEquals(student.name.last, result[++index]); + Assert.assertEquals(student.id, result[++index]); + Assert.assertEquals(student.email, result[++index]); + + + Student mapBack = mapper.map(result, Student.class); + + Assert.assertEquals(student.id, mapBack.id); + Assert.assertEquals(student.email, mapBack.email); + Assert.assertEquals(student.name.first, mapBack.name.first); + Assert.assertEquals(student.name.last, mapBack.name.last); + Assert.assertEquals(student.grade.letter, mapBack.grade.letter); + Assert.assertEquals(student.grade.percentage, mapBack.grade.percentage, DELTA); + Assert.assertEquals(student.grade.point, mapBack.grade.point, DELTA); + + } + + public static class Student { + public Grade grade; + public String id; + public String email; + public Name name; + } + + public static class Name { + public String first; + public String last; + } + + public static class Grade { + public double point; + public double percentage; + public String letter; + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/generator/BeanToListGenerationTestCase.java b/core/src/test/java/ma/glasnost/orika/test/generator/BeanToListGenerationTestCase.java new file mode 100644 index 00000000..33a93074 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/generator/BeanToListGenerationTestCase.java @@ -0,0 +1,147 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.generator; + +import java.util.List; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.test.MappingUtil; + +import org.junit.Assert; +import org.junit.Test; + +public class BeanToListGenerationTestCase { + + private final double DELTA = 0.00001; + + @Test + public void testBeanToListGeneration() throws Exception { + + + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.classMap(Student.class, List.class) + .field("grade.letter", "[0]") + .field("grade.point", "[1]") + .field("grade.percentage", "[2]") + .field("name.first", "[3]") + .field("name.last", "[4]") + .byDefault() + .register(); + + MapperFacade mapper = factory.getMapperFacade(); + + Student student = new Student(); + student.id = "1"; + student.email = "test@test.com"; + student.name = new Name(); + student.name.first = "Chuck"; + student.name.last = "Testa"; + student.grade = new Grade(); + student.grade.letter = "B-"; + student.grade.percentage = 81.5; + student.grade.point = 2.7; + + + @SuppressWarnings("unchecked") + List result = mapper.map(student, List.class); + + int index = -1; + Assert.assertEquals(student.grade.letter, result.get(++index)); + Assert.assertEquals(student.grade.point, result.get(++index)); + Assert.assertEquals(student.grade.percentage, result.get(++index)); + Assert.assertEquals(student.name.first, result.get(++index)); + Assert.assertEquals(student.name.last, result.get(++index)); + Assert.assertEquals(student.id, result.get(++index)); + Assert.assertEquals(student.email, result.get(++index)); + + + Student mapBack = mapper.map(result, Student.class); + + Assert.assertEquals(student.id, mapBack.id); + Assert.assertEquals(student.email, mapBack.email); + Assert.assertEquals(student.name.first, mapBack.name.first); + Assert.assertEquals(student.name.last, mapBack.name.last); + Assert.assertEquals(student.grade.letter, mapBack.grade.letter); + Assert.assertEquals(student.grade.percentage, mapBack.grade.percentage, DELTA); + Assert.assertEquals(student.grade.point, mapBack.grade.point, DELTA); + + } + + @Test + public void nestedListElement() { + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.classMap(Person.class, PersonDto.class) + .field("name.first", "names[0].name") + .register(); + + MapperFacade mapper = factory.getMapperFacade(); + + Person person = new Person(); + person.name = new Name(); + person.name.first = "Chuck"; + person.name.last = "Testa"; + + PersonDto result = mapper.map(person, PersonDto.class); + + Assert.assertNotNull(result.names); + Assert.assertEquals(person.name.first, result.names.get(0).name); + + Person mapBack = mapper.map(result, Person.class); + + Assert.assertNotNull(mapBack.name.first); + Assert.assertEquals(person.name.first, mapBack.name.first); + + } + + public static class Student { + public Grade grade; + public String id; + public String email; + public Name name; + } + + public static class Name { + public String first; + public String last; + } + + public static class NameDto { + public String name; + } + + public static class Grade { + public double point; + public double percentage; + public String letter; + } + + public static class Person { + public Name name; + } + + public static class PersonDto { + public List names; + } + + + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/generator/BeanToMapGenerationTestCase.java b/core/src/test/java/ma/glasnost/orika/test/generator/BeanToMapGenerationTestCase.java new file mode 100644 index 00000000..4ff50e7e --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/generator/BeanToMapGenerationTestCase.java @@ -0,0 +1,408 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.generator; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.UtilityResolver; +import ma.glasnost.orika.impl.generator.VariableRef; +import ma.glasnost.orika.metadata.Property; +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.metadata.TypeBuilder; +import ma.glasnost.orika.metadata.TypeFactory; +import ma.glasnost.orika.property.PropertyResolverStrategy; +import ma.glasnost.orika.test.MappingUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +public class BeanToMapGenerationTestCase { + + private final double DELTA = 0.00001; + + @Test + public void testBeanToMapGeneration() throws Exception { + + + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.classMap(Student.class, Map.class) + .field("grade.letter", "letterGrade") + .field("grade.point", "GPA") + .field("grade.percentage", "gradePercentage") + .field("name.first", "firstName") + .field("name.last", "lastName") + .byDefault() + .register(); + + MapperFacade mapper = factory.getMapperFacade(); + + Student student = new Student(); + student.id = "1"; + student.email = "test@test.com"; + student.name = new Name(); + student.name.first = "Chuck"; + student.name.last = "Testa"; + student.grade = new Grade(); + student.grade.letter = "B-"; + student.grade.percentage = 81.5; + student.grade.point = 2.7; + + + @SuppressWarnings("unchecked") + Map result = mapper.map(student, Map.class); + + Assert.assertEquals(student.id, result.get("id")); + Assert.assertEquals(student.email, result.get("email")); + Assert.assertEquals(student.name.first, result.get("firstName")); + Assert.assertEquals(student.name.last, result.get("lastName")); + Assert.assertEquals(student.grade.letter, result.get("letterGrade")); + Assert.assertEquals(student.grade.percentage, result.get("gradePercentage")); + Assert.assertEquals(student.grade.point, result.get("GPA")); + + Student mapBack = mapper.map(result, Student.class); + + Assert.assertEquals(student.id, mapBack.id); + Assert.assertEquals(student.email, mapBack.email); + Assert.assertEquals(student.name.first, mapBack.name.first); + Assert.assertEquals(student.name.last, mapBack.name.last); + Assert.assertEquals(student.grade.letter, mapBack.grade.letter); + Assert.assertEquals(student.grade.percentage, mapBack.grade.percentage, DELTA); + Assert.assertEquals(student.grade.point, mapBack.grade.point, DELTA); + + } + + @Test + public void testBeanToCustomMapGeneration() throws Exception { + + + MapperFactory factory = MappingUtil.getMapperFactory(); + + Type> mapType = new TypeBuilder>(){}.build(); + Type studentType = TypeFactory.valueOf(Student.class); + + factory.classMap(Student.class, mapType) + .field("grade.letter", "letterGrade") + .field("grade.point", "GPA") + .field("grade.percentage", "gradePercentage") + .field("name.first", "firstName") + .field("name.last", "lastName") + .byDefault() + .register(); + + MapperFacade mapper = factory.getMapperFacade(); + + Student student = new Student(); + student.id = "1"; + student.email = "test@test.com"; + student.name = new Name(); + student.name.first = "Chuck"; + student.name.last = "Testa"; + student.grade = new Grade(); + student.grade.letter = "B-"; + student.grade.percentage = 81.5; + student.grade.point = 2.7; + + Map result = mapper.map(student, studentType, mapType); + + Assert.assertEquals(student.id, result.get("id")); + Assert.assertEquals(student.email, result.get("email")); + Assert.assertEquals(student.name.first, result.get("firstName")); + Assert.assertEquals(student.name.last, result.get("lastName")); + Assert.assertEquals(student.grade.letter, result.get("letterGrade")); + Assert.assertEquals("" + student.grade.percentage, result.get("gradePercentage")); + Assert.assertEquals("" + student.grade.point, result.get("GPA")); + + Student mapBack = mapper.map(result, mapType, studentType); + + Assert.assertEquals(student.id, mapBack.id); + Assert.assertEquals(student.email, mapBack.email); + Assert.assertEquals(student.name.first, mapBack.name.first); + Assert.assertEquals(student.name.last, mapBack.name.last); + Assert.assertEquals(student.grade.letter, mapBack.grade.letter); + Assert.assertEquals(student.grade.percentage, mapBack.grade.percentage, DELTA); + Assert.assertEquals(student.grade.point, mapBack.grade.point, DELTA); + + } + + @Test + public void testResolveMapKeys() { + + PropertyResolverStrategy propertyResolver = UtilityResolver.getDefaultPropertyResolverStrategy(); + Property namesFirst = propertyResolver.getProperty(PersonDto.class, "names['first']"); + + Assert.assertNotNull(namesFirst); + Assert.assertEquals(TypeFactory.valueOf(String.class), namesFirst.getType()); + Assert.assertNull(namesFirst.getContainer()); + + VariableRef ref = new VariableRef(namesFirst, "destination"); + Assert.assertEquals("((java.lang.String)((java.util.Map)destination.names).get(\"first\"))", ref.toString()); + } + + @Test + public void testMapElementProperties() { + + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.classMap(Person.class, PersonDto.class) + .field("name.first", "names['first']") + .field("name.last", "names[\"last\"]") + .register(); + + MapperFacade mapper = factory.getMapperFacade(); + + Person person = new Person(); + person.name = new Name(); + person.name.first = "Chuck"; + person.name.last = "Testa"; + + PersonDto result = mapper.map(person, PersonDto.class); + + Assert.assertNotNull(result.names); + Assert.assertEquals(person.name.first, result.names.get("first")); + Assert.assertEquals(person.name.last, result.names.get("last")); + + Person mapBack = mapper.map(result, Person.class); + + Assert.assertNotNull(mapBack.name.first); + Assert.assertEquals(person.name.first, mapBack.name.first); + Assert.assertEquals(person.name.last, mapBack.name.last); + + } + + @Test + public void testNestedMapElement() { + + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.classMap(Person.class, PersonDto2.class) + .field("name.first", "names['self'].first") + .field("name.last", "names['self'].last") + .field("father.first", "names['father'].first") + .field("father.last", "names['father'].last") + .register(); + + MapperFacade mapper = factory.getMapperFacade(); + + Person person = new Person(); + person.name = new Name(); + person.name.first = "Chuck"; + person.name.last = "Testa"; + person.father = new Name(); + person.father.first = "Buck"; + person.father.last = "Testa"; + + PersonDto2 result = mapper.map(person, PersonDto2.class); + + Assert.assertNotNull(result.names); + Assert.assertEquals(person.name.first, result.names.get("self").first); + Assert.assertEquals(person.name.last, result.names.get("self").last); + Assert.assertEquals(person.father.first, result.names.get("father").first); + Assert.assertEquals(person.father.last, result.names.get("father").last); + + Person mapBack = mapper.map(result, Person.class); + + Assert.assertNotNull(mapBack.name.first); + Assert.assertEquals(person.name.first, mapBack.name.first); + Assert.assertEquals(person.name.last, mapBack.name.last); + Assert.assertEquals(person.father.first, mapBack.father.first); + Assert.assertEquals(person.father.last, mapBack.father.last); + + } + + @Test + public void testNestedMapElementWithIntegerKey() { + + + MapperFactory factory = MappingUtil.getMapperFactory(); + + Type> mapType = new TypeBuilder>(){}.build(); + Type nameType = TypeFactory.valueOf(Name.class); + + factory.classMap(Name.class, mapType) + .field("first", "['0']") + .field("last", "['42']") + .byDefault() + .register(); + + MapperFacade mapper = factory.getMapperFacade(); + + Name name = new Name(); + name.first = "Any First Name"; + name.last = "Any Last Name"; + + Map result = mapper.map(name, nameType, mapType); + + Assert.assertEquals(name.first, result.get(0)); + Assert.assertEquals(name.last, result.get(42)); + + Name mapBack = mapper.map(result, mapType, nameType); + + Assert.assertEquals(name.first, mapBack.first); + Assert.assertEquals(name.last, mapBack.last); + } + + @Test + public void testNestedMapElementWithEnumKey() { + + + MapperFactory factory = MappingUtil.getMapperFactory(); + + Type> mapType = new TypeBuilder>(){}.build(); + Type nameType = TypeFactory.valueOf(Name.class); + + factory.classMap(Name.class, mapType) + .field("first", "['FIRST']") + .field("last", "['LAST']") + .byDefault() + .register(); + + MapperFacade mapper = factory.getMapperFacade(); + + Name name = new Name(); + name.first = "Any First Name"; + name.last = "Any Last Name"; + + Map result = mapper.map(name, nameType, mapType); + + Assert.assertEquals(name.first, result.get(NameFields.FIRST)); + Assert.assertEquals(name.last, result.get(NameFields.LAST)); + + Name mapBack = mapper.map(result, mapType, nameType); + + Assert.assertEquals(name.first, mapBack.first); + Assert.assertEquals(name.last, mapBack.last); + } + + @Test + public void testDoubleNestedMapElement() { + + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.classMap(Person.class, PersonDto3.class) + .field("name.first", "names['self']['first']") + .field("name.last", "names['self']['last']") + .field("father.first", "names['father']['first']") + .field("father.last", "names['father']['last']") + .register(); + + MapperFacade mapper = factory.getMapperFacade(); + + Person person = new Person(); + person.name = new Name(); + person.name.first = "Chuck"; + person.name.last = "Testa"; + person.father = new Name(); + person.father.first = "Buck"; + person.father.last = "Testa"; + + PersonDto3 result = mapper.map(person, PersonDto3.class); + + Assert.assertNotNull(result.names); + Assert.assertEquals(person.name.first, result.names.get("self").get("first")); + Assert.assertEquals(person.name.last, result.names.get("self").get("last")); + Assert.assertEquals(person.father.first, result.names.get("father").get("first")); + Assert.assertEquals(person.father.last, result.names.get("father").get("last")); + + Person mapBack = mapper.map(result, Person.class); + + Assert.assertNotNull(mapBack.name.first); + Assert.assertEquals(person.name.first, mapBack.name.first); + Assert.assertEquals(person.name.last, mapBack.name.last); + Assert.assertEquals(person.father.first, mapBack.father.first); + Assert.assertEquals(person.father.last, mapBack.father.last); + + } + + @Test + public void testMapWithGenericSuperclassImplementation() { + + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.classMap(Person.class, PersonDto4.class) + .field("name.first", "names['self'].first") + .register(); + + MapperFacade mapper = factory.getMapperFacade(); + + Person person = new Person(); + person.name = new Name(); + person.name.first = "Chuck"; + + PersonDto4 result = mapper.map(person, PersonDto4.class); + + Assert.assertNotNull(result.names); + Assert.assertEquals(person.name.first, result.names.get("self").first); + + Person mapBack = mapper.map(result, Person.class); + + Assert.assertNotNull(mapBack.name.first); + Assert.assertEquals(person.name.first, mapBack.name.first); + } + + public static enum NameFields { + FIRST, LAST + } + + public static class Person { + public Name name; + public Name father; + } + + public static class PersonDto { + public Map names = new HashMap<>(); + } + + public static class PersonDto2 { + public Map names = new HashMap<>(); + } + + public static class PersonDto3 { + public Map> names = new HashMap<>(); + } + + public static class PersonDto4 { + public NameMap names = new NameMap(); + } + + public static class Student { + public Grade grade; + public String id; + public String email; + public Name name; + } + + public static class Name { + public String first; + public String last; + } + + public static class Grade { + public double point; + public double percentage; + public String letter; + } + + public static class NameMap extends HashMap{ + + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/generator/BeanToMultiOccurrenceTestCase.java b/core/src/test/java/ma/glasnost/orika/test/generator/BeanToMultiOccurrenceTestCase.java new file mode 100644 index 00000000..8c19c0d9 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/generator/BeanToMultiOccurrenceTestCase.java @@ -0,0 +1,388 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.generator; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.GeneratedObjectBase; +import ma.glasnost.orika.test.MappingUtil; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import javax.xml.datatype.DatatypeConfigurationException; +import javax.xml.datatype.DatatypeFactory; +import javax.xml.datatype.XMLGregorianCalendar; +import java.util.ArrayList; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +public class BeanToMultiOccurrenceTestCase { + + private DatatypeFactory dataTypeFactory; + + @Before + public void setUp() { + try { + dataTypeFactory = DatatypeFactory.newInstance(); + } catch (DatatypeConfigurationException e) { + throw new IllegalStateException(e); + } + } + + @Test + public void unequalSize() throws Exception { + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.registerClassMap(factory.classMap(MapOfScores.class, GenericDto.class) + .field("scores{key}", "stringArray{}") + .field("scores{value}", "intArray{}") + .byDefault()); + + /* + * Tell Orika how we should convert the list element type to map entry + */ + MapperFacade mapper = factory.getMapperFacade(); + + GenericDto source = new GenericDto(); + List testScores = new ArrayList<>(); + List numericScores = new ArrayList<>(); + testScores.add("A"); + numericScores.add(90); + testScores.add("B"); + numericScores.add(80); + testScores.add("C"); + + source.setStringArray(testScores.toArray(new String[testScores.size()])); + source.setIntArray(GeneratedObjectBase.intArray(numericScores)); + + MapOfScores result = mapper.map(source, MapOfScores.class); + + Assert.assertNotNull(result.getScores()); + Assert.assertTrue("90".equals(result.getScores().get("A"))); + Assert.assertTrue("80".equals(result.getScores().get("B"))); + Assert.assertFalse(result.getScores().containsKey("C")); + } + + /** + * Demonstrates how a single field can be mapped to more than one + * destination, in both directions. + * + * @throws Exception + */ + @Test + public void parallelWithConvertedTypes() throws Exception { + + MapperFactory factory = MappingUtil.getMapperFactory(true); + factory.registerClassMap(factory.classMap(MapOfPeople.class, GenericDto.class) + .field("people{value.birthDate}", "dateArray{}") + .field("people{value.name}", "stringArray{}") + .byDefault()); + + MapOfPeople peopleMap = new MapOfPeople(); + Person p = new Person(); + p.birthDate = DatatypeFactory.newInstance().newXMLGregorianCalendar("2001-02-03"); + p.name = "Jim"; + peopleMap.people.put(new Date(), p); + + p = new Person(); + p.birthDate = DatatypeFactory.newInstance().newXMLGregorianCalendar("2005-07-14"); + p.name = "Sue"; + peopleMap.people.put(new Date(System.currentTimeMillis() + 20000L), p); + + p = new Person(); + p.birthDate = DatatypeFactory.newInstance().newXMLGregorianCalendar("2003-07-14"); + p.name = "Sally"; + peopleMap.people.put(new Date(System.currentTimeMillis() + 9000000L), p); + + /* + * Tell Orika how we should convert the list element type to map entry + */ + MapperFacade mapper = factory.getMapperFacade(); + + GenericDto result = mapper.map(peopleMap, GenericDto.class); + + Assert.assertNotNull(result.dateArray); + Assert.assertNotNull(result.getStringArray()); + Assert.assertEquals(peopleMap.people.size(), result.dateArray.length); + Assert.assertEquals(peopleMap.people.size(), result.getStringArray().length); + int i = -1; + for (Person person : peopleMap.people.values()) { + ++i; + Assert.assertEquals(person.name, result.getStringArray()[i]); + Assert.assertTrue(toXMLGregorianCalendar(result.dateArray[i], dataTypeFactory).toXMLFormat().startsWith( + person.birthDate.toXMLFormat())); + } + + mapper.map(result, MapOfPeople.class); + } + + /** + * Verifies that we're able to map from a single to field to each of the + * individual elements of a multi-occurrence item + * + * @throws Exception + */ + @Test + public void oneToMany() throws Exception { + MapperFactory factory = MappingUtil.getMapperFactory(true); + factory.registerClassMap(factory.classMap(GroupOfStudents.class, MapOfStudents.class) + .field("names{}", "students{key.name}") + .field("defaultLetterGrade", "students{value.letterGrade}") + .field("defaultScore", "students{value.minimumScore}") + + .byDefault()); + + GroupOfStudents source = new GroupOfStudents(); + source.names = new ArrayList<>(); + source.names.add("Bob"); + source.names.add("Jim"); + source.names.add("Sally"); + source.defaultLetterGrade = 'C'; + source.defaultScore = 70; + + /* + * Tell Orika how we should convert the list element type to map entry + */ + MapperFacade mapper = factory.getMapperFacade(); + MapOfStudents result = mapper.map(source, MapOfStudents.class); + + Assert.assertNotNull(result); + Assert.assertNotNull(result.students); + Assert.assertFalse(result.students.isEmpty()); + Assert.assertEquals(source.names.size(), result.students.size()); + for (Grade grade : result.students.values()) { + Assert.assertEquals(source.defaultLetterGrade, grade.getLetterGrade().charValue()); + Assert.assertEquals(source.defaultScore, grade.getMinimumScore()); + } + + GroupOfStudents mapBack = mapper.map(result, GroupOfStudents.class); + + Assert.assertEquals(source.defaultLetterGrade, mapBack.defaultLetterGrade); + Assert.assertEquals(source.defaultScore, mapBack.defaultScore); + Assert.assertEquals(source.names, mapBack.names); + Assert.assertEquals(source.grades, mapBack.grades); + + } + + @SuppressWarnings("serial") + @Test + public void multipleParallel() throws Exception { + + MapperFactory factory = MappingUtil.getMapperFactory(true); + factory.registerClassMap(factory.classMap(MapOfScores.class, GenericDto.class) + .field("scores{key}", "stringArray{}") + .field("scores{value}", "intArray{}") + .field("scores{key}", "gradeList{letterGrade}") + .field("scores{value}", "gradeList{minimumScore}") + .byDefault()); + + MapOfScores source = new MapOfScores(); + source.setScores(new LinkedHashMap() { + { + put("A", "90"); + put("B", "80"); + put("C", "70"); + put("D", "60"); + put("F", "50"); + } + }); + + /* + * Tell Orika how we should convert the list element type to map entry + */ + MapperFacade mapper = factory.getMapperFacade(); + + GenericDto result = mapper.map(source, GenericDto.class); + + Assert.assertNotNull(result.getGradeList()); + Assert.assertEquals(source.getScores().size(), result.getGradeList().size()); + for (Grade g : result.getGradeList()) { + Assert.assertTrue(source.getScores().containsKey("" + g.getLetterGrade())); + Assert.assertTrue(source.getScores().get("" + g.getLetterGrade()).equals("" + g.getMinimumScore())); + } + + MapOfScores mapBack = mapper.map(result, MapOfScores.class); + Assert.assertTrue(source.getScores().keySet().containsAll(mapBack.getScores().keySet())); + Assert.assertTrue(mapBack.getScores().keySet().containsAll(source.getScores().keySet())); + } + + private static XMLGregorianCalendar toXMLGregorianCalendar(Date source, DatatypeFactory factory) { + + GregorianCalendar c = new GregorianCalendar(); + c.setTime(source); + + return factory.newXMLGregorianCalendar(c); + + } + + public static class MapOfScores { + + private Map scores; + + public Map getScores() { + return scores; + } + + public void setScores(Map scores) { + this.scores = scores; + } + } + + public static class MapOfPeople { + public Map people = new LinkedHashMap<>(); + } + + public static class Person { + public XMLGregorianCalendar birthDate; + public String name; + } + + public static class MapOfStudents { + public Map students = new LinkedHashMap<>(); + } + + public static class Grade { + int minimumScore; + Character letterGrade; + + public int getMinimumScore() { + return minimumScore; + } + + public void setMinimumScore(int minimumScore) { + this.minimumScore = minimumScore; + } + + public Character getLetterGrade() { + return letterGrade; + } + + public void setLetterGrade(Character letterGrade) { + this.letterGrade = letterGrade; + } + } + + public static class GroupOfStudents { + public List names; + public List grades; + public int defaultScore; + public char defaultLetterGrade; + } + + public static class GenericDto { + + private String[] stringArray; + private List stringList; + private int[] intArray; + private long[] longArray; + private List gradeList; + private Grade[] gradeArray; + private Map gradesByLetter; + private Map gradesByMinScore; + private Map lettersByGrade; + private Map scoresByGrade; + + public Date[] dateArray; + + public String[] getStringArray() { + return stringArray; + } + + public void setStringArray(String[] stringArray) { + this.stringArray = stringArray; + } + + public List getStringList() { + return stringList; + } + + public void setStringList(List stringList) { + this.stringList = stringList; + } + + public int[] getIntArray() { + return intArray; + } + + public void setIntArray(int[] intArray) { + this.intArray = intArray; + } + + public long[] getLongArray() { + return longArray; + } + + public void setLongArray(long[] longArray) { + this.longArray = longArray; + } + + public List getGradeList() { + return gradeList; + } + + public void setGradeList(List gradeList) { + this.gradeList = gradeList; + } + + public Grade[] getGradeArray() { + return gradeArray; + } + + public void setGradeArray(Grade[] gradeArray) { + this.gradeArray = gradeArray; + } + + public Map getGradesByLetter() { + return gradesByLetter; + } + + public void setGradesByLetter(Map gradesByLetter) { + this.gradesByLetter = gradesByLetter; + } + + public Map getGradesByMinScore() { + return gradesByMinScore; + } + + public void setGradesByMinScore(Map gradesByMinScore) { + this.gradesByMinScore = gradesByMinScore; + } + + public Map getLettersByGrade() { + return lettersByGrade; + } + + public void setLettersByGrade(Map lettersByGrade) { + this.lettersByGrade = lettersByGrade; + } + + public Map getScoresByGrade() { + return scoresByGrade; + } + + public void setScoresByGrade(Map scoresByGrade) { + this.scoresByGrade = scoresByGrade; + } + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/generator/CodeGenerationAddSpecificationCase.java b/core/src/test/java/ma/glasnost/orika/test/generator/CodeGenerationAddSpecificationCase.java new file mode 100644 index 00000000..fb8ea4d4 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/generator/CodeGenerationAddSpecificationCase.java @@ -0,0 +1,61 @@ +package ma.glasnost.orika.test.generator; + +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.impl.generator.CodeGenerationStrategy; +import ma.glasnost.orika.impl.generator.SourceCodeContext; +import ma.glasnost.orika.impl.generator.Specification; +import ma.glasnost.orika.impl.generator.VariableRef; +import ma.glasnost.orika.impl.generator.specification.Convert; +import ma.glasnost.orika.metadata.FieldMap; +import org.junit.Assert; +import org.junit.Test; + +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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. + */ +public class CodeGenerationAddSpecificationCase { + + @Test + public void testAddSpecification() { + Specification testSpec = new TestSpecification(); + DefaultMapperFactory.Builder builder = new DefaultMapperFactory.Builder(); + CodeGenerationStrategy codeGenerationStrategy = builder.getCodeGenerationStrategy(); + codeGenerationStrategy.addSpecification(testSpec, CodeGenerationStrategy.Position.IN_PLACE_OF, Convert.class); + DefaultMapperFactory mapperFactory= builder.build(); + + Assert.assertTrue(codeGenerationStrategy.getSpecifications().contains(testSpec)); + } + + private class TestSpecification extends Convert { + @Override + public boolean appliesTo(FieldMap fieldMap) { + return super.appliesTo(fieldMap); + } + + @Override + public String generateEqualityTestCode(FieldMap fieldMap, VariableRef source, VariableRef destination, + SourceCodeContext code) { + return super.generateEqualityTestCode(fieldMap, source, destination, code); + } + + @Override + public String generateMappingCode(FieldMap fieldMap, VariableRef source, VariableRef destination, + SourceCodeContext code) { + return super.generateMappingCode(fieldMap, source, destination, code); + } + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/generator/ExpanderTestCase.java b/core/src/test/java/ma/glasnost/orika/test/generator/ExpanderTestCase.java new file mode 100644 index 00000000..0b55b505 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/generator/ExpanderTestCase.java @@ -0,0 +1,235 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.generator; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.metadata.ScoringClassMapBuilder; +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.metadata.TypeBuilder; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** + * This test case demonstrates two things together: + * + * 1) The usage of the ScoringClassMapBuilder to automagically guess + * the right mapping of various fields based on their "sameness" + * + * 2) The usage of built-in nested field mapping functionality + * to handle mapping these objects, resulting in the mapping of a + * flat list structure into an expanded object graph by guessing + * how the fields should line up. + * + * + * @author matt.deboer@gmail.com + * + */ +public class ExpanderTestCase { + + public static class Year { + public int yearNumber; + public String yearAnimal; + public List months = new ArrayList<>(); + @Override + public String toString() { + return "Year [yearNumber=" + yearNumber + ", yearAnimal=" + yearAnimal + ", months=" + months + "]"; + } + @Override + public boolean equals(final Object other) { + if (!(other instanceof Year)) { + return false; + } + Year castOther = (Year) other; + return Objects.equals(yearNumber, castOther.yearNumber) && Objects.equals(yearAnimal, castOther.yearAnimal) + && Objects.equals(months, castOther.months); + } + @Override + public int hashCode() { + return Objects.hash(yearNumber, yearAnimal, months); + } + } + + public static class Month { + public int monthNumber; + public String monthName; + public List days = new ArrayList<>(); + @Override + public String toString() { + return "Month [monthNumber=" + monthNumber + ", monthName=" + monthName + ", days=" + days + "]"; + } + @Override + public boolean equals(final Object other) { + if (!(other instanceof Month)) { + return false; + } + Month castOther = (Month) other; + return Objects.equals(monthNumber, castOther.monthNumber) && Objects.equals(monthName, castOther.monthName) + && Objects.equals(days, castOther.days); + } + @Override + public int hashCode() { + return Objects.hash(monthNumber, monthName, days); + } + } + + public static class Day { + public int dayNumber; + public String dayOfWeek; + @Override + public String toString() { + return "Day [dayNumber=" + dayNumber + ", dayOfWeek=" + dayOfWeek + "]"; + } + @Override + public boolean equals(final Object other) { + if (!(other instanceof Day)) { + return false; + } + Day castOther = (Day) other; + return Objects.equals(dayNumber, castOther.dayNumber) && Objects.equals(dayOfWeek, castOther.dayOfWeek); + } + @Override + public int hashCode() { + return Objects.hash(dayNumber, dayOfWeek); + } + } + + public static class FlatData { + public int dayNumber; + public String dayOfWeek; + public int yearNumber; + public String yearAnimal; + public int monthNumber; + public String monthName; + @Override + public String toString() { + return "FlatData [dayNumber=" + dayNumber + ", dayOfWeek=" + dayOfWeek + ", yearNumber=" + yearNumber + + ", yearAnimal=" + yearAnimal + ", monthNumber=" + monthNumber + ", monthName=" + monthName + "]"; + } + @Override + public boolean equals(final Object other) { + if (!(other instanceof FlatData)) { + return false; + } + FlatData castOther = (FlatData) other; + return Objects.equals(dayNumber, castOther.dayNumber) && Objects.equals(dayOfWeek, castOther.dayOfWeek) + && Objects.equals(yearNumber, castOther.yearNumber) + && Objects.equals(yearAnimal, castOther.yearAnimal) + && Objects.equals(monthNumber, castOther.monthNumber) + && Objects.equals(monthName, castOther.monthName); + } + @Override + public int hashCode() { + return Objects.hash(dayNumber, dayOfWeek, yearNumber, yearAnimal, monthNumber, monthName); + } + } + + @Test + public void testExpand() { + + Type> typeOf_FlatData = new TypeBuilder>(){}.build(); + Type> typeOf_Year = new TypeBuilder>(){}.build(); + + MapperFactory mapperFactory = new DefaultMapperFactory.Builder() + .classMapBuilderFactory(new ScoringClassMapBuilder.Factory()) + .build(); + + mapperFactory.classMap(typeOf_FlatData, typeOf_Year).byDefault().register(); + + MapperFacade mapper = mapperFactory.getMapperFacade(); + + + List flatData = new ArrayList<>(); + FlatData item = new FlatData(); + item.dayNumber = 1; + item.dayOfWeek = "Monday"; + item.monthNumber = 10; + item.monthName = "October"; + item.yearNumber = 2011; + item.yearAnimal = "monkey"; + flatData.add(item); + + item = new FlatData(); + item.dayNumber = 2; + item.dayOfWeek = "Tuesday"; + item.monthNumber = 12; + item.monthName = "December"; + item.yearNumber = 2011; + item.yearAnimal = "monkey"; + flatData.add(item); + + item = new FlatData(); + item.dayNumber = 2; + item.dayOfWeek = "Tuesday"; + item.monthNumber = 12; + item.monthName = "December"; + item.yearNumber = 2012; + item.yearAnimal = "dragon"; + flatData.add(item); + + List years = mapper.map(flatData, typeOf_FlatData, typeOf_Year); + + Assert.assertNotNull(years); + Assert.assertFalse(years.isEmpty()); + Assert.assertEquals(2, years.size()); + + Year year = years.get(0); + Assert.assertEquals(2011, year.yearNumber); + Assert.assertEquals(2, year.months.size()); + + Month m1 = year.months.get(0); + Assert.assertEquals("October", m1.monthName); + Assert.assertEquals(10,m1.monthNumber); + + Day m1d1 = m1.days.get(0); + Assert.assertEquals("Monday", m1d1.dayOfWeek); + Assert.assertEquals(1,m1d1.dayNumber); + + Month m2 = year.months.get(1); + Assert.assertEquals("December", m2.monthName); + Assert.assertEquals(12, m2.monthNumber); + + Day m2d1 = m2.days.get(0); + Assert.assertEquals("Tuesday", m2d1.dayOfWeek); + Assert.assertEquals(2,m2d1.dayNumber); + + year = years.get(1); + Assert.assertEquals(2012, year.yearNumber); + Assert.assertEquals(1, year.months.size()); + + m1 = year.months.get(0); + Assert.assertEquals("December", m1.monthName); + Assert.assertEquals(12, m1.monthNumber); + + m1d1 = m1.days.get(0); + Assert.assertEquals("Tuesday", m1d1.dayOfWeek); + Assert.assertEquals(2,m1d1.dayNumber); + + + List mapBack = mapper.map(years, typeOf_Year, typeOf_FlatData); + + Assert.assertEquals(flatData, mapBack); + + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/generator/MapNullsTestCase.java b/core/src/test/java/ma/glasnost/orika/test/generator/MapNullsTestCase.java new file mode 100644 index 00000000..e76f3d5c --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/generator/MapNullsTestCase.java @@ -0,0 +1,203 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.generator; + +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/** + * @author matt.deboer@gmail.com + * + */ +public class MapNullsTestCase { + + public enum Position { + FIRST, + LAST + } + + public static class Container { + public long longValue; + public String stringValue; + public List listOfString; + public String[] arrayOfString; + public int[] arrayOfInt; + public Map map; + public Position enumValue; + } + + public static class Container2 { + public long longValue; + public String stringValue; + public List listOfString; + public String[] arrayOfString; + public int[] arrayOfInt; + public Map map; + public Position enumValue; + } + + @Test + public void mapNulls_False() { + + MapperFactory mapperFactory = new DefaultMapperFactory.Builder().mapNulls(false).build(); + + Container a = new Container(); + Container b = new Container(); + + b.longValue = 1L; + b.stringValue = "TEST A"; + b.arrayOfString = new String[]{"a", "b", "c"}; + b.arrayOfInt = new int[] {1,2,3}; + b.listOfString = Arrays.asList("l1","l2"); + b.map = Collections.singletonMap("key", (Object)"value"); + b.enumValue = Position.FIRST; + + mapperFactory.getMapperFacade().map(a, b); + + Assert.assertNotNull( b.stringValue ); + Assert.assertNotNull( b.arrayOfString ); + Assert.assertNotNull( b.arrayOfInt ); + Assert.assertNotNull( b.listOfString ); + Assert.assertNotNull( b.map ); + Assert.assertNotNull( b.enumValue ); + } + + @Test + public void mapNulls_True() { + + MapperFactory mapperFactory = new DefaultMapperFactory.Builder().mapNulls(true).build(); + + Container a = new Container(); + Container b = new Container(); + + b.longValue = 1L; + b.stringValue = "TEST A"; + b.arrayOfString = new String[]{"a", "b", "c"}; + b.arrayOfInt = new int[] {1,2,3}; + b.listOfString = Arrays.asList("l1","l2"); + b.map = Collections.singletonMap("key", (Object)"value"); + b.enumValue = Position.FIRST; + + mapperFactory.getMapperFacade().map(a, b); + + Assert.assertNull( b.stringValue ); + Assert.assertNull( b.arrayOfString ); + Assert.assertNull( b.arrayOfInt ); + Assert.assertNull( b.listOfString ); + Assert.assertNull( b.map ); + Assert.assertNull( b.enumValue ); + } + + @Test + public void mapNulls_True_ClassLevel() { + + MapperFactory mapperFactory = new DefaultMapperFactory.Builder().mapNulls(false).build(); + + mapperFactory.classMap(Container.class, Container2.class) + .mapNulls(true).byDefault().register(); + + Container a = new Container(); + Container2 b = new Container2(); + + b.longValue = 1L; + b.stringValue = "TEST A"; + b.arrayOfString = new String[]{"a", "b", "c"}; + b.arrayOfInt = new int[] {1,2,3}; + b.listOfString = Arrays.asList("l1","l2"); + b.map = Collections.singletonMap("key", (Object)"value"); + b.enumValue = Position.FIRST; + + mapperFactory.getMapperFacade().map(a, b); + + Assert.assertNull( b.stringValue ); + Assert.assertNull( b.arrayOfString ); + Assert.assertNull( b.arrayOfInt ); + Assert.assertNull( b.listOfString ); + Assert.assertNull( b.map ); + Assert.assertNull( b.enumValue ); + + + } + + @Test + public void mapNulls_False_ClassLevel() { + + MapperFactory mapperFactory = new DefaultMapperFactory.Builder().mapNulls(true).build(); + + mapperFactory.classMap(Container.class, Container2.class) + .mapNulls(false).byDefault().register(); + + Container a = new Container(); + Container2 b = new Container2(); + + b.longValue = 1L; + b.stringValue = "TEST A"; + b.arrayOfString = new String[]{"a", "b", "c"}; + b.arrayOfInt = new int[] {1,2,3}; + b.listOfString = Arrays.asList("l1","l2"); + b.map = Collections.singletonMap("key", (Object)"value"); + b.enumValue = Position.FIRST; + + mapperFactory.getMapperFacade().map(a, b); + + Assert.assertNotNull( b.stringValue ); + Assert.assertNotNull( b.arrayOfString ); + Assert.assertNotNull( b.arrayOfInt ); + Assert.assertNotNull( b.listOfString ); + Assert.assertNotNull( b.map ); + Assert.assertNotNull( b.enumValue ); + } + + @Test + public void mapNulls_FieldLevel() { + + MapperFactory mapperFactory = new DefaultMapperFactory.Builder().mapNulls(false).build(); + + mapperFactory.classMap(Container.class, Container2.class) + .mapNulls(false) + .fieldMap("arrayOfString").mapNulls(true).add() + .byDefault().register(); + + Container a = new Container(); + Container2 b = new Container2(); + + b.longValue = 1L; + b.stringValue = "TEST A"; + b.arrayOfString = new String[]{"a", "b", "c"}; + b.arrayOfInt = new int[] {1,2,3}; + b.listOfString = Arrays.asList("l1","l2"); + b.map = Collections.singletonMap("key", (Object)"value"); + b.enumValue = Position.FIRST; + + mapperFactory.getMapperFacade().map(a, b); + + Assert.assertNotNull( b.stringValue ); + Assert.assertNull( b.arrayOfString ); + Assert.assertNotNull( b.arrayOfInt ); + Assert.assertNotNull( b.listOfString ); + Assert.assertNotNull( b.map ); + Assert.assertNotNull( b.enumValue ); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/generator/MultiOccurrenceToMultiOccurrenceTestCase.java b/core/src/test/java/ma/glasnost/orika/test/generator/MultiOccurrenceToMultiOccurrenceTestCase.java new file mode 100644 index 00000000..014edfce --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/generator/MultiOccurrenceToMultiOccurrenceTestCase.java @@ -0,0 +1,386 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.generator; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.impl.GeneratedObjectBase; +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.test.MappingUtil; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import javax.xml.datatype.DatatypeConfigurationException; +import javax.xml.datatype.DatatypeFactory; +import javax.xml.datatype.XMLGregorianCalendar; +import java.util.ArrayList; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +public class MultiOccurrenceToMultiOccurrenceTestCase { + + private DatatypeFactory dataTypeFactory; + + @Before + public void setUp() { + try { + dataTypeFactory = DatatypeFactory.newInstance(); + } catch (DatatypeConfigurationException e) { + throw new IllegalStateException(e); + } + } + + @Test + public void unequalSize() throws Exception { + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.registerClassMap(factory.classMap(MapOfScores.class, GenericDto.class) + .field("scores{key}", "stringArray{}") + .field("scores{value}", "intArray{}") + .byDefault()); + + /* + * Tell Orika how we should convert the list element type to map entry + */ + MapperFacade mapper = factory.getMapperFacade(); + + GenericDto source = new GenericDto(); + List testScores = new ArrayList<>(); + List numericScores = new ArrayList<>(); + testScores.add("A"); + numericScores.add(90); + testScores.add("B"); + numericScores.add(80); + testScores.add("C"); + + source.setStringArray(testScores.toArray(new String[testScores.size()])); + source.setIntArray(GeneratedObjectBase.intArray(numericScores)); + + MapOfScores result = mapper.map(source, MapOfScores.class); + + Assert.assertNotNull(result.getScores()); + Assert.assertTrue("90".equals(result.getScores().get("A"))); + Assert.assertTrue("80".equals(result.getScores().get("B"))); + Assert.assertFalse(result.getScores().containsKey("C")); + } + + /** + * Demonstrates how a single field can be mapped to more than one + * destination, in both directions. + * + * @throws Exception + */ + @Test + public void parallelWithConvertedTypes() throws Exception { + + MapperFactory factory = MappingUtil.getMapperFactory(true); + factory.registerClassMap(factory.classMap(MapOfPeople.class, GenericDto.class) + .field("people{value.birthDate}", "dateArray{}") + .field("people{value.name}", "stringArray{}") + .byDefault()); + + MapOfPeople peopleMap = new MapOfPeople(); + Person p = new Person(); + p.birthDate = DatatypeFactory.newInstance().newXMLGregorianCalendar("2001-02-03"); + p.name = "Jim"; + peopleMap.people.put(new Date(), p); + + p = new Person(); + p.birthDate = DatatypeFactory.newInstance().newXMLGregorianCalendar("2005-07-14"); + p.name = "Sue"; + peopleMap.people.put(new Date(System.currentTimeMillis() + 20000L), p); + + p = new Person(); + p.birthDate = DatatypeFactory.newInstance().newXMLGregorianCalendar("2003-07-14"); + p.name = "Sally"; + peopleMap.people.put(new Date(System.currentTimeMillis() + 9000000L), p); + + /* + * Tell Orika how we should convert the list element type to map entry + */ + MapperFacade mapper = factory.getMapperFacade(); + + GenericDto result = mapper.map(peopleMap, GenericDto.class); + + Assert.assertNotNull(result.dateArray); + Assert.assertNotNull(result.getStringArray()); + Assert.assertEquals(peopleMap.people.size(), result.dateArray.length); + Assert.assertEquals(peopleMap.people.size(), result.getStringArray().length); + int i = -1; + for (Person person : peopleMap.people.values()) { + ++i; + Assert.assertEquals(person.name, result.getStringArray()[i]); + Assert.assertTrue(toXMLGregorianCalendar(result.dateArray[i], dataTypeFactory).toXMLFormat().startsWith( + person.birthDate.toXMLFormat())); + } + + mapper.map(result, MapOfPeople.class); + } + + @SuppressWarnings("serial") + @Test + public void multipleParallel() throws Exception { + + MapperFactory factory = MappingUtil.getMapperFactory(true); + factory.registerClassMap(factory.classMap(MapOfScores.class, GenericDto.class) + .field("scores{key}", "stringArray{}") + .field("scores{value}", "intArray{}") + .field("scores{key}", "gradeList{letterGrade}") + .field("scores{value}", "gradeList{minimumScore}") + .byDefault()); + + MapOfScores source = new MapOfScores(); + source.setScores(new LinkedHashMap() { + { + put("A", "90"); + put("B", "80"); + put("C", "70"); + put("D", "60"); + put("F", "50"); + } + }); + + /* + * Tell Orika how we should convert the list element type to map entry + */ + MapperFacade mapper = factory.getMapperFacade(); + + GenericDto result = mapper.map(source, GenericDto.class); + + Assert.assertNotNull(result.getGradeList()); + Assert.assertEquals(source.getScores().size(), result.getGradeList().size()); + for (Grade g : result.getGradeList()) { + Assert.assertTrue(source.getScores().containsKey("" + g.getLetterGrade())); + Assert.assertTrue(source.getScores().get("" + g.getLetterGrade()).equals("" + g.getMinimumScore())); + } + + MapOfScores mapBack = mapper.map(result, MapOfScores.class); + Assert.assertTrue(source.getScores().keySet().containsAll(mapBack.getScores().keySet())); + Assert.assertTrue(mapBack.getScores().keySet().containsAll(source.getScores().keySet())); + } + + @Test + public void mappingContext() throws Exception { + + MapperFactory factory = MappingUtil.getMapperFactory(true); + factory.registerClassMap(factory.classMap(MapOfScores.class, GenericDto.class) + .field("scores{key}", "gradeList{letterGrade}") + .field("scores{value}", "gradeList{minimumScore}") + .byDefault()); + + MapOfScores source = new MapOfScores(); + source.setScores(new LinkedHashMap() { + { + put("A", "90"); + put("B", "80"); + put("C", "70"); + put("D", "60"); + put("F", "50"); + } + }); + + MapperFacade mapper = factory.getMapperFacade(); + + final int[] maxDepth = new int[] { 0 }; + MappingContext context = new MappingContext(null) { + @Override + public void beginMapping(Type sourceType, Object source, Type destType, Object dest) { + super.beginMapping(sourceType, source, destType, dest); + + maxDepth[0] = getDepth(); + + switch (getDepth()) { + case 1: + Assert.assertEquals(MapOfScores.class, sourceType.getRawType()); + Assert.assertEquals(GenericDto.class, destType.getRawType()); + Assert.assertNotNull(source); + Assert.assertNotNull(dest); + break; + + case 2: + Assert.assertEquals(Map.class, sourceType.getRawType()); + Assert.assertEquals(List.class, destType.getRawType()); + Assert.assertEquals(5, ((Map) source).size()); + Assert.assertNotNull(dest); + break; + + default: + Assert.fail("Unexpected depth " + getDepth()); + } + } + }; + + mapper.map(source, GenericDto.class, context); + Assert.assertEquals(2, maxDepth[0]); + } + + private static XMLGregorianCalendar toXMLGregorianCalendar(Date source, DatatypeFactory factory) { + + GregorianCalendar c = new GregorianCalendar(); + c.setTime(source); + + return factory.newXMLGregorianCalendar(c); + + } + + public static class MapOfScores { + + private Map scores; + + public Map getScores() { + return scores; + } + + public void setScores(Map scores) { + this.scores = scores; + } + } + + public static class MapOfPeople { + public Map people = new LinkedHashMap<>(); + } + + public static class Person { + public XMLGregorianCalendar birthDate; + public String name; + } + + public static class Grade { + int minimumScore; + Character letterGrade; + + public int getMinimumScore() { + return minimumScore; + } + + public void setMinimumScore(int minimumScore) { + this.minimumScore = minimumScore; + } + + public Character getLetterGrade() { + return letterGrade; + } + + public void setLetterGrade(Character letterGrade) { + this.letterGrade = letterGrade; + } + } + + public static class GenericDto { + + private String[] stringArray; + private List stringList; + private int[] intArray; + private long[] longArray; + private List gradeList; + private Grade[] gradeArray; + private Map gradesByLetter; + private Map gradesByMinScore; + private Map lettersByGrade; + private Map scoresByGrade; + + public Date[] dateArray; + + public String[] getStringArray() { + return stringArray; + } + + public void setStringArray(String[] stringArray) { + this.stringArray = stringArray; + } + + public List getStringList() { + return stringList; + } + + public void setStringList(List stringList) { + this.stringList = stringList; + } + + public int[] getIntArray() { + return intArray; + } + + public void setIntArray(int[] intArray) { + this.intArray = intArray; + } + + public long[] getLongArray() { + return longArray; + } + + public void setLongArray(long[] longArray) { + this.longArray = longArray; + } + + public List getGradeList() { + return gradeList; + } + + public void setGradeList(List gradeList) { + this.gradeList = gradeList; + } + + public Grade[] getGradeArray() { + return gradeArray; + } + + public void setGradeArray(Grade[] gradeArray) { + this.gradeArray = gradeArray; + } + + public Map getGradesByLetter() { + return gradesByLetter; + } + + public void setGradesByLetter(Map gradesByLetter) { + this.gradesByLetter = gradesByLetter; + } + + public Map getGradesByMinScore() { + return gradesByMinScore; + } + + public void setGradesByMinScore(Map gradesByMinScore) { + this.gradesByMinScore = gradesByMinScore; + } + + public Map getLettersByGrade() { + return lettersByGrade; + } + + public void setLettersByGrade(Map lettersByGrade) { + this.lettersByGrade = lettersByGrade; + } + + public Map getScoresByGrade() { + return scoresByGrade; + } + + public void setScoresByGrade(Map scoresByGrade) { + this.scoresByGrade = scoresByGrade; + } + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/generator/PropertiesWithNoSetterTestCase.java b/core/src/test/java/ma/glasnost/orika/test/generator/PropertiesWithNoSetterTestCase.java new file mode 100644 index 00000000..c67a60b0 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/generator/PropertiesWithNoSetterTestCase.java @@ -0,0 +1,80 @@ +package ma.glasnost.orika.test.generator; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.test.MappingUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.util.UUID; + + +/** + * Verify that we can properly map non-assignable properties of an object, + * so long as they are not immutable + * + * + */ +public class PropertiesWithNoSetterTestCase { + + + public static class Person { + public String firstName; + public String lastName; + } + + public static class SomeObject { + + private final Person person; + private final String id; + + public SomeObject() { + this.person = new Person(); + this.id = UUID.randomUUID().toString(); + } + + public Person getPerson() { + return person; + } + + public String getId() { + return id; + } + + } + + public static class AnotherObject { + + private final Person person; + private final String id; + + public AnotherObject() { + this.person = new Person(); + this.id = UUID.randomUUID().toString(); + } + + public Person getPerson() { + return person; + } + + public String getId() { + return id; + } + } + + @Test + public void test() { + + MapperFactory factory = MappingUtil.getMapperFactory(); + MapperFacade mapper = factory.getMapperFacade(); + + SomeObject source = new SomeObject(); + source.getPerson().firstName = "Joe"; + source.getPerson().lastName = "Smith"; + + AnotherObject dest = mapper.map(source, AnotherObject.class); + Assert.assertEquals(source.getPerson().firstName, dest.getPerson().firstName); + Assert.assertEquals(source.getPerson().lastName, dest.getPerson().lastName); + Assert.assertNotEquals(source.getId(), dest.getId()); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/generator/RetrieveDestinationValueOnMappingTestCase.java b/core/src/test/java/ma/glasnost/orika/test/generator/RetrieveDestinationValueOnMappingTestCase.java new file mode 100644 index 00000000..5ef7ce82 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/generator/RetrieveDestinationValueOnMappingTestCase.java @@ -0,0 +1,305 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2019 Orika 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 ma.glasnost.orika.test.generator; + +import com.google.common.collect.ImmutableMap; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +public class RetrieveDestinationValueOnMappingTestCase { + + public static class Container1 { + private long longValue1; + private String stringValue1; + private List listOfString1; + private String[] arrayOfString1; + private int[] arrayOfInt1; + private Map map1; + private MapNullsTestCase.Position enumValue1; + + public long getLongValue() { + return longValue1; + } + + public void setLongValue(long longValue) { + this.longValue1 = longValue; + } + + public String getStringValue() { + return stringValue1; + } + + public void setStringValue(String stringValue) { + this.stringValue1 = stringValue; + } + + public List getListOfString() { + return listOfString1; + } + + public void setListOfString(List listOfString) { + this.listOfString1 = listOfString; + } + + public String[] getArrayOfString() { + return arrayOfString1; + } + + public void setArrayOfString(String[] arrayOfString) { + this.arrayOfString1 = arrayOfString; + } + + public int[] getArrayOfInt() { + return arrayOfInt1; + } + + public void setArrayOfInt(int[] arrayOfInt) { + this.arrayOfInt1 = arrayOfInt; + } + + public Map getMap() { + return map1; + } + + public void setMap(Map map) { + this.map1 = map; + } + + public MapNullsTestCase.Position getEnumValue() { + return enumValue1; + } + + public void setEnumValue(MapNullsTestCase.Position enumValue) { + this.enumValue1 = enumValue; + } + } + + public static class Container2 { + private long myLongValue; + private String myStringValue; + private List myListOfString; + private String[] myArrayOfString; + private int[] myArrayOfInt; + private Map myMap; + private MapNullsTestCase.Position myEnumValue; + private Object myObject; + + private boolean longSet, stringSet, listOfStringSet, arrayOfStringSet, arrayOfIntSet, mapSet, enumSet; + + public long getLongValue() { + if(!longSet){ + throw new RuntimeException(); + } + return myLongValue; + } + + public void setLongValue(long longValue) { + this.myLongValue = longValue; + longSet = true; + } + + public String getStringValue() { + if(!stringSet){ + throw new RuntimeException(); + } + return myStringValue; + } + + public void setStringValue(String stringValue) { + this.myStringValue = stringValue; + stringSet = true; + } + + public List getListOfString() { + if(!listOfStringSet){ + throw new RuntimeException(); + } + return myListOfString; + } + + public void setListOfString(List listOfString) { + this.myListOfString = listOfString; + listOfStringSet = true; + } + + public String[] getArrayOfString() { + if(!arrayOfStringSet){ + throw new RuntimeException(); + } + return myArrayOfString; + } + + public void setArrayOfString(String[] arrayOfString) { + this.myArrayOfString = arrayOfString; + arrayOfStringSet = true; + } + + public int[] getArrayOfInt() { + if(!arrayOfIntSet){ + throw new RuntimeException(); + } + return myArrayOfInt; + } + + public void setArrayOfInt(int[] arrayOfInt) { + this.myArrayOfInt = arrayOfInt; + arrayOfIntSet = true; + } + + public Map getMap() { + if(!mapSet){ + throw new RuntimeException(); + } + return myMap; + } + + public void setMap(Map map) { + this.myMap = map; + mapSet = true; + } + + public MapNullsTestCase.Position getEnumValue() { + if(!enumSet){ + throw new RuntimeException(); + } + return myEnumValue; + } + + public void setEnumValue(MapNullsTestCase.Position enumValue) { + this.myEnumValue = enumValue; + enumSet = true; + } + + public Object getMyObject() { + return myObject; + } + + public void setMyObject(Object myObject) { + this.myObject = myObject; + } + } + + @Test + public void shouldMapWithDisabledRetrievalOfDestinationValueOnMapping(){ + + MapperFactory mapperFactory = new DefaultMapperFactory.Builder().captureFieldContext(true) + .getDestinationOnMapping(false).build(); + mapperFactory.classMap(Container1.class, Container2.class) + .mapNulls(true) + .mapNullsInReverse(true) + .byDefault() + .register(); + + Container1 container1 = buildContainer1(); + Container2 container2 = new Container2(); + Object myObject = new Object(); + container2.setMyObject(myObject); + mapperFactory.getMapperFacade().map(container1, container2); + + assertContainersEquals(container1, container2); + Assert.assertEquals(myObject, container2.getMyObject()); + } + + @Test(expected = RuntimeException.class) + public void shouldFailWithEnabledRetrievalOfDestinationValueOnMapping(){ + + MapperFactory mapperFactory = new DefaultMapperFactory.Builder().captureFieldContext(true).build(); + mapperFactory.classMap(Container1.class, Container2.class) + .mapNulls(true) + .mapNullsInReverse(true) + .byDefault() + .register(); + + Container1 container1 = buildContainer1(); + Container2 container2 = new Container2(); + Object myObject = new Object(); + container2.setMyObject(myObject); + + mapperFactory.getMapperFacade().map(container1, container2); + } + + @Test + public void shouldMapWithEnabledRetrievalOfDestinationValueOnMapping(){ + + MapperFactory mapperFactory = new DefaultMapperFactory.Builder().captureFieldContext(true).build(); + mapperFactory.classMap(Container1.class, Container2.class) + .mapNulls(true) + .mapNullsInReverse(true) + .byDefault() + .register(); + + Container1 container1 = buildContainer1(); + Container2 container2 = buildContainer2(); + Object myObject = new Object(); + container2.setMyObject(myObject); + + mapperFactory.getMapperFacade().map(container1, container2); + + assertContainersEquals(container1, container2); + Assert.assertEquals(myObject, container2.getMyObject()); + } + + private void assertContainersEquals(Container1 container1, Container2 container2){ + + Assert.assertEquals(container1.getLongValue(), container2.getLongValue()); + Assert.assertEquals(container1.getStringValue(), container2.getStringValue()); + Assert.assertEquals(container1.getListOfString(), container2.getListOfString()); + Assert.assertArrayEquals(container1.getArrayOfInt(), container2.getArrayOfInt()); + Assert.assertArrayEquals(container1.getArrayOfString(), container2.getArrayOfString()); + Assert.assertEquals(container1.getMap(), container2.getMap()); + Assert.assertEquals(container1.getEnumValue(), container2.getEnumValue()); + } + + private Container1 buildContainer1(){ + + Container1 container1 = new Container1(); + + container1.longValue1 = 1L; + container1.stringValue1 = "TEST A"; + container1.arrayOfString1 = new String[]{"a", "b", "c"}; + container1.arrayOfInt1 = new int[] {1,2,3}; + container1.listOfString1 = Arrays.asList("l1","l2"); + container1.map1 = Collections.singletonMap("key1", "value1"); + container1.enumValue1 = MapNullsTestCase.Position.FIRST; + + return container1; + } + + private Container2 buildContainer2(){ + + Container2 container2 = new Container2(); + + container2.setLongValue(0L); + container2.setStringValue("TEST B"); + container2.setArrayOfString(new String[]{"d", "e"}); + container2.setArrayOfInt(new int[] {4, 5}); + + container2.setListOfString(Arrays.asList("l3","l4","l5")); + container2.setMap(ImmutableMap.of("key2", "value2", "key3", 3)); + container2.setEnumValue(MapNullsTestCase.Position.LAST); + + return container2; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/generator/TestCompilerStrategyWritingFiles.java b/core/src/test/java/ma/glasnost/orika/test/generator/TestCompilerStrategyWritingFiles.java new file mode 100644 index 00000000..27df8327 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/generator/TestCompilerStrategyWritingFiles.java @@ -0,0 +1,93 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.generator; + +import java.io.File; + +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.runner.RunWith; + +import ma.glasnost.orika.OrikaSystemProperties; +import ma.glasnost.orika.test.DynamicSuite; +import ma.glasnost.orika.test.DynamicSuite.Scenario; +import ma.glasnost.orika.test.DynamicSuite.TestCasePattern; + +/** + * This provides a test case that verifies that Orika generates source and + * class files to the locations expected. + * + * It is marked to be ignored, because writing to an absolute file location + * is generally not repeatable in a unit test. + * The test is provided anyway for verification of the functionality. + * + * @author matt.deboer@gmail.com + * + */ +@RunWith(DynamicSuite.class) +@TestCasePattern(".*TestCase.class") +@Scenario(name="writeToUserHome") +@Ignore +public class TestCompilerStrategyWritingFiles { + + @BeforeClass + public static void writeDebugFiles() { + System.setProperty(OrikaSystemProperties.WRITE_SOURCE_FILES_TO_PATH, + System.getProperty("user.home")+"/.orikaGenerated/src/"); + System.setProperty(OrikaSystemProperties.WRITE_CLASS_FILES_TO_PATH, + System.getProperty("user.home")+"/.orikaGenerated/bin/"); + System.setProperty(OrikaSystemProperties.WRITE_SOURCE_FILES, "true"); + System.setProperty(OrikaSystemProperties.WRITE_CLASS_FILES, "true"); + + } + + @AfterClass + public static void tearDown() { + System.clearProperty(OrikaSystemProperties.WRITE_SOURCE_FILES_TO_PATH); + System.clearProperty(OrikaSystemProperties.WRITE_CLASS_FILES_TO_PATH); + System.clearProperty(OrikaSystemProperties.WRITE_SOURCE_FILES); + System.clearProperty(OrikaSystemProperties.WRITE_CLASS_FILES); + System.clearProperty(OrikaSystemProperties.COMPILER_STRATEGY); + + File generatedSrc = new File(System.getProperty("user.home")+"/.orikaGenerated/src/"); + File generatedBin = new File(System.getProperty("user.home")+"/.orikaGenerated/bin/"); + File generatedSrcFiles = null; + File generatedBinFiles = null; + try { + Assert.assertTrue(generatedSrc.exists()); + generatedSrcFiles = new File(generatedSrc,"ma/glasnost/orika/generated/"); + Assert.assertTrue(generatedSrcFiles.isDirectory()); + Assert.assertTrue(generatedSrcFiles.listFiles().length > 0); + + Assert.assertTrue(generatedBin.exists()); + generatedBinFiles = new File(generatedBin,"ma/glasnost/orika/generated/"); + Assert.assertTrue(generatedBinFiles.isDirectory()); + Assert.assertTrue(generatedBinFiles.listFiles().length > 0); + + } finally { + // Note: this is coming from hibernate jar which is included only for test + //TODO: is this still needed? The function doesn't exist anymore + //IOUtils.deleteRecursive(generatedSrc.getParentFile().getAbsolutePath(), true); + } + + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/generator/janino/JaninoCompilerStrategyTestSuite.java b/core/src/test/java/ma/glasnost/orika/test/generator/janino/JaninoCompilerStrategyTestSuite.java new file mode 100644 index 00000000..3417d34e --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/generator/janino/JaninoCompilerStrategyTestSuite.java @@ -0,0 +1,35 @@ +package ma.glasnost.orika.test.generator.janino; + +import ma.glasnost.orika.OrikaSystemProperties; +import ma.glasnost.orika.test.DynamicSuite; +import ma.glasnost.orika.test.DynamicSuite.Scenario; +import ma.glasnost.orika.test.DynamicSuite.TestCasePattern; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; + +/** + * This provides the equivalent of a test suite which will run all the defined + * test cases (matching ".*TestCase.class") using JaninoCompilerStrategy as the + * compiler strategy instead of JaninoCompilerStrategy which is the default. + * + * @author elaatifi@gmail.com + * + */ +@RunWith(DynamicSuite.class) +@TestCasePattern(".*TestCase") +@Scenario(name = "janino") +public class JaninoCompilerStrategyTestSuite { + + @BeforeClass + public static void janino() { + System.setProperty(OrikaSystemProperties.COMPILER_STRATEGY, JaninoCompilerStrategyTestSuite.class.getCanonicalName()); + } + + @AfterClass + public static void tearDown() { + System.clearProperty(OrikaSystemProperties.COMPILER_STRATEGY); + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/generics/GenericCollectionsTestCase.java b/core/src/test/java/ma/glasnost/orika/test/generics/GenericCollectionsTestCase.java new file mode 100644 index 00000000..77c58a95 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/generics/GenericCollectionsTestCase.java @@ -0,0 +1,145 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.generics; + +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.converter.builtin.PassThroughConverter; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.metadata.ClassMap; +import ma.glasnost.orika.metadata.ClassMapBuilder; +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.metadata.TypeBuilder; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; + +public class GenericCollectionsTestCase { + + /* Abstract class for person */ + public abstract static class Person { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public boolean equals(Object that) { + return Objects.equals(name, ((Person) that).name); + } + + public int hashCode() { + return Objects.hash(name); + } + } + + /* Concrete class for employee */ + public static class Employee extends Person { + } + + /* Task class for some Layer 1 */ + public static class TaskLayer1

{ + private List

workers = new ArrayList<>(); + + public List

getWorkers() { + return workers; + } + + public void setWorkers(List

workers) { + this.workers = workers; + } + } + + /* Task class for some Layer 2 (mapped from TaskLayer1) */ + public static class TaskLayer2

{ + private List

workers = new ArrayList<>(); + + public List

getWorkers() { + return workers; + } + + public void setWorkers(List

workers) { + this.workers = workers; + } + } + + /** + * This test uses the older Class-based mapping method, which is unable + * to determine the proper type hierarchy from the raw types + */ + @Test + public void testParameterizedCollection_rawTypes() { + + MapperFactory factory = new DefaultMapperFactory.Builder().build(); + + ClassMapBuilder builder = factory.classMap(TaskLayer1.class, TaskLayer2.class).byDefault(); + ClassMap classMap = builder.toClassMap(); + factory.registerClassMap(classMap); + + /* + * Let Orika know that it's okay to copy Employee or Person by reference... + */ + factory.getConverterFactory().registerConverter(new PassThroughConverter(Employee.class, Person.class)); + + + Employee e = new Employee(); + e.setName("Name"); + TaskLayer1 t1 = new TaskLayer1<>(); + t1.setWorkers(Arrays.asList(e)); + + + TaskLayer2 t2 = factory.getMapperFacade().map(t1, TaskLayer2.class); + Assert.assertNotNull(t2); + Assert.assertTrue(t1.getWorkers().containsAll(t2.getWorkers())); + Assert.assertTrue(t2.getWorkers().containsAll(t1.getWorkers())); + } + + /** + * This test attempts the same mapping using the newer type-based methods + * which allow passing in the exact runtime types. + */ + @Test + public void testParameterizedCollection_genericTypes() { + + MapperFactory factory = new DefaultMapperFactory.Builder().build(); + + Employee e = new Employee(); + e.setName("Name"); + TaskLayer1 t1 = new TaskLayer1<>(); + t1.setWorkers(Arrays.asList(e)); + + Type> sourceType = new TypeBuilder>(){}.build(); + Type> targetType = new TypeBuilder>(){}.build(); + + factory.registerClassMap( + factory.classMap(sourceType, targetType).byDefault()); + + TaskLayer2 t2 = factory.getMapperFacade().map(t1, sourceType, targetType); + Assert.assertNotNull(t2); + Assert.assertTrue(t1.getWorkers().containsAll(t2.getWorkers())); + Assert.assertTrue(t2.getWorkers().containsAll(t1.getWorkers())); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/generics/GenericsTestCase.java b/core/src/test/java/ma/glasnost/orika/test/generics/GenericsTestCase.java new file mode 100644 index 00000000..dc477d6f --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/generics/GenericsTestCase.java @@ -0,0 +1,515 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.generics; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.UtilityResolver; +import ma.glasnost.orika.metadata.Property; +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.metadata.TypeBuilder; +import ma.glasnost.orika.metadata.TypeFactory; +import ma.glasnost.orika.property.PropertyResolverStrategy; +import ma.glasnost.orika.test.MappingUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.io.Serializable; +import java.lang.reflect.ParameterizedType; +import java.util.Map; + +public class GenericsTestCase { + + @Test + public void testTypeErasure() { + MapperFacade mapperFacade = MappingUtil.getMapperFactory().getMapperFacade(); + EntityLong entity = new EntityLong(); + entity.setId(42L); + + new EntityGeneric().setId("Hello"); + new EntityGeneric().setId(42); + EntityLong clone = mapperFacade.map(entity, EntityLong.class); + + Assert.assertEquals(Long.valueOf(42L), clone.getId()); + } + + @Test + public void testTypeErasure2() { + MapperFacade mapperFacade = MappingUtil.getMapperFactory().getMapperFacade(); + EntityLong entity = new EntityLong(); + entity.setId(42L); + + new EntityGeneric().setId("Hello"); + EntityGeneric sourceObject = new EntityGeneric<>(); + sourceObject.setId(42L); + EntityLong clone = mapperFacade.map(sourceObject, EntityLong.class); + + Assert.assertEquals(Long.valueOf(42L), clone.getId()); + } + + @Test + public void testGenericsWithNestedParameterizedTypes() { + + MapperFactory factory = MappingUtil.getMapperFactory(); + + try { + /* + * Note that the normal lookup of nested property doesn't work, + * since EntityGeneric doesn't have actualized type arguments + */ + factory.classMap(EntityGeneric.class, EntityLong.class).field("id.key", "id").toClassMap(); + Assert.fail("should throw exception for unresolvable nested property"); + } catch (Exception e) { + Assert.assertTrue(e.getLocalizedMessage().contains("could not resolve nested property [id.key]")); + } + + // If we explicitly declare the generic type for the source object, + // we can successfully register the class map + Type>> sourceType = new TypeBuilder>>() {}.build(); + factory.registerClassMap(factory.classMap(sourceType, EntityLong.class).field("id.key", "id").toClassMap()); + + MapperFacade mapperFacade = factory.getMapperFacade(); + + EntityGeneric> sourceObject = new EntityGeneric<>(); + + NestedKey key = new NestedKey<>(); + key.setKey(42L); + sourceObject.setId(key); + Type _Entity_Long = TypeFactory.valueOf(EntityLong.class); + + EntityLong clone = mapperFacade.map(sourceObject, sourceType, _Entity_Long); + + Assert.assertEquals(Long.valueOf(42L), clone.getId()); + } + + @Test + public void testParameterizedPropertyUtil() { + + Type t = new TypeBuilder, Holder>>() {}.build(); + PropertyResolverStrategy propertyResolver = UtilityResolver.getDefaultPropertyResolverStrategy(); + Property p = propertyResolver.getProperty(t, "key.held"); + Assert.assertEquals(p.getType().getRawType(), Long.class); + Assert.assertEquals(p.getType(), TypeFactory.valueOf(Long.class)); + + Map properties = propertyResolver.getProperties(t); + Assert.assertTrue(properties.containsKey("key")); + Assert.assertEquals(properties.get("key").getType(), new TypeBuilder>() {}.build()); + } + + @Test + public void testMappingParameterizedTypes() { + + Type, Holder>> fromType = new TypeBuilder, Holder>>() {}.build(); + Type, Container>> toType = new TypeBuilder, Container>>() {}.build(); + + MapperFactory factory = MappingUtil.getMapperFactory(); + + TestEntry, Holder> fromObject = new TestEntry<>(); + fromObject.setKey(new Holder<>()); + fromObject.getKey().setHeld(42L); + fromObject.setValue(new Holder<>()); + fromObject.getValue().setHeld("What is the meaning of life?"); + + factory.registerClassMap( + factory.classMap( + new TypeBuilder>(){}.build(), + new TypeBuilder>(){}.build()) + .field("held", "contained").byDefault().toClassMap()); + + factory.registerClassMap( + factory.classMap( + new TypeBuilder>(){}.build(), + new TypeBuilder>(){}.build()) + .field("held", "contained").byDefault().toClassMap()); + + MapperFacade mapper = factory.getMapperFacade(); + + OtherTestEntry, Container> result = mapper.map(fromObject, fromType, toType); + + Assert.assertNotNull(result); + Assert.assertEquals("" + fromObject.getKey().getHeld(), result.getKey().getContained()); + Assert.assertEquals(fromObject.getValue().getHeld(), result.getValue().getContained()); + } + + @Test + public void testMappingParameterizedTypes2() { + + Type>, Envelope>>> fromType = + new TypeBuilder>, Envelope>>>() {}.build(); + Type, Container>> toType = + new TypeBuilder, Container>>() {}.build(); + + MapperFactory factory = MappingUtil.getMapperFactory(); + + // Construct our elaborate 'fromObject' + Entry>, Envelope>> fromObject = + new Entry<>(); + Container> container = new Container<>(); + Holder holder = new Holder<>(); + holder.setHeld(42L); + container.setContained(holder); + fromObject.setKey(container); + + Envelope> envelope = new Envelope<>(); + Container container2 = new Container<>(); + container2.setContained("What is the meaning of life?"); + envelope.setContents(container2); + fromObject.setValue(envelope); + + factory.registerClassMap( + factory.classMap(fromType, toType) + .field("key.contained.held", "key.held") + .field("value.contents.contained", "value.contained") + /*.byDefault()*/.toClassMap()); + + MapperFacade mapper = factory.getMapperFacade(); + + Entry, Container> result = mapper.map(fromObject, fromType, toType); + + Assert.assertNotNull(result); + Assert.assertEquals("" + fromObject.getKey().getContained().getHeld(), "" +result.getKey().getHeld()); + Assert.assertEquals("" + fromObject.getValue().getContents().getContained(), ""+result.getValue().getContained()); + } + + /** + * This test confirms that multiple mappings using different + * parameterizations of the same raw class type do not overwrite each other + * or cause conflicts + */ + @Test + public void testMultipleMappingsForParameterizedTypes() { + + Type, Holder>> fromType = new TypeBuilder, Holder>>() {}.build(); + Type, Container>> toType_1 = new TypeBuilder, Container>>() {}.build(); + Type, Container>> toType_2 = new TypeBuilder, Container>>() {}.build(); + + Type> _Container_Long = toType_2.getNestedType(0); + Type> _Holder_String = fromType.getNestedType(1); + Type> _Container_String = toType_1.getNestedType(0); + Type> _Holder_Long = fromType.getNestedType(0); + + MapperFactory factory = MappingUtil.getMapperFactory(); + + TestEntry, Holder> fromObject = new TestEntry<>(); + fromObject.setKey(new Holder<>()); + fromObject.getKey().setHeld(42L); + fromObject.setValue(new Holder<>()); + fromObject.getValue().setHeld("What is the meaning of life?"); + + /* + * We map the field types explicitly for the separate type mappings + */ + factory.registerClassMap(factory.classMap(_Holder_String, _Container_String) + .field("held", "contained") + .byDefault() + .toClassMap()); + factory.registerClassMap(factory.classMap(_Holder_Long, _Container_String) + .field("held", "contained") + .byDefault() + .toClassMap()); + factory.registerClassMap(factory.classMap(_Holder_Long, _Container_Long) + .field("held", "secondaryContained") + .byDefault() + .toClassMap()); + + MapperFacade mapper = factory.getMapperFacade(); + + /* + * Map the same source type to 2 different parameterized variations of + * the destination class; the mappings should not step on each other, + * since different types are used + */ + OtherTestEntry, Container> result1 = mapper.map(fromObject, fromType, toType_1); + OtherTestEntry, Container> result2 = mapper.map(fromObject, fromType, toType_2); + + Assert.assertNotNull(result1); + Assert.assertEquals("" + fromObject.getKey().getHeld(), result1.getKey().getContained()); + Assert.assertEquals(fromObject.getValue().getHeld(), result1.getValue().getContained()); + Assert.assertNull(result1.getKey().getSecondaryContained()); + + Assert.assertNotNull(result1); + Assert.assertNull(result2.getKey().getContained()); + Assert.assertEquals(fromObject.getKey().getHeld(), result2.getKey().getSecondaryContained()); + Assert.assertEquals(fromObject.getValue().getHeld(), result2.getValue().getContained()); + } + + /** + */ + @Test + public void testParameterizedTypeTokens() { + + Type, Holder>> typeA = new TypeBuilder, Holder>>() {}.build(); + Type, Container>> typeB = new TypeBuilder, Container>>() {}.build(); + + Type> _Container_Long = typeB.getNestedType(0); + Type> _Holder_String = typeA.getNestedType(1); + Type> _Container_String = typeB.getNestedType(1); + Type> _Holder_Long = typeA.getNestedType(0); + Type _Long = typeA.getNestedType(0).getNestedType(0); + Type _String = typeA.getNestedType(1).getNestedType(0); + + // Test type equivalence of nested types + Assert.assertEquals(new TypeBuilder>() {}.build(), _Container_Long); + Assert.assertEquals(new TypeBuilder>() {}.build(), _Container_String); + Assert.assertEquals(new TypeBuilder>() {}.build(), _Holder_Long); + Assert.assertEquals(new TypeBuilder>() {}.build(), _Holder_String); + Assert.assertEquals(new TypeBuilder() {}.build(), _Long); + Assert.assertEquals(new TypeBuilder() {}.build(), _String); + + abstract class RawParameterizedType { + } + + // Test types constructed through alternate means + RawParameterizedType rawType = new RawParameterizedType, Holder>>() {}; + Type valueOfRawType = TypeFactory.valueOf(rawType.getClass()); + Assert.assertEquals(typeA, valueOfRawType.getNestedType(0)); + + Type alternateTypeA1 = TypeFactory.valueOf(TestEntry.class, TypeFactory.valueOf(Holder.class, Long.class), + TypeFactory.valueOf(Holder.class, String.class)); + Assert.assertEquals(typeA, alternateTypeA1); + + Type alternateTypeA2 = TypeFactory.valueOf(TestEntry.class, _Holder_Long, _Holder_String); + Assert.assertEquals(typeA, alternateTypeA2); + + Type> wildType = new TypeBuilder>(){}.build(); + Assert.assertNotNull(wildType); + // Note that wildcard types are resolved to the nearest actual type + Assert.assertEquals(new TypeBuilder>(){}.build(), wildType); + } + + @Test + public void testRecursivelyDefinedTypes() { + + Type recursive = new TypeBuilder(){}.build(); + Assert.assertNotNull(recursive); + Type recursiveSuper = recursive.getSuperType(); + Assert.assertNotNull(recursiveSuper); + + recursive = TypeFactory.valueOf(RecursiveType.class); + Assert.assertNotNull(recursive); + Assert.assertEquals(recursive.getNestedType(0).getRawType(), RecursiveType.class); + } + + + public static class Envelope { + private String id; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public T getContents() { + return contents; + } + + public void setContents(T contents) { + this.contents = contents; + } + + private T contents; + } + + public static class Entry { + private K key; + private V value; + + public K getKey() { + return key; + } + + public void setKey(K key) { + this.key = key; + } + + public V getValue() { + return value; + } + + public void setValue(V value) { + this.value = value; + } + } + + public static class TestEntry { + + private K key; + private V value; + + public K getKey() { + return key; + } + + public void setKey(K key) { + this.key = key; + } + + public V getValue() { + return value; + } + + public void setValue(V value) { + this.value = value; + } + } + + public static class OtherTestEntry { + + private A key; + private B value; + + public A getKey() { + return key; + } + + public void setKey(A key) { + this.key = key; + } + + public B getValue() { + return value; + } + + public void setValue(B value) { + this.value = value; + } + } + + public static class Holder { + private H held; + + public H getHeld() { + return held; + } + + public void setHeld(H held) { + this.held = held; + } + + } + + public static class Container { + private C contained; + private C secondaryContained; + + public C getSecondaryContained() { + return secondaryContained; + } + + public void setSecondaryContained(C secondaryContained) { + this.secondaryContained = secondaryContained; + } + + public C getContained() { + return contained; + } + + public void setContained(C contained) { + this.contained = contained; + } + } + + public interface Entity { + T getId(); + + void + + setId(T id); + } + + public static class EntityLong implements Entity { + private Long id; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + } + + public static class EntityString implements Entity { + private String id; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + } + + public static class NestedKey implements Serializable { + + private static final long serialVersionUID = 1L; + + private K key; + + public K getKey() { + return key; + } + + public void setKey(K key) { + this.key = key; + } + } + + public static class EntityGeneric implements Entity { + private T id; + + public T getId() { + return id; + } + + public void setId(T id) { + this.id = id; + } + + } + + public static abstract class RecursiveType> implements Comparable{ + + private final Type recursiveType; + + public RecursiveType() { + ParameterizedType superType = (ParameterizedType)getClass().getGenericSuperclass(); + recursiveType = TypeFactory.valueOf(superType.getActualTypeArguments()[0]); + } + + public final int compareTo(R o) { + RecursiveType other = (RecursiveType)o; + RecursiveType self = this; + return self.recursiveType.getName().compareTo(other.recursiveType.getName()); + } + + } + + public static class RecursiveImpl extends RecursiveType { + + } + + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/generics/IntrospectorBugTestCase.java b/core/src/test/java/ma/glasnost/orika/test/generics/IntrospectorBugTestCase.java new file mode 100644 index 00000000..15b27b2a --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/generics/IntrospectorBugTestCase.java @@ -0,0 +1,70 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.generics; + +import java.beans.IntrospectionException; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.test.MappingUtil; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Test for to work around http://bugs.sun.com/view_bug.do?bug_id=6788525 + */ +public class IntrospectorBugTestCase { + + @Test + public void testIntrospectorBugWorkaround() throws IntrospectionException { + MapperFacade mapperFacade = MappingUtil.getMapperFactory().getMapperFacade(); + Source source = new Source(); + source.setFoo("Hello World"); + Destination destination = mapperFacade.map(source, Destination.class); + Assert.assertEquals("Hello World", destination.getFoo()); + } + + public static class Base { + private T foo; + + public T getFoo() { + return this.foo; + } + + public void setFoo(T t) { + this.foo = t; + } + } + + public static class Source extends Base { + } + + public static class Destination { + private String foo; + + public String getFoo() { + return foo; + } + + public void setFoo(String foo) { + this.foo = foo; + } + } + +} \ No newline at end of file diff --git a/core/src/test/java/ma/glasnost/orika/test/generics/Issue289TestCase.java b/core/src/test/java/ma/glasnost/orika/test/generics/Issue289TestCase.java new file mode 100644 index 00000000..72991610 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/generics/Issue289TestCase.java @@ -0,0 +1,125 @@ +package ma.glasnost.orika.test.generics; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.test.MappingUtil; +import org.junit.Assert; +import org.junit.Test; + +public class Issue289TestCase { + + @Test + public void testRecursivelyDefinedClassesWithInheritance() { + final MapperFactory mapperFactory = MappingUtil.getMapperFactory(); + mapperFactory.registerClassMap(mapperFactory.classMap(Parent.class, ParentDto.class).byDefault().toClassMap()); + mapperFactory.registerClassMap(mapperFactory.classMap(Child.class, ChildDto.class).byDefault().toClassMap()); + mapperFactory.registerClassMap(mapperFactory.classMap(ChildImpl.class, ChildImplDto.class).byDefault().toClassMap()); + final MapperFacade mapperFacade = mapperFactory.getMapperFacade(); + + { + final Parent source = new Parent(); + source.setParentName("parentName"); + + final ParentDto target = mapperFacade.map(source, ParentDto.class); + + Assert.assertEquals(source.getParentName(), target.getParentName()); + } + + { + final Child source = new Child(); + source.setParentName("parentName"); + source.setChildName("childName"); + + final ChildDto target = mapperFacade.map(source, ChildDto.class); + + Assert.assertEquals(source.getParentName(), target.getParentName()); + Assert.assertEquals(source.getChildName(), target.getChildName()); + } + + { + final ChildImpl source = new ChildImpl(); + source.setParentName("parentName"); + source.setChildName("childName"); + source.setChildImpl("source"); + + final ChildImplDto target = mapperFacade.map(source, ChildImplDto.class); + + Assert.assertEquals(source.getParentName(), target.getParentName()); + Assert.assertEquals(source.getChildName(), target.getChildName()); + Assert.assertEquals(source.getChildImpl(), target.getChildImpl()); + } + } + + + public static class Parent> { + private String parentName; + + public String getParentName() { + return parentName; + } + + public void setParentName(String parentName) { + this.parentName = parentName; + } + } + + public static class Child> extends Parent { + private String childName; + + public String getChildName() { + return childName; + } + + public void setChildName(String childName) { + this.childName = childName; + } + } + + public static class ChildImpl extends Child { + private String childImpl; + + public String getChildImpl() { + return childImpl; + } + + public void setChildImpl(String childImpl) { + this.childImpl = childImpl; + } + } + + public static class ParentDto { + private String parentName; + + public String getParentName() { + return parentName; + } + + public void setParentName(String parentName) { + this.parentName = parentName; + } + } + + public static class ChildDto extends ParentDto { + private String childName; + + public String getChildName() { + return childName; + } + + public void setChildName(String childName) { + this.childName = childName; + } + } + + public static class ChildImplDto extends ChildDto { + private String childImpl; + + public String getChildImpl() { + return childImpl; + } + + public void setChildImpl(String childImpl) { + this.childImpl = childImpl; + } + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/generics/SpecifiedGenericsTestCase.java b/core/src/test/java/ma/glasnost/orika/test/generics/SpecifiedGenericsTestCase.java new file mode 100644 index 00000000..39febca9 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/generics/SpecifiedGenericsTestCase.java @@ -0,0 +1,63 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.generics; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.test.MappingUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.beans.IntrospectionException; + +/** + * Test to show odd behavior with specified generic types + */ +public class SpecifiedGenericsTestCase { + @Test + public void testSpecifiedGeneric() throws IntrospectionException { + MapperFacade mapperFacade = MappingUtil.getMapperFactory() + .getMapperFacade(); + Source source = new Source(); + source.setFoo("Hello"); + Destination destination = mapperFacade.map(source, Destination.class); + Assert.assertEquals(source.getFoo(), destination.getFoo()); + } + + public static class Base { + protected T foo; + + public T getFoo() { + return this.foo; + } + + } + + public static class Source extends Base { + public void setFoo(String t) { + this.foo = t; + } + } + + public static class Destination extends Base { + public void setFoo(String t) { + this.foo = t; + } + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/hint/DefaultMappingHintTestCase.java b/core/src/test/java/ma/glasnost/orika/test/hint/DefaultMappingHintTestCase.java new file mode 100644 index 00000000..f395eef5 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/hint/DefaultMappingHintTestCase.java @@ -0,0 +1,164 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.hint; + +import ma.glasnost.orika.DefaultFieldMapper; +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.test.MappingUtil; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.Author; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.AuthorMyDTO; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.AuthorParent; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.Book; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.BookMyDTO; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.BookParent; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.Library; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.LibraryMyDTO; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.LibraryParent; +import org.junit.Assert; +import org.junit.Test; + +public class DefaultMappingHintTestCase { + + private Author createAuthor(Class type) throws InstantiationException, IllegalAccessException { + AuthorParent author = type.newInstance(); + author.setName("Khalil Gebran"); + + return author; + } + + private Book createBook(Class type) throws InstantiationException, IllegalAccessException { + BookParent book = type.newInstance(); + book.setTitle("The Prophet"); + + return book; + } + + private Library createLibrary(Class type) throws InstantiationException, IllegalAccessException { + LibraryParent lib = type.newInstance(); + lib.setTitle("Test Library"); + + return lib; + } + + @Test + public void testMappingByDefaultWithNoHint() throws Exception { + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.registerClassMap(factory.classMap(Library.class, LibraryMyDTO.class).byDefault().toClassMap()); + + factory.registerClassMap(factory.classMap(Author.class, AuthorMyDTO.class).byDefault().toClassMap()); + + factory.registerClassMap(factory.classMap(Book.class, BookMyDTO.class).byDefault().toClassMap()); + + MapperFacade mapper = factory.getMapperFacade(); + + Book book = createBook(BookParent.class); + book.setAuthor(createAuthor(AuthorParent.class)); + Library lib = createLibrary(LibraryParent.class); + lib.getBooks().add(book); + + LibraryMyDTO mappedLib = mapper.map(lib, LibraryMyDTO.class); + + Assert.assertNotNull(mappedLib); + Assert.assertTrue(mappedLib.getMyBooks().isEmpty()); + } + + /** + * @throws Exception + */ + @Test + public void testMappingByDefaultWithHint() throws Exception { + + DefaultFieldMapper myHint = + /** + * This sample hint converts "myProperty" to "property", and vis-versa. + */ + (fromProperty, fromPropertyType) -> { + if (fromProperty.startsWith("my")) { + return fromProperty.substring(2, 3).toLowerCase() + fromProperty.substring(3); + } else { + return "my" + fromProperty.substring(0, 1).toUpperCase() + fromProperty.substring(1); + } + }; + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.registerClassMap(factory.classMap(Library.class, LibraryMyDTO.class).byDefault(myHint).toClassMap()); + + factory.registerClassMap(factory.classMap(Author.class, AuthorMyDTO.class).byDefault(myHint).toClassMap()); + + factory.registerClassMap(factory.classMap(Book.class, BookMyDTO.class).byDefault(myHint).toClassMap()); + + MapperFacade mapper = factory.getMapperFacade(); + + Book book = createBook(BookParent.class); + book.setAuthor(createAuthor(AuthorParent.class)); + Library lib = createLibrary(LibraryParent.class); + lib.getBooks().add(book); + + LibraryMyDTO mappedLib = mapper.map(lib, LibraryMyDTO.class); + + Assert.assertEquals(lib.getTitle(), mappedLib.getMyTitle()); + Assert.assertEquals(book.getTitle(), mappedLib.getMyBooks().get(0).getMyTitle()); + Assert.assertEquals(book.getAuthor().getName(), mappedLib.getMyBooks().get(0).getMyAuthor().getMyName()); + } + + /** + * @throws Exception + */ + @Test + public void testMappingWithRegisteredHintAndNoClassMap() throws Exception { + + DefaultFieldMapper myHint = + /** + * This sample hint converts "myProperty" to "property", and vis-versa. + */ + (fromProperty, fromPropertyType) -> { + if (fromProperty.startsWith("my")) { + return fromProperty.substring(2, 3).toLowerCase() + fromProperty.substring(3); + } else { + return "my" + fromProperty.substring(0, 1).toUpperCase() + fromProperty.substring(1); + } + }; + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.registerDefaultFieldMapper(myHint); + + MapperFacade mapper = factory.getMapperFacade(); + + Book book = createBook(BookParent.class); + book.setAuthor(createAuthor(AuthorParent.class)); + Library lib = createLibrary(LibraryParent.class); + lib.getBooks().add(book); + + LibraryMyDTO mappedLib = mapper.map(lib, LibraryMyDTO.class); + + Assert.assertEquals(lib.getTitle(), mappedLib.getMyTitle()); + Assert.assertEquals(book.getTitle(), mappedLib.getMyBooks().get(0).getMyTitle()); + Assert.assertEquals(book.getAuthor().getName(), mappedLib.getMyBooks().get(0).getMyAuthor().getMyName()); + + // Now, map it back to the original... + + Library lib2 = mapper.map(mappedLib, Library.class); + Assert.assertEquals(lib.getTitle(), lib2.getTitle()); + Assert.assertEquals(book.getTitle(), lib2.getBooks().get(0).getTitle()); + Assert.assertEquals(book.getAuthor().getName(), lib2.getBooks().get(0).getAuthor().getName()); + + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/hint/DefaultMappingHintTestCaseClasses.java b/core/src/test/java/ma/glasnost/orika/test/hint/DefaultMappingHintTestCaseClasses.java new file mode 100644 index 00000000..ee485855 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/hint/DefaultMappingHintTestCaseClasses.java @@ -0,0 +1,233 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.hint; + +import java.util.ArrayList; +import java.util.List; + +public interface DefaultMappingHintTestCaseClasses { + + interface Book { + + String getTitle(); + + void setTitle(String title); + + Author getAuthor(); + + void setAuthor(Author author); + + } + + interface Author { + + String getName(); + + void setName(String name); + + } + + interface Library { + + String getTitle(); + + List getBooks(); + } + + class BookParent implements Book { + + private String title; + private Author author; + + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public Author getAuthor() { + return author; + } + + public void setAuthor(Author author) { + this.author = author; + } + + } + + class AuthorParent implements Author { + + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + } + + class LibraryParent implements Library { + + private String title; + + private List books; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public List getBooks() { + if (books==null) { + books = new ArrayList<>(); + } + return books; + } + + } + + class BookChild extends BookParent { + private String additionalValue; + + public String getAdditionalValue() { + return additionalValue; + } + + public void setAdditionalValue(String additionalValue) { + this.additionalValue = additionalValue; + } + } + + class AuthorChild extends AuthorParent { + private String additionalValue; + + public String getAdditionalValue() { + return additionalValue; + } + + public void setAdditionalValue(String additionalValue) { + this.additionalValue = additionalValue; + } + } + + class LibraryChild extends LibraryParent { + private String additionalValue; + + public String getAdditionalValue() { + return additionalValue; + } + + public void setAdditionalValue(String additionalValue) { + this.additionalValue = additionalValue; + } + } + + + class AuthorDTO { + + private String name; + private String additionalValue; + + public String getMyAdditionalValue() { + return additionalValue; + } + + public void setMyAdditionalValue(String additionalValue) { + this.additionalValue = additionalValue; + } + + public String getMyName() { + return name; + } + + public void setMyName(String name) { + this.name = name; + } + } + + class BookDTO { + + private String title; + private AuthorDTO author; + private String additionalValue; + + public String getMyAdditionalValue() { + return additionalValue; + } + + public void setMyAdditionalValue(String additionalValue) { + this.additionalValue = additionalValue; + } + + public String getMyTitle() { + return title; + } + + public void setMyTitle(String title) { + this.title = title; + } + + public AuthorDTO getMyAuthor() { + return author; + } + + public void setMyAuthor(AuthorDTO author) { + this.author = author; + } + } + + class LibraryDTO { + + private String title; + private List books; + private String additionalValue; + + public String getMyAdditionalValue() { + return additionalValue; + } + + public void setMyAdditionalValue(String additionalValue) { + this.additionalValue = additionalValue; + } + + public String getMyTitle() { + return title; + } + + public void setMyTitle(String title) { + this.title = title; + } + + public List getMyBooks() { + if (books==null) { + books = new ArrayList<>(); + } + return books; + } + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/inheritance/InheritanceTestCase.java b/core/src/test/java/ma/glasnost/orika/test/inheritance/InheritanceTestCase.java new file mode 100644 index 00000000..83ab77cf --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/inheritance/InheritanceTestCase.java @@ -0,0 +1,152 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.inheritance; + +import org.junit.Assert; +import org.junit.Test; + +import ma.glasnost.orika.CustomMapper; +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.test.MappingUtil; + +public class InheritanceTestCase { + + private final MapperFactory factory = MappingUtil.getMapperFactory(); + + public void setUp() { + + } + + @Test + public void testSimpleInheritance() { + MapperFacade mapper = factory.getMapperFacade(); + + ChildEntity entity = new ChildEntity(); + entity.setId(1L); + entity.setName("Khettabi"); + + ChildDTO dto = mapper.map(entity, ChildDTO.class); + + Assert.assertEquals(entity.getId(), dto.getId()); + Assert.assertEquals(entity.getName(), dto.getName()); + } + + @Test + public void resolveConcreteClass() { + MapperFacade mapper = factory.getMapperFacade(); + factory.registerClassMap(factory.classMap(ChildEntity.class, ChildDTO.class).byDefault().toClassMap()); + + ChildEntity entity = new ChildEntity(); + entity.setId(1L); + entity.setName("Khettabi"); + + BaseDTO dto = mapper.map(entity, BaseDTO.class); + + Assert.assertTrue(dto instanceof ChildDTO); + Assert.assertEquals(entity.getName(), ((ChildDTO) dto).getName()); + } + + @Test + public void testDifferentLevelOfInheritance() { + factory.registerClassMap(factory.classMap(ChildEntity.class, Child2DTO.class) + .customize(new CustomMapper() { + + @Override + public void mapAtoB(ChildEntity a, Child2DTO b, MappingContext context) { + b.setMessage("Hello " + a.getName()); + } + + }).byDefault().toClassMap()); + + MapperFacade mapper = factory.getMapperFacade(); + + ChildEntity entity = new ChildEntity(); + entity.setId(1L); + entity.setName("Khettabi"); + + Child2DTO dto = mapper.map(entity, Child2DTO.class); + + Assert.assertEquals(entity.getId(), dto.getId()); + Assert.assertEquals(entity.getName(), dto.getName()); + Assert.assertEquals("Hello Khettabi", dto.getMessage()); + } + + public static abstract class BaseEntity { + private Long id; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + } + + public static abstract class BaseDTO { + private Long id; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + } + + public static class ChildEntity extends BaseEntity { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + public static class ChildDTO extends BaseDTO { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + public static class Child2DTO extends ChildDTO { + private String message; + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/inheritance/InitializeUsedMappersTestCase.java b/core/src/test/java/ma/glasnost/orika/test/inheritance/InitializeUsedMappersTestCase.java new file mode 100644 index 00000000..c5fcd2a5 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/inheritance/InitializeUsedMappersTestCase.java @@ -0,0 +1,143 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.inheritance; + +import org.junit.Assert; +import org.junit.Test; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.test.MappingUtil; + +/** + * @author matt.deboer@gmail.com + * + */ +public class InitializeUsedMappersTestCase { + + public static class A1 { + public String name1; + } + + public static class A2 extends A1 { + public String name2; + } + + public static class A3 extends A2 { + public String name3; + } + + public static class B1 { + public String name1; + } + + public static class B2 extends B1 { + public String name2; + } + + public static class B3 extends B2 { + public String name3; + } + + + @Test + public void testParentLookup() { + + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.registerClassMap( + factory.classMap(B2.class, A2.class) + .use(B1.class,A1.class) + .byDefault()); + factory.registerClassMap( + factory.classMap(A1.class, B1.class) + .byDefault()); + + MapperFacade mapper = factory.getMapperFacade(); + + A3 a = new A3(); + a.name1 = "a1"; + a.name2 = "a2"; + a.name3 = "a3"; + + + B3 b = mapper.map(a, B3.class); + + Assert.assertNotNull(b); + Assert.assertEquals(a.name1, b.name1); + Assert.assertEquals(a.name2, b.name2); + } + + public static class ABase { + private String property; + + public String getProperty() { + return property; + } + + public void setProperty(String property) { + this.property = property; + } + } + + public static class ASub extends ABase { + } + + public static class BBase { + private String property; + private int timesSet = 0; + + public String getProperty() { + return property; + } + + public void setProperty(String property) { + this.property = property; + timesSet++; + } + + public int getTimesSet() { + return timesSet; + } + } + + public static class BSub extends BBase { + } + + @Test + public void testParentPropertiesSetOnce() { + + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.registerClassMap(factory.classMap(ABase.class, BBase.class) + .byDefault()); + factory.registerClassMap(factory.classMap(ASub.class, BSub.class) + .byDefault()); + + MapperFacade mapper = factory.getMapperFacade(); + + ASub a = new ASub(); + a.setProperty("property"); + + BSub b = mapper.map(a, BSub.class); + + Assert.assertNotNull(b); + Assert.assertEquals(a.getProperty(), b.getProperty()); + Assert.assertEquals(1, b.getTimesSet()); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/inheritance/NestedInheritanceTestCase.java b/core/src/test/java/ma/glasnost/orika/test/inheritance/NestedInheritanceTestCase.java new file mode 100644 index 00000000..68299241 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/inheritance/NestedInheritanceTestCase.java @@ -0,0 +1,156 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.inheritance; + +import java.util.Arrays; +import java.util.List; + +import org.junit.Assert; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.test.MappingUtil; + +import org.junit.Test; + +public class NestedInheritanceTestCase { + + @Test + public void testNestedInheritance() { + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.registerClassMap(factory.classMap(Person.class, PersonDTO.class).byDefault().toClassMap()); + factory.registerClassMap(factory.classMap(Client.class, ClientDTO.class).byDefault().toClassMap()); + factory.registerClassMap(factory.classMap(Subscription.class, SubscriptionDTO.class).field("client", "person").toClassMap()); + + Client client = new Client(); + client.setName("Khalil Gebran"); + + Subscription subscription = new Subscription(); + subscription.setClient(client); + + SubscriptionDTO dto = factory.getMapperFacade().map(subscription, SubscriptionDTO.class); + + Assert.assertNotNull(dto); + Assert.assertNotNull(dto.getPerson()); + Assert.assertEquals(client.getName(), dto.getPerson().getName()); + } + + @Test + public void testNestedPolymorphicInheritance() { + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.registerClassMap(factory.classMap(Person.class, PersonDTO.class).byDefault().toClassMap()); + factory.registerClassMap(factory.classMap(Client.class, ClientDTO.class).byDefault().toClassMap()); + factory.registerClassMap(factory.classMap(Employee.class, EmployeeDTO.class).byDefault().toClassMap()); + factory.registerClassMap(factory.classMap(Subscription.class, SubscriptionDTO.class).field("client", "person").toClassMap()); + + Client client = new Client(); + client.setName("Khalil Gebran"); + + Employee employee = new Employee(); + employee.setName("Kuipje Anders"); + + Subscription clientSubscription = new Subscription(); + clientSubscription.setClient(client); + + Subscription employeeSubscription = new Subscription(); + employeeSubscription.setClient(employee); + + List subscriptions = Arrays.asList(clientSubscription, employeeSubscription); + + List dto = factory.getMapperFacade().mapAsList(subscriptions, SubscriptionDTO.class); + + Assert.assertNotNull(dto); + Assert.assertEquals(2, dto.size()); + Assert.assertNotNull(dto.get(0).getPerson()); + Assert.assertEquals(client.getName(), dto.get(0).getPerson().getName()); + Assert.assertEquals(employee.getName(), dto.get(1).getPerson().getName()); + Assert.assertEquals(ClientDTO.class, dto.get(0).getPerson().getClass()); + Assert.assertEquals(EmployeeDTO.class, dto.get(1).getPerson().getClass()); + } + + public abstract static class Person { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + } + + public static class Client extends Person { + + } + + public static class Employee extends Person { + + } + + public static class Subscription { + + private Person client; + + public Person getClient() { + return client; + } + + public void setClient(Person client) { + this.client = client; + } + + } + + public static abstract class PersonDTO { + + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + } + + public static class ClientDTO extends PersonDTO { + + } + + public static class EmployeeDTO extends PersonDTO { + + } + + public static class SubscriptionDTO { + private PersonDTO person; + + public PersonDTO getPerson() { + return person; + } + + public void setPerson(PersonDTO person) { + this.person = person; + } + + } +} \ No newline at end of file diff --git a/core/src/test/java/ma/glasnost/orika/test/inheritance/ReuseMappersTestCase.java b/core/src/test/java/ma/glasnost/orika/test/inheritance/ReuseMappersTestCase.java new file mode 100644 index 00000000..2eb9fde3 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/inheritance/ReuseMappersTestCase.java @@ -0,0 +1,165 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.inheritance; + +import org.junit.Assert; +import org.junit.Test; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.test.MappingUtil; + +public class ReuseMappersTestCase { + + @Test + public void testReuse() { + + MapperFactory factory = MappingUtil.getMapperFactory(); + + { + factory.classMap(Location.class, LocationDTO.class) + .field("x", "coordinateX") + .field("y", "coordinateY") + .register(); + } + + { + factory.classMap(NamedLocation.class, NamedLocationDTO.class) + .use(Location.class, LocationDTO.class) + .field("name", "label") + .register(); + } + + { + factory.classMap(City.class, CityDTO.class) + .use(NamedLocation.class, NamedLocationDTO.class) + .byDefault() + .register(); + } + + MapperFacade mapper = factory.getMapperFacade(); + + City city = new City(); + city.setX(5); + city.setY(7); + city.setZipCode("78951123"); + + CityDTO dto = mapper.map(city, CityDTO.class); + + Assert.assertEquals(city.getX(), dto.getCoordinateX()); + Assert.assertEquals(city.getY(), dto.getCoordinateY()); + Assert.assertEquals(city.getName(), dto.getLabel()); + Assert.assertEquals(city.getZipCode(), dto.getZipCode()); + + } + + public static abstract class Location { + private int x, y; + + public int getX() { + return x; + } + + public void setX(int x) { + this.x = x; + } + + public int getY() { + return y; + } + + public void setY(int y) { + this.y = y; + } + + } + + public static class NamedLocation extends Location { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + } + + public static class City extends NamedLocation { + private String zipCode; + + public String getZipCode() { + return zipCode; + } + + public void setZipCode(String zipCode) { + this.zipCode = zipCode; + } + + } + + public static abstract class LocationDTO { + private int coordinateX, coordinateY; + + public int getCoordinateX() { + return coordinateX; + } + + public void setCoordinateX(int x) { + this.coordinateX = x; + } + + public int getCoordinateY() { + return coordinateY; + } + + public void setCoordinateY(int y) { + this.coordinateY = y; + } + + } + + public static class NamedLocationDTO extends LocationDTO { + private String label; + + public String getLabel() { + return label; + } + + public void setLabel(String name) { + this.label = name; + } + + } + + public static class CityDTO extends NamedLocationDTO { + private String zipCode; + + public String getZipCode() { + return zipCode; + } + + public void setZipCode(String zipCode) { + this.zipCode = zipCode; + } + + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/inheritance/UsedMappersTestCase.java b/core/src/test/java/ma/glasnost/orika/test/inheritance/UsedMappersTestCase.java new file mode 100644 index 00000000..a91eef0a --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/inheritance/UsedMappersTestCase.java @@ -0,0 +1,248 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.inheritance; + +import org.junit.Assert; +import org.junit.Test; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.test.MappingUtil; + +public class UsedMappersTestCase { + + @Test + public void testReuseOfMapper() { + MapperFactory mapperFactory = MappingUtil.getMapperFactory(); + { + mapperFactory.classMap(A.class, C.class) + .field("name", "nom") + .register(); + } + + { + mapperFactory.classMap(B.class, D.class) + .use(A.class, C.class) + .field("age", "ages") + .register(); + } + + MapperFacade mapperFacade = mapperFactory.getMapperFacade(); + + B source = new B(); + source.setName("Israfil"); + source.setAge(1000); + + D target = mapperFacade.map(source, D.class); + + Assert.assertEquals(source.getName(), target.getNom()); + Assert.assertEquals(source.getAge(), target.getAges()); + + } + + @Test + public void testOneCallOfFieldMapping() { + MapperFactory mapperFactory = MappingUtil.getMapperFactory(); + { + mapperFactory.classMap(A.class, E.class) + .byDefault() + .register(); + } + { + mapperFactory.classMap(B.class, F.class) + .use(A.class, E.class) + .byDefault() + .register(); + } + + MapperFacade mapperFacade = mapperFactory.getMapperFacade(); + + B source = new B(); + source.setName("Israfil"); + source.setAge(1000); + + F target = mapperFacade.map(source, F.class); + + Assert.assertEquals(source.getName(), target.getName()); + Assert.assertEquals(source.getAge(), target.getAge()); + Assert.assertEquals(1, target.getNameCalls()); + } + + @Test + public void exclusionOnAbstractParent() throws Throwable { + + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.classMap(Throwable.class, RuntimeException.class) + .exclude("stackTrace") + .favorExtension(true) + .byDefault() + .register(); + // TODO 17. Sep. 2015 : why is this registration required: + factory.classMap(UserUpdateException.class, UserRegistrationModelException.class) + .byDefault() + .register(); + + UserUpdateException src = new UserUpdateException(true); + UserRegistrationModelException dest = factory.getMapperFacade().map(src, UserRegistrationModelException.class); + + Assert.assertEquals(src.isEmailDuplicate(), dest.isEmailDuplicate()); + } + + public static class UserUpdateException extends TestRuntimeException { + private static final long serialVersionUID = 1L; + + private final boolean emailDuplicate; + + public UserUpdateException(boolean emailDuplicate) { + this.emailDuplicate = emailDuplicate; + } + + public boolean isEmailDuplicate() { + return emailDuplicate; + } + + } + + public static class UserRegistrationModelException extends TestException { + private static final long serialVersionUID = 1L; + + private boolean emailDuplicate; + + public boolean isEmailDuplicate() { + return emailDuplicate; + } + + public void setEmailDuplicate(final boolean emailDuplicate) { + this.emailDuplicate = emailDuplicate; + } + + } + + public abstract static class TestRuntimeException extends RuntimeException { + private static final long serialVersionUID = 1L; + + @Override + public StackTraceElement[] getStackTrace() { + throw new UnsupportedOperationException("getStackTrace should never be called."); + } + + @Override + public void setStackTrace(StackTraceElement[] stackTrace) { + super.setStackTrace(stackTrace); + } + } + + public abstract static class TestException extends Exception { + private static final long serialVersionUID = 1L; + + @Override + public StackTraceElement[] getStackTrace() { + throw new UnsupportedOperationException("getStackTrace should never be called."); + } + + @Override + public void setStackTrace(StackTraceElement[] stackTrace) { + super.setStackTrace(stackTrace); + } + } + + public static abstract class A { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + } + + public static class B extends A { + private int age; + + public int getAge() { + return age; + } + + public void setAge(int ages) { + this.age = ages; + } + + } + + public static abstract class C { + private String nom; + + public String getNom() { + return nom; + } + + public void setNom(String nom) { + this.nom = nom; + } + + } + + public static class D extends C { + private int ages; + + public int getAges() { + return ages; + } + + public void setAges(int age) { + this.ages = age; + } + } + + public static abstract class E { + private String name; + private int nameCalls; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + nameCalls++; + } + + public int getNameCalls() { + return nameCalls; + } + + } + + public static class F extends E { + private int age; + + public int getAge() { + return age; + } + + public void setAge(int ages) { + this.age = ages; + } + + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/inheritance/UserProvidedInheritanceTestCase.java b/core/src/test/java/ma/glasnost/orika/test/inheritance/UserProvidedInheritanceTestCase.java new file mode 100644 index 00000000..a12ee09c --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/inheritance/UserProvidedInheritanceTestCase.java @@ -0,0 +1,106 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.inheritance; + +import org.junit.Assert; +import org.junit.Test; + +import ma.glasnost.orika.CustomMapper; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.metadata.ClassMapBuilder; + +public class UserProvidedInheritanceTestCase { + + @SuppressWarnings("deprecation") + @Test + public void testFail() { + MapperFactory factory = new DefaultMapperFactory.Builder().build(); + + factory.registerClassMap(ClassMapBuilder.map(Base.class, BaseDto.class).customize(new CustomMapper() { + @Override + public void mapAtoB(Base base, BaseDto baseDto, MappingContext context) { + baseDto.setBaseField(base.getBaseTrickField()); + } + }).toClassMap()); + factory.registerClassMap(ClassMapBuilder.map(Child.class, ChildDto.class).byDefault().toClassMap()); + + factory.build(); + + Child child = new Child(); + child.setChildField("CHILD FIELD"); + child.setBaseTrickField("BASE FIELD"); + + ChildDto dto = factory.getMapperFacade().map(child, ChildDto.class); + + Assert.assertNotNull(dto); + Assert.assertEquals(child.getChildField(), dto.getChildField()); + Assert.assertEquals(child.getBaseTrickField(), dto.getBaseField()); + + } + + public static class Base { + private String baseTrickField; + + public String getBaseTrickField() { + return baseTrickField; + } + + public void setBaseTrickField(String baseTrickField) { + this.baseTrickField = baseTrickField; + } + } + + public static class BaseDto { + private String baseField; + + public String getBaseField() { + return baseField; + } + + public void setBaseField(String baseField) { + this.baseField = baseField; + } + } + + public static class Child extends Base { + private String childField; + + public String getChildField() { + return childField; + } + + public void setChildField(String childField) { + this.childField = childField; + } + } + + public static class ChildDto extends BaseDto { + private String childField; + + public String getChildField() { + return childField; + } + + public void setChildField(String childField) { + this.childField = childField; + } + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/map/CoreMappingFunctionsTestCase.java b/core/src/test/java/ma/glasnost/orika/test/map/CoreMappingFunctionsTestCase.java new file mode 100644 index 00000000..8800f60a --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/map/CoreMappingFunctionsTestCase.java @@ -0,0 +1,296 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.map; + +import ma.glasnost.orika.CustomConverter; +import ma.glasnost.orika.MapEntry; +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.metadata.TypeBuilder; +import ma.glasnost.orika.metadata.TypeFactory; +import ma.glasnost.orika.test.MappingUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +public class CoreMappingFunctionsTestCase { + + /* + * Case 1: from a map to another map + * + * we iterate over the entry set, map the key and value, and put into new + * map + */ + @Test + public void testMapToMap_Simple() { + + Map sourceMap = new HashMap<>(); + sourceMap.put("A", 1); + sourceMap.put("B", 2); + sourceMap.put("C", 3); + + MapperFacade mapper = MappingUtil.getMapperFactory().getMapperFacade(); + + Map result = mapper.mapAsMap(sourceMap, new TypeBuilder>() { + }.build(), new TypeBuilder>() { + }.build()); + + Assert.assertNotNull(result); + Assert.assertNotSame(sourceMap, result); + + } + + @Test + public void testMapToMap_WithConversion() { + + Map sourceMap = new HashMap<>(); + sourceMap.put("A", 1); + sourceMap.put("B", 2); + sourceMap.put("C", 3); + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(new CustomConverter() { + + public boolean canConvert(Type sourceType, Type destinationType) { + return destinationType.getRawType().equals(String.class) + && (sourceType.getRawType().equals(Integer.class) || sourceType.getRawType().equals(int.class)); + } + + public String convert(Integer source, Type destinationType, MappingContext context) { + return "" + source; + } + + }); + MapperFacade mapper = factory.getMapperFacade(); + + Map result = mapper.mapAsMap(sourceMap, new TypeBuilder>() { + }.build(), new TypeBuilder>() { + }.build()); + + Assert.assertNotNull(result); + Assert.assertNotSame(sourceMap, result); + for (Entry entry : sourceMap.entrySet()) { + Assert.assertNotNull(result.get(entry.getKey())); + Assert.assertTrue(result.get(entry.getKey()).equals("" + entry.getValue().toString())); + } + + } + + public static class Ranking { + private String name; + private Integer rank; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getRank() { + return rank; + } + + public void setRank(Integer rank) { + this.rank = rank; + } + } + + /* + * Case 2a: from a collection to a map + * + * we iterate over the collection, and attempt to map each element to a + * Map.Entry; we'll need a special concrete destination type since Map.Entry + * is not concrete + */ + @Test + public void testCollectionToMap_Simple() { + + Collection source = new ArrayList<>(); + Ranking r = new Ranking(); + r.setName("A"); + r.setRank(1); + source.add(r); + r = new Ranking(); + r.setName("B"); + r.setRank(2); + source.add(r); + r = new Ranking(); + r.setName("C"); + r.setRank(3); + source.add(r); + + /* + * To make the map work for Collection to Map, we provide a class + * mapping from the element type in the collection to the special type + * MapEntry which represents map entries. + */ + Type> mapType = new TypeBuilder>() { + }.build(); + Type> entryType = MapEntry.concreteEntryType(mapType); + Type rankingType = TypeFactory.valueOf(Ranking.class); + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.registerClassMap(factory.classMap(rankingType, entryType) + .field("name", "key") + .field("rank", "value") + .byDefault() + .toClassMap()); + + factory.registerConcreteType(Map.Entry.class, MapEntry.class); + MapperFacade mapper = factory.getMapperFacade(); + Map result = mapper.mapAsMap(source, rankingType, mapType); + + Assert.assertNotNull(result); + Assert.assertEquals(source.size(), result.size()); + for (Ranking ranking : source) { + Assert.assertTrue(result.get(ranking.getName()).equals(ranking.getRank())); + } + + } + + /* + * Case 2b: from an array to a map + * + * we iterator over the array, and attempt to map each element to a + * Map.Entry; we'll need a special concrete destination type since Map.Entry + * is not concrete + */ + @Test + public void testArrayToMap_Simple() { + + List tempList = new ArrayList<>(); + Ranking r = new Ranking(); + r.setName("A"); + r.setRank(1); + tempList.add(r); + r = new Ranking(); + r.setName("B"); + r.setRank(2); + tempList.add(r); + r = new Ranking(); + r.setName("C"); + r.setRank(3); + tempList.add(r); + + Ranking[] source = tempList.toArray(new Ranking[0]); + + /* + * To make the map work for Collection to Map, we provide a class + * mapping from the element type in the collection to the special type + * MapEntry which represents map entries. + */ + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.registerClassMap(factory.classMap(Ranking.class, new TypeBuilder>() { + }.build()).field("name", "key").field("rank", "value").byDefault().toClassMap()); + + MapperFacade mapper = factory.getMapperFacade(); + Map result = mapper.mapAsMap(source, TypeFactory.valueOf(Ranking.class), new TypeBuilder>() { + }.build()); + + Assert.assertNotNull(result); + Assert.assertEquals(source.length, result.size()); + for (Ranking ranking : source) { + Assert.assertTrue(result.get(ranking.getName()).equals(ranking.getRank())); + } + + } + + /* + * Case 3a: from a map to a collection + * + * we iterate over the entry set, and map each entry to a collection element + */ + @Test + public void testMapToCollection_Simple() { + + Map source = new HashMap<>(); + source.put("A", 1); + source.put("B", 2); + source.put("C", 3); + + Type> mapType = new TypeBuilder>() { + }.build(); + Type> entryType = MapEntry.concreteEntryType(mapType); + Type rankingType = TypeFactory.valueOf(Ranking.class); + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.registerClassMap(factory.classMap(rankingType, entryType) + .field("name", "key") + .field("rank", "value") + .byDefault() + .toClassMap()); + + MapperFacade mapper = factory.getMapperFacade(); + + List result = mapper.mapAsList(source, mapType, rankingType); + + Assert.assertNotNull(result); + + for (Ranking ranking : result) { + Assert.assertTrue(source.get(ranking.getName()).equals(ranking.getRank())); + } + } + + /* + * Case 3b: from a map to an array + * + * we iterate over the entry set, and map each entry to an array element + */ + @Test + public void testMapToArray_Simple() { + + Map source = new HashMap<>(); + source.put("A", 1); + source.put("B", 2); + source.put("C", 3); + + Type> mapType = new TypeBuilder>() { + }.build(); + Type> entryType = MapEntry.concreteEntryType(mapType); + Type rankingType = TypeFactory.valueOf(Ranking.class); + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.registerClassMap(factory.classMap(rankingType, entryType) + .field("name", "key") + .field("rank", "value") + .byDefault() + .toClassMap()); + + MapperFacade mapper = factory.getMapperFacade(); + + Ranking[] result = mapper.mapAsArray(new Ranking[source.size()], source, mapType, rankingType); + + Assert.assertNotNull(result); + + for (Ranking ranking : result) { + Assert.assertTrue(source.get(ranking.getName()).equals(ranking.getRank())); + } + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/map/MapGenerationTestCase.java b/core/src/test/java/ma/glasnost/orika/test/map/MapGenerationTestCase.java new file mode 100644 index 00000000..98aa4dba --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/map/MapGenerationTestCase.java @@ -0,0 +1,554 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.map; + +import ma.glasnost.orika.CustomConverter; +import ma.glasnost.orika.MapEntry; +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.impl.GeneratedObjectBase; +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.test.MappingUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +public class MapGenerationTestCase { + + @Test + public void testMapToMapGeneration() throws Exception { + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.registerClassMap(factory.classMap(MapWithSetter.class, MapWithSetterDto.class).field("testScores", "scores").byDefault()); + + MapperFacade mapper = factory.getMapperFacade(); + + MapWithSetter source = new MapWithSetter(); + Map testScores = new LinkedHashMap<>(); + + testScores.put("A", 90); + testScores.put("B", 80); + testScores.put("C", 70); + source.setTestScores(testScores); + + MapWithSetterDto result = mapper.map(source, MapWithSetterDto.class); + + Assert.assertNotNull(result); + Assert.assertNotNull(result.getScores()); + for (Entry entry : testScores.entrySet()) { + Assert.assertEquals(entry.getValue(), result.getScores().get(entry.getKey())); + } + + } + + @Test + public void testMapToMapGeneration_noSetter() throws Exception { + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.registerClassMap(factory.classMap(MapWithSetter.class, MapWithoutSetter.class).field("testScores", "scores").byDefault()); + + MapperFacade mapper = factory.getMapperFacade(); + + MapWithSetter source = new MapWithSetter(); + Map testScores = new LinkedHashMap<>(); + + testScores.put("A", 90); + testScores.put("B", 80); + testScores.put("C", 70); + source.setTestScores(testScores); + + MapWithoutSetter result = mapper.map(source, MapWithoutSetter.class); + + Assert.assertNotNull(result); + Assert.assertNotNull(result.getScores()); + for (Entry entry : testScores.entrySet()) { + Assert.assertEquals(entry.getValue().toString(), result.getScores().get(entry.getKey())); + } + + } + + @Test + public void testMapToArrayGeneration() throws Exception { + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.registerClassMap(factory.classMap(MapWithSetter.class, GenericDto.class).field("testScores", "stringArray").byDefault()); + + /* + * Tell Orika how we should convert the map entries to the result array + * component type (String) + */ + factory.getConverterFactory().registerConverter(new CustomConverter, String>() { + + public String convert(Map.Entry source, Type destinationType, MappingContext context) { + return source.getKey(); + } + }); + + MapperFacade mapper = factory.getMapperFacade(); + + MapWithSetter source = new MapWithSetter(); + Map testScores = new LinkedHashMap<>(); + + testScores.put("A", 90); + testScores.put("B", 80); + testScores.put("C", 70); + source.setTestScores(testScores); + + GenericDto result = mapper.map(source, GenericDto.class); + + Assert.assertNotNull(result.getStringArray()); + + } + + @Test + public void testMapToListGeneration() throws Exception { + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.registerClassMap(factory.classMap(MapWithSetter.class, GenericDto.class).field("testScores", "stringList").byDefault()); + + /* + * Tell Orika how we should convert the map entries to the result list + * element type (String) + */ + factory.getConverterFactory().registerConverter(new CustomConverter, String>() { + + public String convert(Map.Entry source, Type destinationType, MappingContext context) { + return source.getKey(); + } + }); + + MapperFacade mapper = factory.getMapperFacade(); + + MapWithSetter source = new MapWithSetter(); + Map testScores = new LinkedHashMap<>(); + + testScores.put("A", 90); + testScores.put("B", 80); + testScores.put("C", 70); + source.setTestScores(testScores); + + GenericDto result = mapper.map(source, GenericDto.class); + + Assert.assertNotNull(result.getStringList()); + + } + + @Test + public void testListToMapGeneration() throws Exception { + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.registerClassMap(factory.classMap(MapWithoutSetter.class, GenericDto.class).field("scores", "stringList").byDefault()); + + /* + * Tell Orika how we should convert the list element type to map entry + */ + factory.getConverterFactory().registerConverter(new CustomConverter>() { + + @SuppressWarnings("serial") + private final Map> testScores = new LinkedHashMap>() { + { + put("A", new MapEntry<>("A", 90)); + put("B", new MapEntry<>("B", 80)); + put("C", new MapEntry<>("C", 70)); + put("D", new MapEntry<>("D", 60)); + put("F", new MapEntry<>("F", 50)); + } + }; + + public Map.Entry convert(String source, Type> destinationType, + MappingContext context) { + return testScores.get(source); + } + }); + + MapperFacade mapper = factory.getMapperFacade(); + + GenericDto source = new GenericDto(); + List testScores = new ArrayList<>(); + + testScores.add("A"); + testScores.add("B"); + testScores.add("C"); + source.setStringList(testScores); + + MapWithoutSetter result = mapper.map(source, MapWithoutSetter.class); + + Assert.assertNotNull(result.getScores()); + + } + + @Test + public void testArrayToMapGeneration() throws Exception { + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.registerClassMap(factory.classMap(MapWithoutSetter.class, GenericDto.class).field("scores", "stringArray").byDefault()); + + /* + * Tell Orika how we should convert the list element type to map entry + */ + factory.getConverterFactory().registerConverter(new CustomConverter>() { + + @SuppressWarnings("serial") + private final Map> testScores = new LinkedHashMap>() { + { + put("A", new MyMapEntry<>("A", 90)); + put("B", new MapEntry<>("B", 80)); + put("C", new MapEntry<>("C", 70)); + put("D", new MapEntry<>("D", 60)); + put("F", new MapEntry<>("F", 50)); + } + }; + + public Map.Entry convert(String source, Type> destinationType, + MappingContext context) { + return testScores.get(source); + } + }); + + MapperFacade mapper = factory.getMapperFacade(); + + GenericDto source = new GenericDto(); + List testScores = new ArrayList<>(); + + testScores.add("A"); + testScores.add("B"); + testScores.add("C"); + source.setStringArray(testScores.toArray(new String[testScores.size()])); + + MapWithoutSetter result = mapper.map(source, MapWithoutSetter.class); + + Assert.assertNotNull(result.getScores()); + + } + + @Test + public void testNewSyntax_mapToArrays() throws Exception { + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.registerClassMap(factory.classMap(MapWithoutSetter.class, GenericDto.class) + .field("scores{key}", "stringArray{}") + .field("scores{value}", "intArray{}") + .byDefault()); + /* + * Tell Orika how we should convert the list element type to map entry + */ + MapperFacade mapper = factory.getMapperFacade(); + + GenericDto source = new GenericDto(); + List testScores = new ArrayList<>(); + List numericScores = new ArrayList<>(); + testScores.add("A"); + numericScores.add(90); + testScores.add("B"); + numericScores.add(80); + testScores.add("C"); + numericScores.add(70); + source.setStringArray(testScores.toArray(new String[testScores.size()])); + source.setIntArray(GeneratedObjectBase.intArray(numericScores)); + + MapWithoutSetter result = mapper.map(source, MapWithoutSetter.class); + + Assert.assertNotNull(result.getScores()); + + } + + @Test + public void testNewSyntax_mapToArraysWithUnequalSize() throws Exception { + + MapperFactory factory = MappingUtil.getMapperFactory(true); + factory.registerClassMap(factory.classMap(MapWithoutSetter.class, GenericDto.class) + .field("scores{key}", "stringArray{}") + .field("scores{value}", "intArray{}") + .byDefault()); + + /* + * Tell Orika how we should convert the list element type to map entry + */ + MapperFacade mapper = factory.getMapperFacade(); + + GenericDto source = new GenericDto(); + List testScores = new ArrayList<>(); + List numericScores = new ArrayList<>(); + testScores.add("A"); + numericScores.add(90); + testScores.add("B"); + numericScores.add(80); + testScores.add("C"); + + source.setStringArray(testScores.toArray(new String[testScores.size()])); + source.setIntArray(GeneratedObjectBase.intArray(numericScores)); + + MapWithoutSetter result = mapper.map(source, MapWithoutSetter.class); + + Assert.assertNotNull(result.getScores()); + Assert.assertTrue("90".equals(result.getScores().get("A"))); + Assert.assertTrue("80".equals(result.getScores().get("B"))); + Assert.assertFalse(result.getScores().containsKey("C")); + } + + /** + * Demonstrates how a single field can be mapped to more than one + * destination, in both directions. + * + * @throws Exception + */ + @SuppressWarnings("serial") + @Test + public void testNewSyntax_multipleParallel() throws Exception { + + MapperFactory factory = MappingUtil.getMapperFactory(true); + factory.registerClassMap(factory.classMap(MapWithoutSetter.class, GenericDto.class) + .field("scores{key}", "stringArray{}") + .field("scores{value}", "intArray{}") + .field("scores{key}", "gradeList{letterGrade}") + .field("scores{value}", "gradeList{minimumScore}") + .byDefault()); + + MapWithoutSetter source = new MapWithoutSetter(); + source.setScores(new LinkedHashMap() { + { + put("A", "90"); + put("B", "80"); + put("C", "70"); + put("D", "60"); + put("F", "50"); + } + }); + + /* + * Tell Orika how we should convert the list element type to map entry + */ + MapperFacade mapper = factory.getMapperFacade(); + + GenericDto result = mapper.map(source, GenericDto.class); + + Assert.assertNotNull(result.getGradeList()); + Assert.assertEquals(source.getScores().size(), result.getGradeList().size()); + for (Grade g : result.getGradeList()) { + Assert.assertTrue(source.getScores().containsKey("" + g.getLetterGrade())); + Assert.assertTrue(source.getScores().get("" + g.getLetterGrade()).equals("" + g.getMinimumScore())); + } + + MapWithoutSetter mapBack = mapper.map(result, MapWithoutSetter.class); + Assert.assertTrue(source.getScores().keySet().containsAll(mapBack.getScores().keySet())); + Assert.assertTrue(mapBack.getScores().keySet().containsAll(source.getScores().keySet())); + } + + public static class MyMapEntry implements Map.Entry { + + private final K key; + private V value; + + public MyMapEntry(K key, V value) { + this.key = key; + this.value = value; + } + + public K getKey() { + return key; + } + + public V getValue() { + return value; + } + + public V setValue(V value) { + V oldValue = this.value; + this.value = value; + return oldValue; + } + + } + + public static class MapWithSetter { + + private Map testScores; + + public Map getTestScores() { + return Collections.unmodifiableMap(testScores); + // return testScores; + } + + public void setTestScores(Map testScores) { + this.testScores = testScores; + } + } + + public static class MapWithSetterDto { + + private Map scores; + + public Map getScores() { + return scores; + } + + public void setScores(Map scores) { + this.scores = scores; + } + } + + public static class MapWithSetterDto2 { + + private Map scores; + + public Map getScores() { + return scores; + } + + public void setScores(Map scores) { + this.scores = scores; + } + } + + public static class MapWithoutSetter { + + private Map scores; + + public Map getScores() { + return scores; + } + + public void setScores(Map scores) { + this.scores = scores; + } + } + + public static class Grade { + int minimumScore; + Character letterGrade; + + public int getMinimumScore() { + return minimumScore; + } + + public void setMinimumScore(int minimumScore) { + this.minimumScore = minimumScore; + } + + public Character getLetterGrade() { + return letterGrade; + } + + public void setLetterGrade(Character letterGrade) { + this.letterGrade = letterGrade; + } + } + + public static class GenericDto { + + private String[] stringArray; + private List stringList; + private int[] intArray; + private long[] longArray; + private List gradeList; + private Grade[] gradeArray; + private Map gradesByLetter; + private Map gradesByMinScore; + private Map lettersByGrade; + private Map scoresByGrade; + + public String[] getStringArray() { + return stringArray; + } + + public void setStringArray(String[] stringArray) { + this.stringArray = stringArray; + } + + public List getStringList() { + return stringList; + } + + public void setStringList(List stringList) { + this.stringList = stringList; + } + + public int[] getIntArray() { + return intArray; + } + + public void setIntArray(int[] intArray) { + this.intArray = intArray; + } + + public long[] getLongArray() { + return longArray; + } + + public void setLongArray(long[] longArray) { + this.longArray = longArray; + } + + public List getGradeList() { + return gradeList; + } + + public void setGradeList(List gradeList) { + this.gradeList = gradeList; + } + + public Grade[] getGradeArray() { + return gradeArray; + } + + public void setGradeArray(Grade[] gradeArray) { + this.gradeArray = gradeArray; + } + + public Map getGradesByLetter() { + return gradesByLetter; + } + + public void setGradesByLetter(Map gradesByLetter) { + this.gradesByLetter = gradesByLetter; + } + + public Map getGradesByMinScore() { + return gradesByMinScore; + } + + public void setGradesByMinScore(Map gradesByMinScore) { + this.gradesByMinScore = gradesByMinScore; + } + + public Map getLettersByGrade() { + return lettersByGrade; + } + + public void setLettersByGrade(Map lettersByGrade) { + this.lettersByGrade = lettersByGrade; + } + + public Map getScoresByGrade() { + return scoresByGrade; + } + + public void setScoresByGrade(Map scoresByGrade) { + this.scoresByGrade = scoresByGrade; + } + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/map/MultipleMapperWrapperTest.java b/core/src/test/java/ma/glasnost/orika/test/map/MultipleMapperWrapperTest.java new file mode 100644 index 00000000..07e0c79d --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/map/MultipleMapperWrapperTest.java @@ -0,0 +1,171 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.map; + +import ma.glasnost.orika.Mapper; +import ma.glasnost.orika.impl.GeneratedMapperBase; +import ma.glasnost.orika.impl.MultipleMapperWrapper; +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.metadata.TypeBuilder; +import ma.glasnost.orika.test.TestUtil; +import ma.glasnost.orika.test.community.Issue24TestCase; +import ma.glasnost.orika.test.community.issue121.Issue121TestCase; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; + +public class MultipleMapperWrapperTest { + + /** + * Simple Hirarchy Test + * + * @see Issue24TestCase + * @see https://code.google.com/archive/p/orika/ + */ + @Test + public void testFindMapper_withSimpleHirarchy() { + Exception expectedException; + + // create MultipleMapperWrapper instance to Test: + final MultipleMapperWrapper multipleMapper = createMultipleMapperWrapper( + new TypeBuilder(){}.build(), // aTypeMapper + new TypeBuilder(){}.build(), // bTypeMapper + new TypeBuilder(){}.build(), // aTypeWrapper + new TypeBuilder(){}.build()); // bTypeWrapper + + // validation: If there is no Exception it's OK (the only Mapper where found) + multipleMapper.mapAtoB(new A(), new BSub(), null); + multipleMapper.mapAtoB(new A(), new BSubSub(), null); + multipleMapper.mapAtoB(new ASub(), new BSub(), null); + multipleMapper.mapAtoB(new ASub2(), new BSub(), null); + multipleMapper.mapAtoB(new ASubSub(), new BSub(), null); + + // validation ExceptionCases: No Mapper should be found: + + // ExceptionCase 1: BSuper will be expected, but MultipleMapperWrapper knows that it + // always generates at least the more specific class B: + expectedException = TestUtil.expectException(() -> multipleMapper.mapAtoB(new A(), new BSuper(), null)); + assertThat(expectedException.getMessage(), containsString("No matching Mapper found for A <-> B\n")); + assertThat(expectedException.getMessage(), containsString("Existing Mapper: A <-> BSub\n")); + + // ExceptionCase 2: BSub2 will be expected, but no Mapper is included: + expectedException = TestUtil.expectException(() -> multipleMapper.mapAtoB(new A(), new BSub2(), null)); + assertThat(expectedException.getMessage(), containsString("No matching Mapper found for A <-> BSub2\n")); + assertThat(expectedException.getMessage(), containsString("Existing Mapper: A <-> BSub\n")); + + } + + /** + * With generic-List example + * + * @see Issue121TestCase + * @see https://code.google.com/archive/p/orika/ + */ + @Test + public void testFindMapper_withGenericList() { + Exception expectedException; + + // create MultipleMapperWrapper instance to Test: + final MultipleMapperWrapper multipleMapper = createMultipleMapperWrapper( + new TypeBuilder>(){}.build(), // aTypeMapper + new TypeBuilder>(){}.build(), // bTypeMapper + new TypeBuilder>(){}.build(), // aTypeWrapper + new TypeBuilder>(){}.build()); // bTypeWrapper + + // validation: If there is no Exception it's OK (the only Mapper where found) + multipleMapper.mapAtoB(new ArrayList(), new ArrayList(), null); + multipleMapper.mapAtoB(new ArrayList(), new ArrayList(), null); + multipleMapper.mapAtoB(new ArrayList(), new ArrayList(), null); + multipleMapper.mapAtoB(new ArrayList(), new ArrayList(), null); + multipleMapper.mapAtoB(new ArrayList(), new ArrayList(), null); + multipleMapper.mapAtoB(new ArrayList(), new ArrayList(), null); + multipleMapper.mapAtoB(Collections.unmodifiableList(new ArrayList()), new ArrayList(), null); + + // validation ExceptionCases: No Mapper should be found: + // ExceptionCase 1: A HashSet is not enough as Source, Generics get lost for error-Message. + expectedException = TestUtil.expectException(() -> multipleMapper.mapAtoB(new HashSet(), new ArrayList(), null)); + assertThat(expectedException.getMessage(), containsString("No matching Mapper found for HashSet <-> ArrayList\n")); + assertThat(expectedException.getMessage(), containsString("Existing Mapper: List <-> List\n")); + + // ExceptionCase 2: A HashSet is not enough as Target. + expectedException = TestUtil.expectException(() -> multipleMapper.mapAtoB(new ArrayList(), new HashSet(), null)); + assertThat(expectedException.getMessage(), containsString("No matching Mapper found for ArrayList <-> HashSet\n")); + assertThat(expectedException.getMessage(), containsString("Existing Mapper: List <-> List\n")); + + } + + private MultipleMapperWrapper createMultipleMapperWrapper(Type aTypeMapper, Type bTypeMapper, Type aTypeWrapper, + Type bTypeWrapper) { + GeneratedMapperBase generatedMapper = new GeneratedMapperBase() { + }; + generatedMapper.setAType(aTypeMapper); + generatedMapper.setBType(bTypeMapper); + + List> mappers = Collections.singletonList((Mapper) generatedMapper); + @SuppressWarnings("unchecked") + MultipleMapperWrapper multipleMapper = new MultipleMapperWrapper((Type) aTypeWrapper, (Type) bTypeWrapper, mappers); + return multipleMapper; + } + + public static class ASuper { + + } + + public static class A extends ASuper { + + } + + public static class ASub extends A { + + } + + public static class ASub2 extends A { + + } + + public static class ASubSub extends ASub { + + } + + public static class BSuper { + + } + + public static class B extends BSuper { + + } + + public static class BSub extends B { + + } + + public static class BSub2 extends B { + + } + + public static class BSubSub extends BSub { + + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/map/MultipleMapperWrapperTestSuite.java b/core/src/test/java/ma/glasnost/orika/test/map/MultipleMapperWrapperTestSuite.java new file mode 100644 index 00000000..73162de1 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/map/MultipleMapperWrapperTestSuite.java @@ -0,0 +1,69 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.map; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.is; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; + +import ma.glasnost.orika.Mapper; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.impl.MultipleMapperWrapper; +import ma.glasnost.orika.metadata.MapperKey; +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.metadata.TypeFactory; +import ma.glasnost.orika.test.DynamicSuite; +import ma.glasnost.orika.test.DynamicSuite.Scenario; +import ma.glasnost.orika.test.DynamicSuite.TestCasePattern; + +/** + * Run All *TestCase.java Unit-Tests, but use always the {@link MultipleMapperWrapper} even if no ObjectFactory is used or only one Mapper + * where found. + *

+ * This should covering all special cases. + * + */ +@RunWith(DynamicSuite.class) +@TestCasePattern(".*TestCase") +@Scenario(name = "alwaysCreateMultipleMapperWrapper") +public class MultipleMapperWrapperTestSuite { + + @BeforeClass + public static void alwaysCreateMultipleMapperWrapper() { + System.setProperty("ma.glasnost.orika.alwaysCreateMultipleMapperWrapper", "true"); + // validate basic pre-requirements for this TestSuite (be sure that the property is set and evaluated right): + final MapperFactory factory = new DefaultMapperFactory.Builder().build(); + Type aType = TypeFactory.valueOf(A.class); + Mapper mapper = factory.lookupMapper(new MapperKey(aType, aType)); + assertThat(mapper, is(instanceOf(MultipleMapperWrapper.class))); + + } + + @AfterClass + public static void tearDown() { + System.clearProperty("ma.glasnost.orika.alwaysCreateMultipleMapperWrapper"); + } + + public static class A { + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/metadata/CaseInsensitiveClassMapBuilderTest.java b/core/src/test/java/ma/glasnost/orika/test/metadata/CaseInsensitiveClassMapBuilderTest.java new file mode 100644 index 00000000..80bc5c08 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/metadata/CaseInsensitiveClassMapBuilderTest.java @@ -0,0 +1,159 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.metadata; + +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.metadata.CaseInsensitiveClassMapBuilder; +import org.junit.Test; + +import javax.xml.datatype.XMLGregorianCalendar; +import java.util.Date; + +import static org.junit.Assert.assertEquals; + +public class CaseInsensitiveClassMapBuilderTest { + + @Test + public void byDefault() { + MapperFactory factory = new DefaultMapperFactory.Builder() + .classMapBuilderFactory(new CaseInsensitiveClassMapBuilder.Factory()) + .build(); + + factory.classMap(Source.class, Destination.class) + .byDefault() + .register(); + + Source s = new Source(); + s.lastNAME = "Smith"; + s.firstName = "Joe"; + s.age = 25; + + Destination d = factory.getMapperFacade().map(s, Destination.class); + + assertEquals(s.firstName, d.fIrStNaMe); + assertEquals(s.lastNAME, d.LastName); + assertEquals(s.age, d.AGE); + } + + @Test + public void fieldMap_without_nested_properties() { + MapperFactory factory = new DefaultMapperFactory.Builder() + .classMapBuilderFactory(new CaseInsensitiveClassMapBuilder.Factory()) + .build(); + + factory.classMap(Source.class, Destination.class) + .field("FIRSTname", "FIRSTname") + .field("lastNAME", "lastNAME") + .field("aGE", "aGE") + .register(); + + Source s = new Source(); + s.lastNAME = "Smith"; + s.firstName = "Joe"; + s.age = 25; + + Destination d = factory.getMapperFacade().map(s, Destination.class); + + assertEquals(s.firstName, d.fIrStNaMe); + assertEquals(s.lastNAME, d.LastName); + assertEquals(s.age, d.AGE); + } + + @Test + public void fieldMap_with_nested_properties() { + MapperFactory factory = new DefaultMapperFactory.Builder() + .classMapBuilderFactory(new CaseInsensitiveClassMapBuilder.Factory()) + .build(); + + factory.classMap(Source.class, Destination.class) + .field("FIRSTname", "FIRSTname") + .field("lastNAME", "lastNAME") + .field("aGE", "aGE") + .field("name.first", "name.first") + .field("name.last", "name.last") + .register(); + + Source s = new Source(); + s.lastNAME = "Smith"; + s.firstName = "Joe"; + s.age = 25; + s.NaMe = new SourceName(); + s.NaMe.FIRST = "Joe"; + s.NaMe.LAST = "Smith"; + + Destination d = factory.getMapperFacade().map(s, Destination.class); + + assertEquals(s.firstName, d.fIrStNaMe); + assertEquals(s.lastNAME, d.LastName); + assertEquals(s.age, d.AGE); + assertEquals(s.NaMe.FIRST, d.nAme.fIrSt); + assertEquals(s.NaMe.LAST, d.nAme.LaSt); + } + + @Test // issue 236 + public void maps_date_to_xml_gregorian_calendar_by_default_without_mapping_its_fields() throws Exception { + MapperFactory factory = new DefaultMapperFactory.Builder() + .classMapBuilderFactory(new CaseInsensitiveClassMapBuilder.Factory()) + .build(); + + factory.classMap(SourceDate.class, DestinationDate.class) + .byDefault() + .register(); + + final SourceDate source = new SourceDate(); + source.date = new Date(); + + DestinationDate destination = factory.getMapperFacade().map(source, DestinationDate.class); + + assertEquals(source.date, destination.date.toGregorianCalendar().getTime()); + } + + public static class Source { + public String lastNAME; + public String firstName; + public Integer age; + public SourceName NaMe; + } + + public static class SourceName { + public String FIRST; + public String LAST; + } + + public static class Destination { + public String LastName; + public String fIrStNaMe; + public Integer AGE; + public DestinationName nAme; + } + + public static class DestinationName { + public String fIrSt; + public String LaSt; + } + + public static class SourceDate { + public Date date; + } + + public static class DestinationDate { + public XMLGregorianCalendar date; + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/metadata/ClassMapBuilderTest.java b/core/src/test/java/ma/glasnost/orika/test/metadata/ClassMapBuilderTest.java new file mode 100644 index 00000000..62e03766 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/metadata/ClassMapBuilderTest.java @@ -0,0 +1,242 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.metadata; + +import static ma.glasnost.orika.metadata.MappingDirection.A_TO_B; +import static ma.glasnost.orika.metadata.MappingDirection.B_TO_A; + +import org.junit.Assert; +import org.junit.Test; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.metadata.CaseInsensitiveClassMapBuilder; + +/** + * @author matt.deboer@gmail.com + * + */ +public class ClassMapBuilderTest { + + public static class Source { + public final String lastName; + public final String firstName; + public final Integer age; + public final SourceName name; + + public Source(String firstName, String lastName, Integer age, SourceName name) { + this.firstName = firstName; + this.lastName = lastName; + this.age = age; + this.name = name; + } + } + + public static class Source2 { + public String lastName; + public String firstName; + public Integer age; + public SourceName name; + } + + public static class SourceName { + public String first; + public String last; + } + + public static class Destination { + public String lastName; + public String firstName; + public Integer age; + public DestinationName name; + } + + public static class DestinationName { + public String first; + public String last; + } + + @Test + public void byDefault() { + + MapperFactory factory = new DefaultMapperFactory.Builder() + .classMapBuilderFactory(new CaseInsensitiveClassMapBuilder.Factory()).build(); + + factory.classMap(Source.class, Destination.class).byDefault().register(); + + MapperFacade mapper = factory.getMapperFacade(); + + Source s = new Source("Joe", "Smith", 25, null); + Destination d = mapper.map(s, Destination.class); + /* + * Check that properties we expect were mapped + */ + Assert.assertEquals(s.firstName, d.firstName); + Assert.assertEquals(s.lastName, d.lastName); + Assert.assertEquals(s.age, d.age); + } + + @Test + public void byDefault_AtoB_final() { + + MapperFactory factory = new DefaultMapperFactory.Builder() + .classMapBuilderFactory(new CaseInsensitiveClassMapBuilder.Factory()).build(); + + factory.classMap(Source.class, Destination.class) + .byDefault(A_TO_B) + .register(); + + + MapperFacade mapper = factory.getMapperFacade(); + + SourceName name = new SourceName(); + name.first = "Joe"; + name.last = "Smith"; + + Source s = new Source("Joe", "Smith", 25, name); + + + Destination d = mapper.map(s, Destination.class); + /* + * Check that properties we expect were mapped + */ + Assert.assertEquals(s.firstName, d.firstName); + Assert.assertEquals(s.lastName, d.lastName); + Assert.assertEquals(s.age, d.age); + Assert.assertEquals(s.name.first, d.name.first); + Assert.assertEquals(s.name.last, d.name.last); + } + + @Test + public void byDefault_AtoB() { + + MapperFactory factory = new DefaultMapperFactory.Builder() + .classMapBuilderFactory(new CaseInsensitiveClassMapBuilder.Factory()).build(); + + factory.classMap(Source2.class, Destination.class) + .byDefault(A_TO_B) + .register(); + + + MapperFacade mapper = factory.getMapperFacade(); + + SourceName name = new SourceName(); + name.first = "Joe"; + name.last = "Smith"; + + Source2 s = new Source2(); + s.firstName = "Joe"; + s.lastName = "Smith"; + s.age = 25; + s.name = name; + + Destination d = mapper.map(s, Destination.class); + /* + * Check that properties we expect were mapped + */ + Assert.assertEquals(s.firstName, d.firstName); + Assert.assertEquals(s.lastName, d.lastName); + Assert.assertEquals(s.age, d.age); + Assert.assertEquals(s.name.first, d.name.first); + Assert.assertEquals(s.name.last, d.name.last); + + /* + * Check that byDefault was only in one direction + */ + Source2 mapBack = mapper.map(d, Source2.class); + Assert.assertNull(mapBack.firstName); + Assert.assertNull(mapBack.lastName); + Assert.assertNull(mapBack.age); + Assert.assertNull(mapBack.name); + } + + @Test + public void byDefault_BtoA_final() { + + MapperFactory factory = new DefaultMapperFactory.Builder() + .classMapBuilderFactory(new CaseInsensitiveClassMapBuilder.Factory()).build(); + + factory.classMap(Destination.class, Source.class) + .byDefault(B_TO_A) + .register(); + + + MapperFacade mapper = factory.getMapperFacade(); + + SourceName name = new SourceName(); + name.first = "Joe"; + name.last = "Smith"; + + Source s = new Source("Joe", "Smith", 25, name); + + + Destination d = mapper.map(s, Destination.class); + /* + * Check that properties we expect were mapped + */ + Assert.assertEquals(s.firstName, d.firstName); + Assert.assertEquals(s.lastName, d.lastName); + Assert.assertEquals(s.age, d.age); + Assert.assertEquals(s.name.first, d.name.first); + Assert.assertEquals(s.name.last, d.name.last); + } + + @Test + public void byDefault_BtoA() { + + MapperFactory factory = new DefaultMapperFactory.Builder() + .classMapBuilderFactory(new CaseInsensitiveClassMapBuilder.Factory()).build(); + + factory.classMap(Destination.class, Source2.class) + .byDefault(B_TO_A) + .register(); + + + MapperFacade mapper = factory.getMapperFacade(); + + SourceName name = new SourceName(); + name.first = "Joe"; + name.last = "Smith"; + + Source2 s = new Source2(); + s.firstName = "Joe"; + s.lastName = "Smith"; + s.age = 25; + s.name = name; + + + Destination d = mapper.map(s, Destination.class); + /* + * Check that properties we expect were mapped + */ + Assert.assertEquals(s.firstName, d.firstName); + Assert.assertEquals(s.lastName, d.lastName); + Assert.assertEquals(s.age, d.age); + Assert.assertEquals(s.name.first, d.name.first); + Assert.assertEquals(s.name.last, d.name.last); + /* + * Check that byDefault was only in one direction + */ + Source2 mapBack = mapper.map(d, Source2.class); + Assert.assertNull(mapBack.firstName); + Assert.assertNull(mapBack.lastName); + Assert.assertNull(mapBack.age); + Assert.assertNull(mapBack.name); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/metadata/Issues296Test.java b/core/src/test/java/ma/glasnost/orika/test/metadata/Issues296Test.java new file mode 100644 index 00000000..d57503ba --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/metadata/Issues296Test.java @@ -0,0 +1,71 @@ +package ma.glasnost.orika.test.metadata; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import org.junit.Assert; +import org.junit.Test; + +/** + * + * @Auther: 530827804@qq.com + * @Date: 2018/12/6 + */ +public class Issues296Test { + + @Test + public void testIssues296() { + MapperFactory factory = new DefaultMapperFactory.Builder().build(); + final MapperFacade mapperFacade = factory.getMapperFacade(); + A a = new A(); + B b = new B(); + F f = new F(); + f.setG(b); + a.setF(f); + final D d = mapperFacade.map(a, D.class); + final H g = mapperFacade.map(a, H.class); + Assert.assertEquals(d.getF().getG().getClass(), C.class); + Assert.assertEquals(g.getF().getG().getClass(), C.class); + } + + public static class A { + + F f; + + public F getF() { + return f; + } + + public void setF(F f) { + this.f = f; + } + } + + public static class B { + + } + + public static class C extends B { + + } + + public static class D extends A { + + } + + public static class F { + G g; + + public G getG() { + return g; + } + + public void setG(G g) { + this.g = g; + } + } + + public static class H extends D { + + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/metadata/ScoringClassMapBuilderTest.java b/core/src/test/java/ma/glasnost/orika/test/metadata/ScoringClassMapBuilderTest.java new file mode 100644 index 00000000..019833ad --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/metadata/ScoringClassMapBuilderTest.java @@ -0,0 +1,149 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.metadata; + +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.metadata.ClassMap; +import ma.glasnost.orika.metadata.FieldMap; +import ma.glasnost.orika.metadata.ScoringClassMapBuilder; +import org.junit.Assert; +import org.junit.Test; + +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import static java.util.Arrays.asList; + +/** + * @author matt.deboer@gmail.com + * + */ +public class ScoringClassMapBuilderTest { + public static class Name { + public String first; + public String middle; + public String last; + } + + public static class Source { + public String lastName; + public Integer age; + public PostalAddress postalAddress; + public String firstName; + public String stateOfBirth; + public String eyeColor; + public String driversLicenseNumber; + } + + public static class Destination { + public Name name; + public Integer currentAge; + public String streetAddress; + public String birthState; + public String countryCode; + public String favoriteColor; + public String id; + } + + public static class PostalAddress { + public String street; + public String city; + public String state; + public String postalCode; + public Country country; + } + + public static class Country { + public String name; + public String alphaCode; + public int numericCode; + } + + @Test + public void testClassMapBuilderExtension() { + + MapperFactory factory = new DefaultMapperFactory.Builder().classMapBuilderFactory(new ScoringClassMapBuilder.Factory()).build(); + + ClassMap map = factory.classMap(Source.class, Destination.class).byDefault().toClassMap(); + Map mapping = new HashMap<>(); + for (FieldMap f : map.getFieldsMapping()) { + mapping.put(f.getSource().getExpression(), f.getDestination().getExpression()); + } + + /* + * Check that properties we expect were mapped + */ + Assert.assertEquals("name.first", mapping.get("firstName")); + Assert.assertEquals("name.last", mapping.get("lastName")); + Assert.assertEquals("streetAddress", mapping.get("postalAddress.street")); + Assert.assertEquals("countryCode", mapping.get("postalAddress.country.alphaCode")); + Assert.assertEquals("currentAge", mapping.get("age")); + Assert.assertEquals("birthState", mapping.get("stateOfBirth")); + + /* + * Check that properties that we don't expect aren't mapped by accident + */ + Assert.assertFalse(mapping.containsKey("driversLicenseNumber")); + Assert.assertFalse(mapping.containsKey("eyeColor")); + + + } + + @SuppressWarnings("unchecked") + @Test + public void testSplittingWords() throws Throwable { + Map>> tests = new HashMap>>() { + private static final long serialVersionUID = 1L; + { + put("lowercase", asList(asList("lowercase"))); + put("Class", asList(asList("class"))); + put("MyClass", asList(asList("my", "class"))); + put("HTML", asList(asList("html"))); + put("PDFLoader", asList(asList("pdf", "loader"))); + put("AString", asList(asList("a", "string"))); + put("SimpleXMLParser", asList(asList("Simple", "xml", "parser"))); + put("GL11Version", asList(asList("gl", "11", "version"))); + put("99Bottles", asList(asList("99", "bottles"))); + put("May5", asList(asList("may", "5"))); + put("BFG9000", asList(asList("bfg", "9000"))); + put("SimpleXMLParser", asList(asList("simple", "xml", "parser"))); + put("postalAddress.country", asList(asList("postal", "address"), asList("country"))); + put("aVeryLongWord.name.first", asList(asList("a", "very", "long", "word"), asList("name"), asList("first"))); + } + }; + + Method splitIntoWords = ScoringClassMapBuilder.FieldMatchScore.class.getDeclaredMethod("splitIntoLowerCaseWords", String.class); + splitIntoWords.setAccessible(true); + + for (Entry>> test : tests.entrySet()) { + + List> testValue = test.getValue(); + List> result = (List>)splitIntoWords.invoke(null, test.getKey()); + Assert.assertEquals(testValue.size(), result.size()); + for (int i=0, len = testValue.size(); i < len; ++i) { + Assert.assertEquals(testValue.get(i), result.get(i)); + } + } + + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/metadata/TypeFactoryTestCase.java b/core/src/test/java/ma/glasnost/orika/test/metadata/TypeFactoryTestCase.java new file mode 100644 index 00000000..eb5fd05a --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/metadata/TypeFactoryTestCase.java @@ -0,0 +1,178 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.metadata; + +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.metadata.TypeFactory; +import org.junit.Assert; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.is; + +/** + * @author matt.deboer@gmail.com + * + */ +public class TypeFactoryTestCase { + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Test + public void createTypeFromClass() { + Type type = TypeFactory.valueOf("java.util.List"); + + Assert.assertEquals(List.class, type.getRawType()); + } + + @Test + public void createTypeFromClass_defaultPackages() { + Type type = TypeFactory.valueOf("List"); + + Assert.assertEquals(List.class, type.getRawType()); + + type = TypeFactory.valueOf("String"); + + Assert.assertEquals(String.class, type.getRawType()); + } + + @Test + public void createTypeFromNestedClass() { + Type type = TypeFactory.valueOf("List"); + + Assert.assertEquals(List.class, type.getRawType()); + Assert.assertEquals(Long.class, type.getNestedType(0).getRawType()); + } + + @Test + public void createTypeFromMultipleNestedClass() { + Type type = TypeFactory.valueOf("List>>>"); + + Assert.assertEquals(List.class, type.getRawType()); + Assert.assertEquals(Map.class, type.getNestedType(0).getRawType()); + Assert.assertEquals(String.class, type.getNestedType(0).getNestedType(0).getRawType()); + Assert.assertEquals(Set.class, type.getNestedType(0).getNestedType(1).getRawType()); + Assert.assertEquals(Map.class, type.getNestedType(0).getNestedType(1).getNestedType(0).getRawType()); + Assert.assertEquals(String.class, type.getNestedType(0).getNestedType(1).getNestedType(0).getNestedType(0).getRawType()); + Assert.assertEquals(File.class, type.getNestedType(0).getNestedType(1).getNestedType(0).getNestedType(1).getRawType()); + + } + + @Test(expected=IllegalArgumentException.class) + public void createTypeFromMultipleNestedClass_invalidExpression() { + TypeFactory.valueOf("List>>"); + } + + @Test(expected=IllegalArgumentException.class) + public void createTypeFromMultipleNestedClass_invalidType() { + TypeFactory.valueOf("List>>>"); + } + + @Test + @SuppressWarnings("rawtypes") + public void createTypeWithMultibleBounds() { + Type valueOf = TypeFactory.valueOf(MyObjectWithMultibleBound.class); + Assert.assertEquals("MyObjectWithMultibleBound>", valueOf.toString()); + + } + + @Test + @SuppressWarnings({"rawtypes", "unchecked"}) + public void createTypeFromClassHirarchy() { + Type type = TypeFactory.valueOf(MyObject2.class); + Type interfaceType = TypeFactory.valueOf(MyInterface.class); + + TypeFactory.valueOf(interfaceType); + java.lang.reflect.Type firstArgType = type.findInterface(interfaceType).getActualTypeArguments()[0]; + Type firstType = TypeFactory.valueOf(firstArgType); + Assert.assertEquals(String.class, firstType.getRawType()); + + java.lang.reflect.Type secondArgType = type.findInterface(interfaceType).getActualTypeArguments()[1]; + Type secondType = TypeFactory.valueOf(secondArgType); + Assert.assertEquals(Collection.class, secondType.getRawType()); + + } + + @Test + public void testRefineBoundsSuccess() throws Exception { + testRefineBoundsSuccess(Long.class, Long.class, Object.class); + testRefineBoundsSuccess(HashSet.class, Set.class, HashSet.class, Object.class); + } + + @Test + public void testRefineBoundsFail() throws Exception { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage(containsString("Long")); // it can be "Long and String" or "String and Long" + thrown.expectMessage(containsString("String")); + thrown.expectMessage(containsString("are not comparable")); + + testRefineBoundsSuccess(HashSet.class, String.class, Long.class); + } + + @SuppressWarnings("rawtypes") + public void testRefineBoundsSuccess(Class expetedClass, Class... boundsClass) throws Exception { + Set> bounds = new HashSet<>(); + for (Class clazz : boundsClass) { + bounds.add(TypeFactory.valueOf(clazz)); + } + assertThat(refineBounds(bounds), is((Type) TypeFactory.valueOf(expetedClass))); + } + + @SuppressWarnings("rawtypes") + private static Type refineBounds(Set> bounds) throws Exception { + // call private TypeFactory.refineBounds() per reflection: + Class typeFactoryClass = TypeFactory.class; + Method refineMethod = typeFactoryClass.getDeclaredMethod("refineBounds", Set.class); + refineMethod.setAccessible(true); + try { + return (Type) refineMethod.invoke(null, bounds); + } catch (InvocationTargetException e) { + if (e.getTargetException() instanceof RuntimeException) { + throw (RuntimeException) e.getTargetException(); + } + throw e; + } + } + + public static class MyObject2 implements MyInterface> { + // test Class + } + + @SuppressWarnings("unused") + public interface MyInterface { + // test Class + } + + @SuppressWarnings("unused") + public static class MyObjectWithMultibleBound & Set> { + // test Class + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/metadata/VariableRefTestCase.java b/core/src/test/java/ma/glasnost/orika/test/metadata/VariableRefTestCase.java new file mode 100644 index 00000000..5bc95255 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/metadata/VariableRefTestCase.java @@ -0,0 +1,64 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.metadata; + +import ma.glasnost.orika.impl.UtilityResolver; +import ma.glasnost.orika.metadata.Property; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +public class VariableRefTestCase { + + + public static class Year { + public int yearNumber; + public List months = new ArrayList<>(); + } + + public static class Month { + public int monthNumber; + public List days = new ArrayList<>(); + } + + public static class Day { + public int dayNumber; + public String dayOfWeek; + } + + public static class FlatData { + public int dayNumber; + public String dayOfWeek; + public int yearNumber; + public int monthNumber; + } + + + @Test + public void testGetter() { + + Property prop = UtilityResolver.getDefaultPropertyResolverStrategy().getProperty(Year.class, "months{days{dayOfWeek}}"); + Assert.assertNotNull(prop); + Assert.assertNotNull(prop.getContainer()); + Assert.assertNotNull(prop.getContainer().getContainer()); + + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/object/BidirectionalMappingTestCase.java b/core/src/test/java/ma/glasnost/orika/test/object/BidirectionalMappingTestCase.java new file mode 100644 index 00000000..b426f608 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/object/BidirectionalMappingTestCase.java @@ -0,0 +1,159 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.object; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.test.MappingUtil; + +import org.junit.Assert; +import org.junit.Test; + +public class BidirectionalMappingTestCase { + + @Test + public void testBidirectionalMapping() { + MapperFacade mapper = MappingUtil.getMapperFactory().getMapperFacade(); + + Author author = new Author(); + author.setFirstName("Khalil"); + author.setLastName("Gibran"); + + Book book = new Book(); + book.setTitle("The Prophet"); + book.setAuthor(author); + author.setBook(book); + + BookDTO dto = mapper.map(book, BookDTO.class); + + Assert.assertEquals(book.getTitle(), dto.getTitle()); + Assert.assertEquals(book.getAuthor().getFirstName(), dto.getAuthor().getFirstName()); + + Assert.assertEquals(book.getAuthor().getLastName(), dto.getAuthor().getLastName()); + + Assert.assertTrue(dto == dto.getAuthor().getBook()); + } + + public static class Author { + private String firstName; + private String lastName; + private Book book; + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public Book getBook() { + return book; + } + + public void setBook(Book book) { + this.book = book; + } + + } + + public static class Book { + + private String title; + + private Author author; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public Author getAuthor() { + return author; + } + + public void setAuthor(Author author) { + this.author = author; + } + } + + public static class AuthorDTO { + private String firstName; + private String lastName; + private BookDTO book; + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public BookDTO getBook() { + return book; + } + + public void setBook(BookDTO book) { + this.book = book; + } + } + + public static class BookDTO { + + private String title; + + private AuthorDTO author; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public AuthorDTO getAuthor() { + return author; + } + + public void setAuthor(AuthorDTO author) { + this.author = author; + } + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/object/InverseMappingTestCase.java b/core/src/test/java/ma/glasnost/orika/test/object/InverseMappingTestCase.java new file mode 100644 index 00000000..da48e99e --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/object/InverseMappingTestCase.java @@ -0,0 +1,427 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.object; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.metadata.ClassMapBuilder; +import ma.glasnost.orika.test.MappingUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.util.HashSet; +import java.util.Set; + +public class InverseMappingTestCase { + + @Test + public void testInverseOneToOneMapping() { + MapperFactory mapperFactory = MappingUtil.getMapperFactory(); + + ClassMapBuilder classMapBuilder = mapperFactory.classMap(PersonDTO.class, Person.class); + classMapBuilder.fieldMap("address").bInverse("person").add(); + mapperFactory.registerClassMap(classMapBuilder.byDefault().toClassMap()); + + MapperFacade mapper = mapperFactory.getMapperFacade(); + + AddressDTO addressDTO = new AddressDTO(); + addressDTO.setLine1("5 rue Blida"); + addressDTO.setLine2("20100 Casablanca"); + + PersonDTO personDTO = new PersonDTO(); + personDTO.setFirstName("Khalil"); + personDTO.setLastName("Gibran"); + personDTO.setAddress(addressDTO); + + Person person = mapper.map(personDTO, Person.class); + + Assert.assertEquals(personDTO.getFirstName(), person.getFirstName()); + Assert.assertEquals(personDTO.getAddress().getLine1(), person.getAddress().getLine1()); + + Assert.assertTrue(person == person.getAddress().getPerson()); + } + + @Test + public void testInverseOneToManyMapping() { + MapperFactory mapperFactory = MappingUtil.getMapperFactory(); + + ClassMapBuilder classMapBuilder = mapperFactory.classMap(PublisherDTO.class, Publisher.class); + classMapBuilder.fieldMap("books").bInverse("publisher").add(); + mapperFactory.registerClassMap(classMapBuilder.byDefault().toClassMap()); + + MapperFacade mapper = mapperFactory.getMapperFacade(); + + BookDTO parisNoirDTO = new BookDTO(); + parisNoirDTO.setTitle("Paris Noir"); + + BookDTO chiensFousDTO = new BookDTO(); + chiensFousDTO.setTitle("Chiens Fous"); + + PublisherDTO publisherDTO = new PublisherDTO(); + publisherDTO.setName("Asphalte Editions"); + publisherDTO.getBooks().add(parisNoirDTO); + publisherDTO.getBooks().add(chiensFousDTO); + + Publisher publisher = mapper.map(publisherDTO, Publisher.class); + + Assert.assertTrue(publisher == publisher.getBooks().iterator().next().getPublisher()); + } + + @Test + public void testInverseManyToOneMapping() { + MapperFactory mapperFactory = MappingUtil.getMapperFactory(); + + ClassMapBuilder classMapBuilder = mapperFactory.classMap(BookDTO.class, Book.class); + classMapBuilder.fieldMap("author").bInverse("books").add(); + mapperFactory.registerClassMap(classMapBuilder.byDefault().toClassMap()); + + MapperFacade mapper = mapperFactory.getMapperFacade(); + + AuthorDTO authorDTO = new AuthorDTO(); + authorDTO.setFirstName("Khalil"); + authorDTO.setLastName("Gibran"); + + BookDTO bookDTO = new BookDTO(); + bookDTO.setTitle("The Prophet"); + bookDTO.setAuthor(authorDTO); + + Book book = mapper.map(bookDTO, Book.class); + + Assert.assertTrue(book.getAuthor().getBooks().contains(book)); + } + + @Test + public void testInverseManyToManyMapping() { + MapperFactory mapperFactory = MappingUtil.getMapperFactory(); + + ClassMapBuilder classMapBuilder = mapperFactory.classMap(ReaderDTO.class, Reader.class); + classMapBuilder.fieldMap("books").bInverse("readers").add(); + mapperFactory.registerClassMap(classMapBuilder.byDefault().toClassMap()); + + MapperFacade mapper = mapperFactory.getMapperFacade(); + + Set bookDTOs = new HashSet<>(); + BookDTO bookDTO = new BookDTO(); + bookDTO.setTitle("The Prophet"); + bookDTOs.add(bookDTO); + bookDTO = new BookDTO(); + bookDTO.setTitle("More Effective Java"); + bookDTOs.add(bookDTO); + + ReaderDTO readerDTO = new ReaderDTO(); + readerDTO.setFirstName("Jennifer"); + readerDTO.setLastName("Lopez"); + readerDTO.setBooks(bookDTOs); + + Reader reader = mapper.map(readerDTO, Reader.class); + + for (Book book : reader.getBooks()) { + Assert.assertTrue(book.getReaders().contains(reader)); + } + } + + public static class Person { + + private String firstName; + + private String lastName; + + private Address address; + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public Address getAddress() { + return address; + } + + public void setAddress(Address address) { + this.address = address; + } + + } + + public static class Address { + + private String line1; + + private String line2; + + private Person person; + + public String getLine1() { + return line1; + } + + public void setLine1(String line1) { + this.line1 = line1; + } + + public String getLine2() { + return line2; + } + + public void setLine2(String line2) { + this.line2 = line2; + } + + public Person getPerson() { + return person; + } + + public void setPerson(Person person) { + this.person = person; + } + + } + + public static class Book { + + private String title; + + private Author author; + + private Publisher publisher; + + private Set readers; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public Author getAuthor() { + return author; + } + + public void setAuthor(Author author) { + this.author = author; + } + + public Publisher getPublisher() { + return publisher; + } + + public void setPublisher(Publisher publisher) { + this.publisher = publisher; + } + + public Set getReaders() { + return readers; + } + + public void setReaders(Set readers) { + this.readers = readers; + } + + } + + public static class Author extends Person { + + private Set books; + + public Set getBooks() { + return books; + } + + public void setBooks(Set books) { + this.books = books; + } + + } + + public static class Reader extends Person { + + private Set books; + + public Set getBooks() { + return books; + } + + public void setBooks(Set books) { + this.books = books; + } + + } + + public static class Publisher { + + private String name; + + private Set books; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Set getBooks() { + return books; + } + + public void setBooks(Set books) { + this.books = books; + } + + } + + public static class PersonDTO { + + private String firstName; + + private String lastName; + + private AddressDTO address; + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public AddressDTO getAddress() { + return address; + } + + public void setAddress(AddressDTO address) { + this.address = address; + } + + } + + public static class AddressDTO { + + private String line1; + + private String line2; + + public String getLine1() { + return line1; + } + + public void setLine1(String line1) { + this.line1 = line1; + } + + public String getLine2() { + return line2; + } + + public void setLine2(String line2) { + this.line2 = line2; + } + + } + + public static class BookDTO { + + private String title; + + private AuthorDTO author; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public AuthorDTO getAuthor() { + return author; + } + + public void setAuthor(AuthorDTO author) { + this.author = author; + } + + } + + public static class AuthorDTO extends PersonDTO { + + } + + public static class ReaderDTO extends PersonDTO { + + private Set books; + + public Set getBooks() { + return books; + } + + public void setBooks(Set books) { + this.books = books; + } + + } + + public static class PublisherDTO { + + private String name; + + private Set books = new HashSet<>(); + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Set getBooks() { + return books; + } + + public void setBooks(Set books) { + this.books = books; + } + + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/object/ObjectTestCase.java b/core/src/test/java/ma/glasnost/orika/test/object/ObjectTestCase.java new file mode 100644 index 00000000..e3d1d2ea --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/object/ObjectTestCase.java @@ -0,0 +1,136 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.object; +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.test.MappingUtil; + +import org.junit.Assert; +import org.junit.Test; + + +public class ObjectTestCase { + + @Test + public void testObjectMapping() { + MapperFacade mapper = MappingUtil.getMapperFactory().getMapperFacade(); + + Author author = new Author(); + author.setFirstName("Khalil"); + author.setLastName("Gibran"); + + Book book = new Book(); + book.setTitle("The Prophet"); + book.setAuthor(author); + + BookDTO dto = mapper.map(book, BookDTO.class); + + Assert.assertEquals(book.getTitle(), dto.getTitle()); + Assert.assertEquals(book.getAuthor().getFirstName(), dto.getAuthor().getFirstName()); + Assert.assertEquals(book.getAuthor().getLastName(), dto.getAuthor().getLastName()); + + } + + public static class Author { + private String firstName; + private String lastName; + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + } + + public static class Book { + + private String title; + + private Author author; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public Author getAuthor() { + return author; + } + + public void setAuthor(Author author) { + this.author = author; + } + } + + public static class AuthorDTO { + private String firstName; + private String lastName; + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + } + + public static class BookDTO { + + private String title; + + private AuthorDTO author; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public AuthorDTO getAuthor() { + return author; + } + + public void setAuthor(AuthorDTO author) { + this.author = author; + } + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/objectfactory/CustomFactory.java b/core/src/test/java/ma/glasnost/orika/test/objectfactory/CustomFactory.java new file mode 100644 index 00000000..7811755c --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/objectfactory/CustomFactory.java @@ -0,0 +1,24 @@ +package ma.glasnost.orika.test.objectfactory; + +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.ObjectFactory; + +import java.lang.reflect.Constructor; + +public class CustomFactory implements ObjectFactory { + private final Class type; + + public CustomFactory(Class type) { + this.type = type; + } + + public T create(Object o, MappingContext mappingContext) { + try { + Constructor declaredConstructor = type.getDeclaredConstructor(); + declaredConstructor.setAccessible(true); + return declaredConstructor.newInstance(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/objectfactory/MultipleObjectFactoryTest.java b/core/src/test/java/ma/glasnost/orika/test/objectfactory/MultipleObjectFactoryTest.java new file mode 100644 index 00000000..cdd9f183 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/objectfactory/MultipleObjectFactoryTest.java @@ -0,0 +1,33 @@ +package ma.glasnost.orika.test.objectfactory; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.metadata.TypeFactory; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class MultipleObjectFactoryTest { + public static class Base { + } + + public static class Sub1 extends Base { + } + + public static class Sub2 extends Base { + } + + @Test + public void orikaTest() { + MapperFactory factory = new DefaultMapperFactory.Builder().build(); + + factory.registerObjectFactory(new CustomFactory<>(Sub1.class), TypeFactory.valueOf(Sub1.class)); + factory.registerObjectFactory(new CustomFactory<>(Sub2.class), TypeFactory.valueOf(Sub2.class)); + factory.registerObjectFactory(new CustomFactory<>(Base.class), TypeFactory.valueOf(Base.class)); + + MapperFacade mapperFacade = factory.getMapperFacade(); + Base mapped = mapperFacade.map(new Object(), Base.class); + assertEquals("returned instance is not Base", Base.class, mapped.getClass()); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/optional/GuavaOptionalTestCase.java b/core/src/test/java/ma/glasnost/orika/test/optional/GuavaOptionalTestCase.java new file mode 100644 index 00000000..0b9f9845 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/optional/GuavaOptionalTestCase.java @@ -0,0 +1,66 @@ +package ma.glasnost.orika.test.optional; + +import com.google.common.base.Optional; +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.converter.builtin.GuavaOptionalConverter; +import ma.glasnost.orika.metadata.TypeFactory; +import ma.glasnost.orika.test.MappingUtil; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +public class GuavaOptionalTestCase { + + @Test + public void testMappingIgnoresEmptyOptionalInDestination() { + final String expected = "initial"; + + final Source source = new Source(); + source.setS(Optional.of(expected)); + + final Destination actual = getMapperFacade().map(source, Destination.class); + + assertEquals(expected, actual.getS().get()); + } + + @Test + public void testMappingMapEmptyToEmpty() { + final Destination actual = getMapperFacade().map(new Source(), Destination.class); + + assertFalse(actual.getS().isPresent()); + } + + private MapperFacade getMapperFacade() { + final MapperFactory mapperFactory = MappingUtil.getMapperFactory(true); + mapperFactory.getConverterFactory() + .registerConverter(new GuavaOptionalConverter<>(TypeFactory.valueOf(String.class), TypeFactory.valueOf(String.class))); + return mapperFactory.getMapperFacade(); + } + + public static class Source { + private Optional s = Optional.absent(); + + public Optional getS() { + return s; + } + + public void setS(final Optional s) { + this.s = s; + } + } + + public static class Destination { + private Optional s = Optional.absent(); + + public Optional getS() { + return s; + } + + public void setS(final Optional s) { + this.s = s; + } + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/packageprivate/PackagePrivateTestCase.java b/core/src/test/java/ma/glasnost/orika/test/packageprivate/PackagePrivateTestCase.java new file mode 100644 index 00000000..754319a0 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/packageprivate/PackagePrivateTestCase.java @@ -0,0 +1,101 @@ +package ma.glasnost.orika.test.packageprivate; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.test.MappingUtil; +import ma.glasnost.orika.test.packageprivate.otherpackage.SomePublicDto; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class PackagePrivateTestCase { + + @Test + public void testMappingPackagePrivateToPublic() { + SomePrivateEntity source = new SomePrivateEntity(); + source.setField("test value"); + + final SomePublicDto actual = getMapperFacade().map(source, SomePublicDto.class); + + assertEquals(source.getField(), actual.getField()); + } + + @Test + public void testMappingPublicToPackagePrivate() { + SomePublicDto source = new SomePublicDto(); + source.setField("test value"); + + final SomePrivateEntity actual = getMapperFacade().map(source, SomePrivateEntity.class); + + assertEquals(source.getField(), actual.getField()); + } + + @Test + public void testMappingPackagePrivateToPackagePrivate() { + SomePrivateEntity source = new SomePrivateEntity(); + source.setField("test value"); + + final SimilarEntity actual = getMapperFacade().map(source, SimilarEntity.class); + + assertEquals(source.getField(), actual.getField()); + } + + @Test + public void testGeneratedObjectFactory() { + SimilarEntityCustomConstructor source = new SimilarEntityCustomConstructor("test value"); + + final SimilarEntityCustomConstructor actual = getMapperFacade().map(source, SimilarEntityCustomConstructor.class); + + assertEquals(source.getField(), actual.getField()); + } + + @Test + public void testMappingToNestedProtected() throws Exception { + SomePublicDto source = new SomePublicDto(); + source.setField("test value"); + + final SomeParentClass.SomeProtectedClass actual = getMapperFacade().map(source, SomeParentClass.SomeProtectedClass.class); + + assertEquals(source.getField(), actual.getField()); + } + + @Test + public void testMappingFromNestedProtected() throws Exception { + SomeParentClass.SomeProtectedClass source = new SomeParentClass.SomeProtectedClass(); + source.setField("test value"); + + final SomePublicDto actual = getMapperFacade().map(source, SomePublicDto.class); + + assertEquals(source.getField(), actual.getField()); + } + + @Test + public void testPackagePrivateNestedEntities() { + NestedEntity source = new NestedEntity(); + source.setField("test value"); + + final NestedEntity actual = getMapperFacade().map(source, NestedEntity.class); + + assertEquals(source.getField(), actual.getField()); + } + + static class NestedEntity { + private String field; + + public String getField() { + return field; + } + + public void setField(String field) { + this.field = field; + } + } + + private MapperFacade getMapperFacade() { + final MapperFactory mapperFactory = MappingUtil.getMapperFactory(true); + mapperFactory.classMap(SomePrivateEntity.class, SomePublicDto.class); + mapperFactory.classMap(SomePrivateEntity.class, SimilarEntity.class); + mapperFactory.classMap(SomeParentClass.SomeProtectedClass.class, SomePublicDto.class); + return mapperFactory.getMapperFacade(); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/packageprivate/SimilarEntity.java b/core/src/test/java/ma/glasnost/orika/test/packageprivate/SimilarEntity.java new file mode 100644 index 00000000..8182ef8d --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/packageprivate/SimilarEntity.java @@ -0,0 +1,13 @@ +package ma.glasnost.orika.test.packageprivate; + +class SimilarEntity { + private String field; + + public String getField() { + return field; + } + + public void setField(String field) { + this.field = field; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/packageprivate/SimilarEntityCustomConstructor.java b/core/src/test/java/ma/glasnost/orika/test/packageprivate/SimilarEntityCustomConstructor.java new file mode 100644 index 00000000..98ce9ddb --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/packageprivate/SimilarEntityCustomConstructor.java @@ -0,0 +1,14 @@ +package ma.glasnost.orika.test.packageprivate; + +class SimilarEntityCustomConstructor { + private final String field; + + public SimilarEntityCustomConstructor(String field) { + this.field = field; + } + + public String getField() { + return field; + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/packageprivate/SomeParentClass.java b/core/src/test/java/ma/glasnost/orika/test/packageprivate/SomeParentClass.java new file mode 100644 index 00000000..2a369cd7 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/packageprivate/SomeParentClass.java @@ -0,0 +1,17 @@ +package ma.glasnost.orika.test.packageprivate; + +public class SomeParentClass { + + protected static class SomeProtectedClass { + private String field; + + public String getField() { + return field; + } + + public void setField(String field) { + this.field = field; + } + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/packageprivate/SomePrivateEntity.java b/core/src/test/java/ma/glasnost/orika/test/packageprivate/SomePrivateEntity.java new file mode 100644 index 00000000..41139862 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/packageprivate/SomePrivateEntity.java @@ -0,0 +1,13 @@ +package ma.glasnost.orika.test.packageprivate; + +class SomePrivateEntity { + private String field; + + public String getField() { + return field; + } + + public void setField(String field) { + this.field = field; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/packageprivate/otherpackage/SomePublicDto.java b/core/src/test/java/ma/glasnost/orika/test/packageprivate/otherpackage/SomePublicDto.java new file mode 100644 index 00000000..67c8ef04 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/packageprivate/otherpackage/SomePublicDto.java @@ -0,0 +1,13 @@ +package ma.glasnost.orika.test.packageprivate.otherpackage; + +public class SomePublicDto { + private String field; + + public String getField() { + return field; + } + + public void setField(String field) { + this.field = field; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/perf/ClassLoaderLeakageTestCase.java b/core/src/test/java/ma/glasnost/orika/test/perf/ClassLoaderLeakageTestCase.java new file mode 100644 index 00000000..1c0abd64 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/perf/ClassLoaderLeakageTestCase.java @@ -0,0 +1,368 @@ +///* +// * Orika - simpler, better and faster Java bean mapping +// * +// * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.perf; +// +//import ma.glasnost.orika.DefaultFieldMapper; +//import ma.glasnost.orika.MapperFacade; +//import ma.glasnost.orika.MapperFactory; +//import ma.glasnost.orika.MappingException; +//import ma.glasnost.orika.test.MappingUtil; +//import ma.glasnost.orika.test.MavenProjectUtil; +//import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.Author; +//import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.Book; +//import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.Library; +//import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.LibraryMyDTO; +//import org.junit.Assert; +//import org.junit.Test; +// +//import java.io.File; +//import java.lang.ref.SoftReference; +//import java.lang.reflect.InvocationTargetException; +//import java.util.ArrayList; +//import java.util.List; +// +///** +// * +// * This test attempts to confirm that Orika doesn't cause class-loaders to leak +// * by retaining hard references to classes that were not loaded by it's own +// * class-loader or any parent class-loader(s).
+// *
+// * This can cause problems specifically in web and enterprise application +// * contexts where multiple web application (siblings) might share a common +// * parent enterprise application (or shared library) class-loader.
+// *
+// * +// * @author mattdeboer +// * +// */ +//public class ClassLoaderLeakageTestCase { +// +// /** +// * This initial test is to verify our own sanity +// * +// * @throws Throwable +// */ +// @Test +// public void testControl() throws Throwable { +// +// File projectRoot = MavenProjectUtil.findProjectRoot(); +// +// ClassLoader threadContextLoader = Thread.currentThread() +// .getContextClassLoader(); +// +// EclipseJdtCompiler complier = new EclipseJdtCompiler( +// threadContextLoader); +// ClassLoader childLoader = complier.compile(new File(projectRoot, +// "src/main/java-hidden"), threadContextLoader); +// +// @SuppressWarnings("unchecked") +// Class hiddenAuthorType = (Class) childLoader +// .loadClass("types.AuthorHidden"); +// @SuppressWarnings("unchecked") +// Class hiddenBookType = (Class) childLoader +// .loadClass("types.BookHidden"); +// @SuppressWarnings("unchecked") +// Class hiddenLibraryType = (Class) childLoader +// .loadClass("types.LibraryHidden"); +// +// try { +// threadContextLoader.loadClass("types.LibraryHidden"); +// Assert.fail("types.LibraryHidden should not be accessible to the thread context class loader"); +// } catch (ClassNotFoundException e0) { +// try { +// threadContextLoader.loadClass("types.AuthorHidden"); +// Assert.fail("types.AuthorHidden should not be accessible to the thread context class loader"); +// } catch (ClassNotFoundException e1) { +// try { +// threadContextLoader.loadClass("types.BookHidden"); +// Assert.fail("types.BookHidden should not be accessible to the thread context class loader"); +// } catch (ClassNotFoundException e2) { +// /* good: all of these types should be inaccessible */ +// } +// } +// } +// +// // Now, these types are hidden from the current class-loader, but they +// // implement types +// // that are accessible to this loader +// // ----------------------------------------------------------------------------- +// +// Book book = createBook(hiddenBookType); +// book.setAuthor(createAuthor(hiddenAuthorType)); +// Library lib = createLibrary(hiddenLibraryType); +// lib.getBooks().add(book); +// +// SoftReference ref = new SoftReference<>( +// childLoader); +// +// book = null; +// lib = null; +// hiddenBookType = null; +// hiddenAuthorType = null; +// hiddenLibraryType = null; +// childLoader = null; +// +// Assert.assertNotNull(ref.get()); +// +// forceClearSoftAndWeakReferences(); +// +// Assert.assertNull(ref.get()); +// +// } +// +// /** +// * This test is a bit complicated: it verifies that super-type lookup occurs +// * properly if presented with a class that is not accessible from the +// * current class loader, but which extends some super-type (or implements an +// * interface) which is accessible.
+// * This type of scenario might occur in web-module to ejb jar +// * interactions... +// * +// * @throws Exception +// */ +// @Test +// public void testClassLoaderLeak() throws Exception { +// +// SoftReference childLoaderRef = null; +// +// MapperFactory factory = MappingUtil.getMapperFactory(); +// DefaultFieldMapper fieldDefault = +// /** +// * This sample hint converts "myProperty" to "property", and vis-versa. +// */ +// (fromProperty, fromPropertyType) -> { +// if (fromProperty.startsWith("my")) { +// return fromProperty.substring(2, 3).toLowerCase() +// + fromProperty.substring(3); +// } else { +// return "my" + fromProperty.substring(0, 1).toUpperCase() +// + fromProperty.substring(1); +// } +// }; +// factory.registerDefaultFieldMapper(fieldDefault); +// +// MapperFacade mapper = factory.getMapperFacade(); +// LibraryMyDTO mappedLib; +// { +// File projectRoot = MavenProjectUtil.findProjectRoot(); +// +// ClassLoader threadContextLoader = Thread.currentThread() +// .getContextClassLoader(); +// +// EclipseJdtCompiler complier = new EclipseJdtCompiler( +// threadContextLoader); +// ClassLoader childLoader = complier.compile(new File(projectRoot, +// "src/main/java-hidden"), threadContextLoader); +// +// @SuppressWarnings("unchecked") +// Class hiddenAuthorType = (Class) childLoader +// .loadClass("types.AuthorHidden"); +// @SuppressWarnings("unchecked") +// Class hiddenBookType = (Class) childLoader +// .loadClass("types.BookHidden"); +// @SuppressWarnings("unchecked") +// Class hiddenLibraryType = (Class) childLoader +// .loadClass("types.LibraryHidden"); +// +// try { +// threadContextLoader.loadClass("types.LibraryHidden"); +// Assert.fail("types.LibraryHidden should not be accessible to the thread context class loader"); +// } catch (ClassNotFoundException e0) { +// try { +// threadContextLoader.loadClass("types.AuthorHidden"); +// Assert.fail("types.AuthorHidden should not be accessible to the thread context class loader"); +// } catch (ClassNotFoundException e1) { +// try { +// threadContextLoader.loadClass("types.BookHidden"); +// Assert.fail("types.BookHidden should not be accessible to the thread context class loader"); +// } catch (ClassNotFoundException e2) { +// /* good: all of these types should be inaccessible */ +// } +// } +// } +// // Now, these types are hidden from the current class-loader, but +// // they implement types +// // that are accessible to this loader +// // ----------------------------------------------------------------------------- +// +// Book book = createBook(hiddenBookType); +// book.setAuthor(createAuthor(hiddenAuthorType)); +// Library lib = createLibrary(hiddenLibraryType); +// lib.getBooks().add(book); +// +// mappedLib = mapper.map(lib, LibraryMyDTO.class); +// +// // Just to be sure things mapped as expected +// Assert.assertEquals(lib.getTitle(), mappedLib.getMyTitle()); +// Assert.assertEquals(book.getTitle(), mappedLib.getMyBooks().get(0) +// .getMyTitle()); +// Assert.assertEquals(book.getAuthor().getName(), mappedLib +// .getMyBooks().get(0).getMyAuthor().getMyName()); +// +// // Now, set the soft reference before our hard references go out of +// // scope +// childLoaderRef = new SoftReference<>(childLoader); +// +// book = null; +// lib = null; +// hiddenBookType = null; +// hiddenAuthorType = null; +// hiddenLibraryType = null; +// childLoader = null; +// +// factory = null; +// mapper = null; +// } +// +// Assert.assertNotNull(childLoaderRef.get()); +// +// // Force GC to reclaim the soft reference +// forceClearSoftAndWeakReferences(); +// +// // Test the target group +// Assert.assertNull(childLoaderRef.get()); +// +// } +// +// /** +// * This test attempts to have a child class-loader register a class-mapping +// * using a class which is only visible to this child loader; currently, this +// * fails because Orika throws exception on finding a class which is not +// * accessible to it. +// * +// * @throws Exception +// */ +// @Test(expected = MappingException.class) +// public void testLeak_registerMapChildClasses() throws Throwable { +// +// final ClassLoader originalTccl = Thread.currentThread() +// .getContextClassLoader(); +// +// SoftReference childLoaderRef = null; +// +// MapperFactory factory = MappingUtil.getMapperFactory(); +// +// try { +// File projectRoot = MavenProjectUtil.findProjectRoot(); +// +// ClassLoader threadContextLoader = Thread.currentThread() +// .getContextClassLoader(); +// +// EclipseJdtCompiler complier = new EclipseJdtCompiler( +// threadContextLoader); +// ClassLoader childLoader = complier.compile(new File(projectRoot, +// "src/main/java-hidden"), threadContextLoader); +// +// @SuppressWarnings("unchecked") +// Class runnerType = (Class) childLoader +// .loadClass("types.Runner"); +// +// try { +// threadContextLoader.loadClass("types.Runner"); +// Assert.fail("types.Runner should not be accessible to the thread context class loader"); +// } catch (ClassNotFoundException e0) { +// try { +// threadContextLoader.loadClass("types.AuthorHidden"); +// Assert.fail("types.AuthorHidden should not be accessible to the thread context class loader"); +// } catch (ClassNotFoundException e1) { +// try { +// threadContextLoader.loadClass("types.BookHidden"); +// Assert.fail("types.BookHidden should not be accessible to the thread context class loader"); +// } catch (ClassNotFoundException e2) { +// /* good: all of these types should be inaccessible */ +// } +// } +// } +// +// /* +// * Run the mapping request for the child-loaded Runner class; +// */ +// try { +// Thread.currentThread().setContextClassLoader(childLoader); +// runnerType.getMethod("run", MapperFactory.class).invoke(null, +// factory); +// } catch (InvocationTargetException e) { +// throw e.getTargetException(); +// } +// +// // Now, set the soft reference before our hard references go out of +// // scope +// childLoaderRef = new SoftReference<>(childLoader); +// +// runnerType = null; +// childLoader = null; +// } finally { +// Thread.currentThread().setContextClassLoader(originalTccl); +// } +// +// Assert.assertNotNull(factory); +// Assert.assertNotNull(childLoaderRef.get()); +// +// // Force GC to reclaim the soft reference +// forceClearSoftAndWeakReferences(); +// +// // Test the target group +// Assert.assertNull(childLoaderRef.get()); +// +// } +// +// /** +// * Since the contract for SoftReference states that all soft references will +// * be cleared by the garbage collector before OOME is thrown, we allocate +// * dummy bytes until we reach OOME. +// */ +// private synchronized void forceClearSoftAndWeakReferences() { +// +// SoftReference checkReference = new SoftReference<>(new Object()); +// List byteBucket = new ArrayList<>(); +// try { +// for (int i = 0; i < Integer.MAX_VALUE; ++i) { +// int available = (int) Math.min((long) Integer.MAX_VALUE, Runtime.getRuntime().maxMemory()); +// byteBucket.add(new byte[available/2]); +// } +// } catch (Throwable e) { +// // Ignore OME; soft references should now have been cleared +// Assert.assertNull(checkReference.get()); +// } +// } +// +// private Author createAuthor(Class type) +// throws InstantiationException, IllegalAccessException { +// Author author = (Author) type.newInstance(); +// author.setName("Khalil Gebran"); +// +// return author; +// } +// +// private Book createBook(Class type) +// throws InstantiationException, IllegalAccessException { +// Book book = (Book) type.newInstance(); +// book.setTitle("The Prophet"); +// +// return book; +// } +// +// private Library createLibrary(Class type) +// throws InstantiationException, IllegalAccessException { +// Library lib = (Library) type.newInstance(); +// lib.setTitle("Test Library"); +// +// return lib; +// } +// +//} diff --git a/core/src/test/java/ma/glasnost/orika/test/perf/DefaultMapperFactoryGenerationConcurrencyTestCase.java b/core/src/test/java/ma/glasnost/orika/test/perf/DefaultMapperFactoryGenerationConcurrencyTestCase.java new file mode 100644 index 00000000..66107f57 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/perf/DefaultMapperFactoryGenerationConcurrencyTestCase.java @@ -0,0 +1,106 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.perf; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.metadata.ClassMap; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +public class DefaultMapperFactoryGenerationConcurrencyTestCase { + + static public class A { + + private String property; + + public String getProperty() { + return property; + } + + public void setProperty(String property) { + this.property = property; + } + } + + static public class B { + + private String property; + + public String getProperty() { + return property; + } + + public void setProperty(String property) { + this.property = property; + } + } + + private static Throwable throwable = null; + + private class ConcurrencyTestRunnable implements Runnable { + + public void run() { + try { + + + MapperFactory factory = new DefaultMapperFactory.Builder().build(); + + ClassMap classMap = factory.classMap(A.class, B.class).byDefault().toClassMap(); + + factory.registerClassMap(classMap); + + MapperFacade mapper = factory.getMapperFacade(); + + A from = new A(); + from.setProperty("test"); + mapper.map(from, B.class); + } + + catch(Exception e) { + throwable = e; + } + } + } + + + @Test + public void concurrencyTest() throws Exception { + + List threads = new ArrayList<>(); + + for(int i=0; i<50; ++i) { + threads.add(new Thread(new DefaultMapperFactoryGenerationConcurrencyTestCase.ConcurrencyTestRunnable())); + } + + for(Thread t : threads) { + t.start(); + } + + for(Thread t : threads) { + t.join(); + } + + Assert.assertNull("caught unexpected exception: " + throwable, throwable); + + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/perf/LaunchTestsForProfiler.java b/core/src/test/java/ma/glasnost/orika/test/perf/LaunchTestsForProfiler.java new file mode 100644 index 00000000..9968442e --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/perf/LaunchTestsForProfiler.java @@ -0,0 +1,61 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.perf; + +import java.io.File; +import java.io.IOException; + +import ma.glasnost.orika.test.DynamicSuite; + +import org.junit.runner.JUnitCore; + +/** + * LaunchTestsForProfiler provides a launcher for using the VisualVm (or another) + * profiler over all of the unit tests.
+ * It provides a break at the beginning pausing for input which allows + * attaching/configuring the profiler, as well as a similar pause at the + * end to allow for capturing/saving results.

+ * + * + * @author matt.deboer@gmail.com + * + */ +public class LaunchTestsForProfiler { + + public static void main(String[] args) throws IOException { + + File classFolder = new File(LaunchTestsForProfiler.class.getResource("/").getFile()); + Class[] testClasses = DynamicSuite.findTestCases(classFolder, ".*TestCase").toArray(new Class[0]); + + + System.out.println("Press enter when ready to start..."); + System.in.read(); + + /* + * Manually fire the set of test classes; this avoids having this test included when all + * test cases are run within an IDE, since this is a special case used only for profiling + */ + JUnitCore.runClasses(testClasses); + + System.out.println("Press enter when ready to quit..."); + System.in.read(); + System.in.read(); + + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/perf/MultiLayeredClassloader_IDEOnly.java b/core/src/test/java/ma/glasnost/orika/test/perf/MultiLayeredClassloader_IDEOnly.java new file mode 100644 index 00000000..d014af95 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/perf/MultiLayeredClassloader_IDEOnly.java @@ -0,0 +1,84 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.perf; + +import ma.glasnost.orika.test.MavenProjectUtil; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +import java.io.File; +import java.net.URL; +import java.net.URLClassLoader; + +/** + * @author matt.deboer@gmail.com + * + * Note: this test is named '_IDEOnly' to allow it to be skipped + * during maven tests, as it has achieved inconsistent results + * using that method. + * Until a better solution can be found, we relegate it to running only + * within the IDE. + */ +public class MultiLayeredClassloader_IDEOnly { + + /** + * @return a copy of the current thread context class-loader + */ + public static ClassLoader copyThreadContextClassLoader() { + ClassLoader cl = Thread.currentThread().getContextClassLoader(); + if (cl instanceof URLClassLoader) { + URLClassLoader ucl = (URLClassLoader)cl; + return new URLClassLoader(ucl.getURLs()); + } else { + throw new IllegalStateException("ThreadContextClassLoader is not a URLClassLoader"); + } + } + + @Rule + public TemporaryFolder temporaryFolder = new TemporaryFolder(); + + /** + * Test that Orika can be run from a nested class-loader + */ + @Test + public void nestedClassLoader() throws Exception { + File projectRoot = MavenProjectUtil.findProjectRoot(); + + final ClassLoader tccl = Thread.currentThread().getContextClassLoader(); + File tempClasses = temporaryFolder.getRoot(); + + ClassLoader childLoader = new URLClassLoader(new URL[]{tempClasses.toURI().toURL()}, + copyThreadContextClassLoader()); + + Class runnerClass = childLoader.loadClass("dtotypes.Runner"); + Object runner = runnerClass.newInstance(); + try { + Thread.currentThread().setContextClassLoader(childLoader); + + childLoader.loadClass("dtotypes.BookHiddenDto"); + childLoader.loadClass("types.BookHidden"); + + runnerClass.getMethod("test").invoke(runner); + + } finally { + Thread.currentThread().setContextClassLoader(tccl); + } + + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/perf/MultiThreadedTestCase.java b/core/src/test/java/ma/glasnost/orika/test/perf/MultiThreadedTestCase.java new file mode 100644 index 00000000..8a47c10f --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/perf/MultiThreadedTestCase.java @@ -0,0 +1,441 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.perf; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.metadata.ClassMap; +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.metadata.TypeFactory; +import ma.glasnost.orika.test.ConcurrentRule; +import ma.glasnost.orika.test.ConcurrentRule.Concurrent; +import ma.glasnost.orika.test.DynamicSuite; +import ma.glasnost.orika.test.MappingUtil; +import ma.glasnost.orika.test.common.types.TestCaseClasses.AuthorImpl; +import ma.glasnost.orika.test.common.types.TestCaseClasses.Book; +import ma.glasnost.orika.test.common.types.TestCaseClasses.BookImpl; +import ma.glasnost.orika.test.common.types.TestCaseClasses.Library; +import ma.glasnost.orika.test.common.types.TestCaseClasses.LibraryDTO; +import ma.glasnost.orika.test.common.types.TestCaseClasses.LibraryImpl; +import org.junit.Assert; +import org.junit.Rule; +import org.junit.Test; + +import java.io.File; +import java.io.UnsupportedEncodingException; +import java.lang.ref.SoftReference; +import java.net.URLDecoder; +import java.time.LocalDate; +import java.time.ZoneId; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * @author matt.deboer@gmail.com + * + */ +public class MultiThreadedTestCase { + + private static final boolean IS_IBM_JDK = (""+System.getProperty("java.vendor")).toUpperCase().contains("IBM"); + + /** + * Allows us to run methods concurrently by marking with + * @Concurrent; note that in the current implementation, such + * methods will have the @Before and @After + * methods also invoked concurrently. + */ + @Rule + public ConcurrentRule concurrentRule = new ConcurrentRule(); + + private final Set> classes = getNonAnonymousClasses(); + + private final MapperFacade mapper = MappingUtil.getMapperFactory().getMapperFacade(); + + private static Set> getNonAnonymousClasses() { + Set> classes = new HashSet<>(); + File classFolder; + try { + classFolder = new File(URLDecoder.decode(MultiThreadedTestCase.class.getResource("/").getFile(), "UTF-8")); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + List> allClasses = DynamicSuite.findTestCases(classFolder, ".*"); + for (Class aClass : allClasses) { + if (!aClass.isAnonymousClass()) { + classes.add(aClass); + } + } + return classes; + } + + private final AtomicInteger threadIndex = new AtomicInteger(0); + private final Type[] typeResults = new Type[15]; + private final CountDownLatch finishLine = new CountDownLatch(15); + + @Test + @Concurrent(15) + public void testDefineSingleTypeSimultaneously() throws InterruptedException { + + int myIndex = threadIndex.getAndAdd(1); + typeResults[myIndex] = TypeFactory.valueOf(Integer.class); + + finishLine.countDown(); + + finishLine.await(); + + Type firstType = typeResults[0]; + for (Type type : typeResults) { + Assert.assertEquals(firstType, type); + } + } + + AtomicInteger myIndex = new AtomicInteger(); + + /** + * Verifies that multiple threads requesting the type for the same set of + * classes receive the same set of values over a large number of classes. + */ + @Test + @Concurrent(25) + public void testDefineTypesSimultaneously() { + + int i = myIndex.getAndIncrement(); + int c = 0; + Map, Class> types = new HashMap<>(); + for (Class aClass : classes) { + + /* + * In this section, we force each of the threads to trigger a GC at + * some point in mid process; this should help shake out any issues + * with weak references getting cleared (that we didn't expect to be + * cleared). + */ + ++c; + Type aType; + try { + aType = TypeFactory.valueOf(aClass); + } catch (StackOverflowError e) { + throw new RuntimeException("while trying to evaluate valueOf(" + aClass.getCanonicalName() + ")", e); + } + if (aType == null) { + throw new IllegalStateException("TypeFactory.valueOf() returned null for " + aClass); + } else if (types.containsKey(aType)) { + throw new IllegalStateException("mapping already exists for " + aClass + ": " + aType + " = " + types.get(aType)); + } else { + if (aClass.isAssignableFrom(aType.getRawType())) { + types.put(aType, aClass); + } else { + throw new IllegalStateException(aType + " is not an instance of " + aClass); + } + } + if (c == i) { + forceClearSoftAndWeakReferences(); + } + } + + Assert.assertEquals(classes.size(), types.size()); + } + + @Test + @Concurrent(20) + public void testGenerateMappers() { + BookImpl book = new BookImpl("The Book Title", new AuthorImpl("The Author Name")); + Library lib = new LibraryImpl("The Library", Arrays. asList(book)); + + LibraryDTO mappedLib = mapper.map(lib, LibraryDTO.class); + + // Just to be sure things mapped as expected + Assert.assertEquals(lib.getTitle(), mappedLib.getTitle()); + Assert.assertEquals(book.getTitle(), mappedLib.getBooks().get(0).getTitle()); + Assert.assertEquals(book.getAuthor().getName(), mappedLib.getBooks().get(0).getAuthor().getName()); + + Library mapBack = mapper.map(mappedLib, Library.class); + Assert.assertEquals(lib, mapBack); + } + + @Test + @Concurrent(20) + public void testGenerateObjectFactories() { + + Person person = new Person(); + person.setFirstName("Abdelkrim"); + person.setLastName("EL KHETTABI"); + LocalDate birthDate = LocalDate.now().minusYears(31); + Date date = Date.from(birthDate.atStartOfDay(ZoneId.systemDefault()).toInstant()); + + + person.setDateOfBirth(date); + person.setAge(31L); + + PersonVO vo = mapper.map(person, PersonVO.class); + + Assert.assertEquals(person.getFirstName(), vo.getFirstName()); + Assert.assertEquals(person.getLastName(), vo.getLastName()); + Assert.assertTrue(person.getAge() == vo.getAge()); + Assert.assertEquals(date, vo.getDateOfBirth()); + + Person mapBack = mapper.map(vo, Person.class); + Assert.assertEquals(person, mapBack); + } + + @Test + @Concurrent(20) + public void generateAll() { + testGenerateMappers(); + testGenerateObjectFactories(); + } + + private final MapperFactory factory = new DefaultMapperFactory.Builder().build(); + + @Test + @Concurrent(50) + public void testGetMapperFacade() { + + ClassMap classMap = factory.classMap(A.class, B.class).byDefault().toClassMap(); + + factory.registerClassMap(classMap); + MapperFacade mapper = factory.getMapperFacade(); + + A from = new A(); + from.setProperty("test"); + B to = mapper.map(from, B.class); + } + + @Test + @Concurrent(50) + public void testBuildMapper() { + + MapperFactory factory = new DefaultMapperFactory.Builder().build(); + ClassMap classMap = factory.classMap(A.class, B.class).byDefault().toClassMap(); + + factory.registerClassMap(classMap); + MapperFacade mapper = factory.getMapperFacade(); + } + + + public static class Person { + private String firstName; + private String lastName; + + private Long age; + private Date date; + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public Long getAge() { + return age; + } + + public void setAge(Long age) { + this.age = age; + } + + public Date getDateOfBirth() { + return date; + } + + public void setDateOfBirth(Date date) { + this.date = date; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((age == null) ? 0 : age.hashCode()); + result = prime * result + ((date == null) ? 0 : date.hashCode()); + result = prime * result + ((firstName == null) ? 0 : firstName.hashCode()); + result = prime * result + ((lastName == null) ? 0 : lastName.hashCode()); + return result; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Person other = (Person) obj; + if (age == null) { + if (other.age != null) + return false; + } else if (!age.equals(other.age)) + return false; + if (date == null) { + if (other.date != null) + return false; + } else if (!date.equals(other.date)) + return false; + if (firstName == null) { + if (other.firstName != null) + return false; + } else if (!firstName.equals(other.firstName)) + return false; + if (lastName == null) { + if (other.lastName != null) + return false; + } else if (!lastName.equals(other.lastName)) + return false; + return true; + } + + } + + public static class PersonVO { + private final String firstName; + private final String lastName; + + private final long age; + private final Date dateOfBirth; + + public PersonVO(String firstName, String lastName, long age, Date dateOfBirth) { + this.firstName = firstName; + this.lastName = lastName; + this.age = age; + this.dateOfBirth = dateOfBirth; + } + + public String getFirstName() { + return firstName; + } + + public String getLastName() { + return lastName; + } + + public long getAge() { + return age; + } + + public Date getDateOfBirth() { + return dateOfBirth; + } + } + + /** + * Since the contract for SoftReference states that all soft references will + * be cleared by the garbage collector before OOME is thrown, we allocate + * dummy bytes until we reach OOME. + * TODO: this doesn't work on IBM Jdk, as it propagates the OOME to all + * threads, including the one running our test! + */ + private void forceClearSoftAndWeakReferences() { + + if (IS_IBM_JDK) { + synchronized(this) { + SoftReference checkReference = new SoftReference<>(new Object()); + List byteBucket = new ArrayList<>(); + try { + for (int i = 0; i < Integer.MAX_VALUE; ++i) { + int available = (int) Math.min((long) Integer.MAX_VALUE, Runtime.getRuntime().maxMemory()); + byteBucket.add(new byte[available]); + if (checkReference.get() == null) { + break; + } + } + } catch (Throwable e) { + byteBucket = null; + // Ignore OME; soft references should now have been cleared + Assert.assertNull(checkReference.get()); + // Must explicitly tell IBM jdk to gc here, or it will not reap the released + // memory in time + Runtime.getRuntime().gc(); + } + } + } else { + SoftReference checkReference = new SoftReference<>(new Object()); + List byteBucket = new ArrayList<>(); + try { + for (int i = 0; i < Integer.MAX_VALUE; ++i) { + int available = (int) Math.min((long) Integer.MAX_VALUE, Runtime.getRuntime().maxMemory()); + // 8 bytes for the array header, 4 bytes for the length + if (available > 12) { + available -= 12; + } + byteBucket.add(new byte[available]); + } + } catch (Throwable e) { + // Ignore OME; soft references should now have been cleared + Assert.assertNull(checkReference.get()); + } + } + + } + + static public class A { + + private String property; + + public String getProperty() { + return property; + } + + public void setProperty(String property) { + this.property = property; + } + } + + static public class B { + + private String property; + + public String getProperty() { + return property; + } + + public void setProperty(String property) { + this.property = property; + } + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/primitives/BigDecimalPrimitiveTestCase.java b/core/src/test/java/ma/glasnost/orika/test/primitives/BigDecimalPrimitiveTestCase.java new file mode 100644 index 00000000..2e8cd5f3 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/primitives/BigDecimalPrimitiveTestCase.java @@ -0,0 +1,78 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.primitives; + +import ma.glasnost.orika.CustomConverter; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.test.MappingUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.math.BigDecimal; + +public class BigDecimalPrimitiveTestCase { + + @Test + public void shouldMapBigDecimalToPrimtiveDouble() { + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.getConverterFactory().registerConverter(new CustomConverter() { + + public Double convert(BigDecimal source, Type destinationType, MappingContext context) { + return source.doubleValue(); + } + + }); + + A source = new A(); + source.setValue(BigDecimal.TEN); + B dest = factory.getMapperFacade().map(source, B.class); + + Assert.assertEquals(new Double(10), (Double) dest.getValue()); + + } + + public static class A { + private BigDecimal value; + + public BigDecimal getValue() { + return value; + } + + public void setValue(BigDecimal value) { + this.value = value; + } + + } + + public static class B { + private double value; + + public double getValue() { + return value; + } + + public void setValue(double value) { + this.value = value; + } + + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/primitives/BooleanTestCase.java b/core/src/test/java/ma/glasnost/orika/test/primitives/BooleanTestCase.java new file mode 100644 index 00000000..a45802f0 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/primitives/BooleanTestCase.java @@ -0,0 +1,88 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.primitives; + +import org.junit.Assert; +import org.junit.Test; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.test.MappingUtil; + +public class BooleanTestCase { + + @Test + public void testPrimtiveToWrapper() { + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.classMap(Primitive.class, Wrapper.class).field("primitive", "wrapper").register(); + + MapperFacade mapper = factory.getMapperFacade(); + + Wrapper source = new Wrapper(); + source.setWrapper(true); + + Primitive destination = mapper.map(source, Primitive.class); + Assert.assertEquals(Boolean.TRUE, destination.isPrimitive()); + + } + + @Test + public void testWrapperToPrimtive() { + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.classMap(Wrapper.class, Primitive.class).field("wrapper", "primitive").register(); + + MapperFacade mapper = factory.getMapperFacade(); + + Primitive source = new Primitive(); + source.setPrimitive(true); + + Wrapper destination = mapper.map(source, Wrapper.class); + Assert.assertEquals(true, destination.getWrapper()); + + } + + public static class Primitive { + private boolean primitive; + + public boolean isPrimitive() { + return primitive; + } + + public void setPrimitive(boolean primitive) { + this.primitive = primitive; + } + } + + public static class Wrapper { + + private Boolean wrapper; + + public Boolean getWrapper() { + return wrapper; + } + + public void setWrapper(Boolean wrapper) { + this.wrapper = wrapper; + } + + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/primitives/PrimitivesTestCase.java b/core/src/test/java/ma/glasnost/orika/test/primitives/PrimitivesTestCase.java new file mode 100644 index 00000000..712b9b2c --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/primitives/PrimitivesTestCase.java @@ -0,0 +1,418 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.primitives; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.test.MappingUtil; +import org.junit.Assert; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class PrimitivesTestCase { + + @Test + public void testPrimitivesToWrapper() { + MapperFactory factory = MappingUtil.getMapperFactory(); + MapperFacade mapper = factory.getMapperFacade(); + + PrimitiveAttributes source = new PrimitiveAttributes(); + + source.setAge(27); + source.setShortValue((short)27); + source.setFloatValue(2.5f); + source.setDoubleValue(22.4567d); + source.setLongValue(System.currentTimeMillis()); + source.setName("PPPPP"); + source.setSex('H'); + source.setVip(true); + + WrapperAttributes destination = mapper.map(source, WrapperAttributes.class); + + Assert.assertEquals(Integer.valueOf(source.getAge()), destination.getAge()); + Assert.assertEquals(source.getName(), destination.getName()); + Assert.assertEquals(Character.valueOf(source.getSex()), destination.getSex()); + Assert.assertEquals(source.getVip(), destination.getVip()); + Assert.assertEquals(Short.valueOf(source.getShortValue()), destination.getShortValue()); + Assert.assertEquals(Long.valueOf(source.getLongValue()), destination.getLongValue()); + Assert.assertEquals(Float.valueOf(source.getFloatValue()), destination.getFloatValue()); + Assert.assertEquals(Double.valueOf(source.getDoubleValue()), destination.getDoubleValue()); + + } + + @Test + public void testWrapperToPrimitives() { + MapperFactory factory = MappingUtil.getMapperFactory(); + MapperFacade mapper = factory.getMapperFacade(); + + WrapperAttributes source = new WrapperAttributes(); + + source.setAge(27); + source.setShortValue((short)27); + source.setFloatValue(2.5f); + source.setDoubleValue(22.4567d); + source.setLongValue(System.currentTimeMillis()); + source.setName("PPPPP"); + source.setSex('H'); + source.setVip(true); + + PrimitiveAttributes destination = mapper.map(source, PrimitiveAttributes.class); + + Assert.assertEquals(source.getAge(), Integer.valueOf(destination.getAge())); + Assert.assertEquals(source.getName(), destination.getName()); + Assert.assertEquals(source.getSex(), Character.valueOf(destination.getSex())); + Assert.assertEquals(source.getVip(), destination.getVip()); + Assert.assertEquals(source.getShortValue(), Short.valueOf(destination.getShortValue())); + Assert.assertEquals(source.getLongValue(), Long.valueOf(destination.getLongValue())); + Assert.assertEquals(source.getFloatValue(), Float.valueOf(destination.getFloatValue())); + Assert.assertEquals(source.getDoubleValue(), Double.valueOf(destination.getDoubleValue())); + + } + + @Test + public void testWrapperToWrapper() { + MapperFactory factory = MappingUtil.getMapperFactory(); + MapperFacade mapper = factory.getMapperFacade(); + + WrapperAttributes source = new WrapperAttributes(); + + source.setAge(27); + source.setShortValue((short)27); + source.setFloatValue(2.5f); + source.setDoubleValue(22.4567d); + source.setLongValue(System.currentTimeMillis()); + source.setName("PPPPP"); + source.setSex('H'); + source.setVip(true); + + OtherWrapperAttributes destination = mapper.map(source, OtherWrapperAttributes.class); + + Assert.assertEquals(source.getAge(), destination.getAge()); + Assert.assertEquals(source.getName(), destination.getName()); + Assert.assertEquals(source.getSex(), destination.getSex()); + Assert.assertEquals(source.getVip(), destination.getVip()); + Assert.assertEquals(source.getShortValue(), destination.getShortValue()); + Assert.assertEquals(source.getLongValue(), destination.getLongValue()); + Assert.assertEquals(source.getFloatValue(), destination.getFloatValue()); + Assert.assertEquals(source.getDoubleValue(), destination.getDoubleValue()); + + } + + + @Test + public void int_short() { + ShortHolder source = new ShortHolder(); + source.value = 2; + + MapperFactory factory = MappingUtil.getMapperFactory(); + MapperFacade mapper = factory.getMapperFacade(); + + IntHolder dest = mapper.map(source, IntHolder.class); + assertEquals(source.value, dest.value); + + ShortHolder mapBack = mapper.map(dest, ShortHolder.class); + assertEquals(source.value, mapBack.value); + } + + @Test + public void long_short() { + ShortHolder source = new ShortHolder(); + source.value = 2; + + MapperFactory factory = MappingUtil.getMapperFactory(); + MapperFacade mapper = factory.getMapperFacade(); + + LongHolder dest = mapper.map(source, LongHolder.class); + assertEquals(source.value, dest.value); + + ShortHolder mapBack = mapper.map(dest, ShortHolder.class); + assertEquals(source.value, mapBack.value); + } + + @Test + public void long_int() { + IntHolder source = new IntHolder(); + source.value = 2; + + MapperFactory factory = MappingUtil.getMapperFactory(); + MapperFacade mapper = factory.getMapperFacade(); + + LongHolder dest = mapper.map(source, LongHolder.class); + assertEquals(source.value, dest.value); + + IntHolder mapBack = mapper.map(dest, IntHolder.class); + assertEquals(source.value, mapBack.value); + } + + + public static class IntHolder { + public int value; + } + + public static class ShortHolder { + public short value; + } + + public static class LongHolder { + public long value; + } + + public static class FloatHolder { + public float value; + } + + public static class DoubleHolder { + public double value; + } + + public static class CharHolder { + public char value; + } + + public static class PrimitiveAttributes { + private int age; + private short shortValue; + private long longValue; + private float floatValue; + private double doubleValue; + private String name; + private char sex; + private boolean vip; + + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public char getSex() { + return sex; + } + + public void setSex(char sex) { + this.sex = sex; + } + + public boolean getVip() { + return vip; + } + + public void setVip(boolean vip) { + this.vip = vip; + } + + public short getShortValue() { + return shortValue; + } + + public void setShortValue(short shortValue) { + this.shortValue = shortValue; + } + + public long getLongValue() { + return longValue; + } + + public void setLongValue(long longValue) { + this.longValue = longValue; + } + + public float getFloatValue() { + return floatValue; + } + + public void setFloatValue(float floatValue) { + this.floatValue = floatValue; + } + + public double getDoubleValue() { + return doubleValue; + } + + public void setDoubleValue(double doubleValue) { + this.doubleValue = doubleValue; + } + + } + + public static class WrapperAttributes { + private Integer age; + private Short shortValue; + private Long longValue; + private Float floatValue; + private Double doubleValue; + private String name; + private Character sex; + private Boolean vip; + + public Integer getAge() { + return age; + } + + public void setAge(Integer age) { + this.age = age; + } + + public String getName() { + return name; + } + + public void setName(String nom) { + this.name = nom; + } + + public Character getSex() { + return sex; + } + + public void setSex(Character sex) { + this.sex = sex; + } + + public Boolean getVip() { + return vip; + } + + public void setVip(Boolean vip) { + this.vip = vip; + } + + public Short getShortValue() { + return shortValue; + } + + public void setShortValue(Short shortValue) { + this.shortValue = shortValue; + } + + public Long getLongValue() { + return longValue; + } + + public void setLongValue(Long longValue) { + this.longValue = longValue; + } + + public Float getFloatValue() { + return floatValue; + } + + public void setFloatValue(Float floatValue) { + this.floatValue = floatValue; + } + + public Double getDoubleValue() { + return doubleValue; + } + + public void setDoubleValue(Double doubleValue) { + this.doubleValue = doubleValue; + } + + } + + public static class OtherWrapperAttributes { + private Integer age; + private Short shortValue; + private Long longValue; + private Float floatValue; + private Double doubleValue; + private String name; + private Character sex; + private Boolean vip; + + public Integer getAge() { + return age; + } + + public void setAge(Integer age) { + this.age = age; + } + + public String getName() { + return name; + } + + public void setName(String nom) { + this.name = nom; + } + + public Character getSex() { + return sex; + } + + public void setSex(Character sex) { + this.sex = sex; + } + + public Boolean getVip() { + return vip; + } + + public void setVip(Boolean vip) { + this.vip = vip; + } + + public Short getShortValue() { + return shortValue; + } + + public void setShortValue(Short shortValue) { + this.shortValue = shortValue; + } + + public Long getLongValue() { + return longValue; + } + + public void setLongValue(Long longValue) { + this.longValue = longValue; + } + + public Float getFloatValue() { + return floatValue; + } + + public void setFloatValue(Float floatValue) { + this.floatValue = floatValue; + } + + public Double getDoubleValue() { + return doubleValue; + } + + public void setDoubleValue(Double doubleValue) { + this.doubleValue = doubleValue; + } + + + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/property/IntrospectorResolverTestCase.java b/core/src/test/java/ma/glasnost/orika/test/property/IntrospectorResolverTestCase.java new file mode 100644 index 00000000..cb71072a --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/property/IntrospectorResolverTestCase.java @@ -0,0 +1,279 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.property; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.metadata.NestedProperty; +import ma.glasnost.orika.metadata.Property; +import ma.glasnost.orika.property.IntrospectorPropertyResolver; +import ma.glasnost.orika.property.PropertyResolverStrategy; +import ma.glasnost.orika.test.MappingUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.math.BigDecimal; +import java.util.Map; + +public class IntrospectorResolverTestCase { + + private final PropertyResolverStrategy propertyResolver = new IntrospectorPropertyResolver(); + + @Test + public void testNestedProperty() { + String np = "start.x"; + + NestedProperty p = (NestedProperty) propertyResolver.getProperty(Line.class, np); + + Assert.assertEquals(Integer.TYPE, p.getRawType()); + } + + @Test + public void testGetInvalidNestedProperty() { + String np = "bogus.x"; + + try { + propertyResolver.getProperty(Line.class, np); + } catch (RuntimeException e) { + Assert.assertTrue(e.getMessage().contains("could not resolve nested property [" + np + "]")); + } + } + + @Test + public void testBooleanMapping() { + SpecialCase sc = new SpecialCase(); + sc.setChecked(true); + sc.totalCost = new BigDecimal("42.50"); + + MapperFacade mapper = MappingUtil.getMapperFactory().getMapperFacade(); + SpecialCaseDto dto = mapper.map(sc, SpecialCaseDto.class); + + Assert.assertEquals(sc.isChecked(), dto.isChecked()); + //Assert.assertEquals(sc.totalCost.doubleValue(), dto.getTotalCost(), 0.01d); + } + + @Test + public void testOverridePropertyDefinition() { + + Map properties = propertyResolver.getProperties(PostalAddress.class); + Property city = properties.get("city"); + + Assert.assertNotNull(city.getSetter()); + } + + @Test + public void testExcludeTransient() { + + /* Test include */ + PropertyResolverStrategy resolver = new IntrospectorPropertyResolver(false, true); + Map props = resolver.getProperties(TransientContainer.class); + Assert.assertTrue(props.containsKey("trans")); + + resolver = new IntrospectorPropertyResolver(false); + props = resolver.getProperties(TransientContainer.class); + Assert.assertTrue(props.containsKey("trans")); + + /* Test exclude not functional pre java 7 */ + //resolver = new IntrospectorPropertyResolver(false, false); + //props = resolver.getProperties(TransientContainer.class); + //Assert.assertFalse(props.containsKey("trans")); + } + + public static class TransientContainer { + private String nonTrans; + private String trans; + + public String getNonTrans() { + return nonTrans; + } + + public void setNonTrans(String nonTrans) { + this.nonTrans = nonTrans; + } + + //@java.beans.Transient + public String getTrans() { + return trans; + } + + public void setTrans(String trans) { + this.trans = trans; + } + } + + public static class Point { + private int x, y; + + public int getX() { + return x; + } + + public void setX(int x) { + this.x = x; + } + + public int getY() { + return y; + } + + public void setY(int y) { + this.y = y; + } + } + + public static class Line { + private Point start; + private Point end; + + public Point getStart() { + return start; + } + + public void setStart(Point start) { + this.start = start; + } + + public Point getEnd() { + return end; + } + + public void setEnd(Point end) { + this.end = end; + } + } + + public static class LineDTO { + private int x0, y0, x1, y1; + + public int getX0() { + return x0; + } + + public void setX0(int x0) { + this.x0 = x0; + } + + public int getY0() { + return y0; + } + + public void setY0(int y0) { + this.y0 = y0; + } + + public int getX1() { + return x1; + } + + public void setX1(int x1) { + this.x1 = x1; + } + + public int getY1() { + return y1; + } + + public void setY1(int y1) { + this.y1 = y1; + } + + } + + public static class SpecialCase { + + private Boolean checked; + public BigDecimal totalCost; + + + public Boolean isChecked() { + return checked; + } + + public void setChecked(Boolean checked) { + this.checked = checked; + } + } + + public static class SpecialCaseDto { + + private boolean checked; + private double totalCost; + + public boolean isChecked() { + return checked; + } + public void setChecked(boolean checked) { + this.checked = checked; + } + public double getTotalCost() { + return totalCost; + } + public void setTotalCost(double totalCost) { + this.totalCost = totalCost; + } + } + + public interface Address { + String getStreet(); + String getCity(); + String getSubnational(); + String getPostalCode(); + String getCountry(); + } + + public static class PostalAddress implements Address { + + private String street; + private String city; + private String subnational; + private String postalCode; + private String country; + public String getStreet() { + return street; + } + public void setStreet(String street) { + this.street = street; + } + public String getCity() { + return city; + } + public void setCity(String city) { + this.city = city; + } + public String getSubnational() { + return subnational; + } + public void setSubnational(String subnational) { + this.subnational = subnational; + } + public String getPostalCode() { + return postalCode; + } + public void setPostalCode(String postalCode) { + this.postalCode = postalCode; + } + public String getCountry() { + return country; + } + public void setCountry(String country) { + this.country = country; + } + } + + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/property/PropertyResolverTestCase.java b/core/src/test/java/ma/glasnost/orika/test/property/PropertyResolverTestCase.java new file mode 100644 index 00000000..da0f9d2b --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/property/PropertyResolverTestCase.java @@ -0,0 +1,865 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.property; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.metadata.ClassMapBuilder; +import ma.glasnost.orika.metadata.NestedProperty; +import ma.glasnost.orika.metadata.Property; +import ma.glasnost.orika.metadata.Type; +import ma.glasnost.orika.metadata.TypeBuilder; +import ma.glasnost.orika.metadata.TypeFactory; +import ma.glasnost.orika.property.IntrospectorPropertyResolver; +import ma.glasnost.orika.property.PropertyResolverStrategy; +import ma.glasnost.orika.test.MappingUtil; +import ma.glasnost.orika.test.property.TestCaseClasses.A; +import ma.glasnost.orika.test.property.TestCaseClasses.B; +import ma.glasnost.orika.test.property.TestCaseClasses.Name; +import ma.glasnost.orika.test.property.TestCaseClasses.Student; +import org.junit.Assert; +import org.junit.Test; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class PropertyResolverTestCase { + + /** + * Extend resolver, make methods public for ease of testing + * + */ + private static class TestResolverStrategy extends IntrospectorPropertyResolver { + + public boolean hasTypeParameters(Class type) { + return super.hasTypeParameters(type); + } + + public boolean isNestedPropertyExpression(String expression) { + return super.isNestedPropertyExpression(expression); + } + + public boolean isElementPropertyExpression(String expression) { + return super.isElementPropertyExpression(expression); + } + + public boolean isIndividualElementExpression(String expression) { + return super.isIndividualElementExpression(expression); + } + + public String[] splitNestedProperty(String propertyName) { + return super.splitNestedProperty(propertyName); + } + + public String[] splitElementProperty(String propertyName) { + return super.splitElementProperty(propertyName); + } + + public boolean isInlinePropertyExpression(String expression) { + return super.isInlinePropertyExpression(expression); + } + + } + + private final TestResolverStrategy propertyResolver = new TestResolverStrategy(); + + @Test + public void testNestedProperty() { + String np = "start.x"; + + NestedProperty p = (NestedProperty) propertyResolver.getProperty(Line.class, np); + Assert.assertEquals(Integer.TYPE, p.getRawType()); + p = (NestedProperty) propertyResolver.getProperty(Student.class, "favoriteBook.author.name"); + + Assert.assertEquals(String.class, p.getRawType()); + } + + @Test + public void testGetInvalidNestedProperty() { + String np = "bogus.x"; + + try { + propertyResolver.getProperty(Line.class, np); + } catch (RuntimeException e) { + Assert.assertTrue(e.getMessage().contains("could not resolve nested property [" + np + "]")); + } + } + + @Test + public void testIsNestedProperty() { + Assert.assertTrue(propertyResolver.isNestedPropertyExpression("a.b")); + Assert.assertTrue(propertyResolver.isNestedPropertyExpression("a[1].b")); + Assert.assertFalse(propertyResolver.isNestedPropertyExpression("a['b']")); + + String inlineProp1 = "points:{getAttribute('points')|setAttribute('points', %s)|type=ma.glasnost.orika.test.property.PropertyResolverTestCase.Point}"; + Assert.assertFalse(propertyResolver.isNestedPropertyExpression(inlineProp1)); + Assert.assertTrue(propertyResolver.isNestedPropertyExpression(inlineProp1 + ".b")); + + String inlineProp2 = "points:{getAttribute('points')|setAttribute('points', %s)|type=List}"; + Assert.assertFalse(propertyResolver.isNestedPropertyExpression(inlineProp2)); + Assert.assertTrue(propertyResolver.isNestedPropertyExpression(inlineProp2 + ".b")); + + } + + + @Test + public void testBooleanMapping() { + SpecialCase sc = new SpecialCase(); + sc.setChecked(true); + sc.totalCost = new BigDecimal("42.50"); + + MapperFacade mapper = MappingUtil.getMapperFactory().getMapperFacade(); + SpecialCaseDto dto = mapper.map(sc, SpecialCaseDto.class); + + Assert.assertEquals(sc.isChecked(), dto.isChecked()); + //Assert.assertEquals(sc.totalCost.doubleValue(), dto.getTotalCost(), 0.01d); + } + + @Test + public void testOverridePropertyDefinition() { + + Map properties = propertyResolver.getProperties(PostalAddress.class); + Property city = properties.get("city"); + + Assert.assertNotNull(city.getSetter()); + } + + @Test + public void testAdHocResolution() { + + Property prop = propertyResolver.getProperty(A.class, "name:{readTheNameForThisBean|assignTheName}.firstName"); + + Assert.assertNotNull(prop); + Assert.assertEquals("firstName", prop.getName()); + Assert.assertEquals("name.firstName", prop.getExpression()); + Assert.assertEquals(TypeFactory.valueOf(String.class), prop.getType()); + } + + @Test + public void testAdHocResolutionGetterOnly() { + + Property prop = propertyResolver.getProperty(A.class, "name:{readTheNameForThisBean}.firstName"); + + Assert.assertNotNull(prop); + Assert.assertEquals("firstName", prop.getName()); + Assert.assertEquals("name.firstName", prop.getExpression()); + Assert.assertEquals(TypeFactory.valueOf(String.class), prop.getType()); + } + + @Test + public void testAdHocResolutionSetterOnly() { + + Property prop = propertyResolver.getProperty(A.class, "name:{|assignTheName}.firstName"); + + Assert.assertNotNull(prop); + Assert.assertEquals("firstName", prop.getName()); + Assert.assertEquals("name.firstName", prop.getExpression()); + Assert.assertEquals(TypeFactory.valueOf(String.class), prop.getType()); + } + + @Test + public void testAdHocResolution_withType() { + + Property prop = propertyResolver.getProperty(A.class, "name:{readTheNameForThisBean|assignTheName|type=ma.glasnost.orika.test.property.TestCaseClasses$Name}.firstName"); + + Assert.assertNotNull(prop); + Assert.assertEquals("firstName", prop.getName()); + Assert.assertEquals("name.firstName", prop.getExpression()); + Assert.assertEquals(TypeFactory.valueOf(String.class), prop.getType()); + } + + @Test + public void testAdHocResolutionGetterOnly_withType() { + + Property prop = propertyResolver.getProperty(A.class, "name:{readTheNameForThisBean|type=ma.glasnost.orika.test.property.TestCaseClasses$Name}.firstName"); + + Assert.assertNotNull(prop); + Assert.assertEquals("firstName", prop.getName()); + Assert.assertEquals("name.firstName", prop.getExpression()); + Assert.assertEquals(TypeFactory.valueOf(String.class), prop.getType()); + } + + @Test + public void testAdHocResolutionSetterOnly_withType() { + + Property prop = propertyResolver.getProperty(A.class, "name:{|assignTheName|type=ma.glasnost.orika.test.property.TestCaseClasses$Name}.firstName"); + + Assert.assertNotNull(prop); + Assert.assertEquals("firstName", prop.getName()); + Assert.assertEquals("name.firstName", prop.getExpression()); + Assert.assertEquals(TypeFactory.valueOf(String.class), prop.getType()); + } + + + /** + * This test confirms that ad-hoc properties can be defined in-line within field mapping + * expressions + */ + @Test + public void testAdHocResolution_integration() { + + MapperFactory factory = new DefaultMapperFactory.Builder().build(); + factory.registerClassMap( + factory.classMap(A.class, B.class) + .field("name:{readTheNameForThisBean|assignTheName}.firstName", "givenName") + .field("name:{readTheNameForThisBean|assignTheName}.lastName", "sirName") + .field("address.city", "city") + .field("address.street", "street") + .field("address.postalCode", "postalCode") + .field("address.country", "country") + ); + + + MapperFacade mapper = factory.getMapperFacade(); + + A a = new A(); + Name name = new Name(); + name.setFirstName("Albert"); + name.setLastName("Einstein"); + a.assignTheName(name); + ma.glasnost.orika.test.property.TestCaseClasses.Address address = new ma.glasnost.orika.test.property.TestCaseClasses.Address(); + address.city = "Somewhere"; + address.country = "Germany"; + address.postalCode = "A1234FG"; + address.street = "1234 Easy St."; + a.setAddress(address); + + + B b = mapper.map(a, B.class); + + Assert.assertNotNull(b); + + A mapBack = mapper.map(b, A.class); + + Assert.assertEquals(a, mapBack); + + } + + /** + * This test case verifies that an ad-hoc property definition can be reused so + * that it doesn't have to be repeated in subsequent lines + */ + @Test + public void testAdHocResolution_integration_reuseName() { + + MapperFactory factory = new DefaultMapperFactory.Builder().build(); + factory.registerClassMap( + factory.classMap(A.class, B.class) + .field("name:{readTheNameForThisBean|assignTheName}.firstName", "givenName") + .field("name.lastName", "sirName") + .field("address.city", "city") + .field("address.street", "street") + .field("address.postalCode", "postalCode") + .field("address.country", "country") + ); + + + MapperFacade mapper = factory.getMapperFacade(); + + A a = new A(); + Name name = new Name(); + name.setFirstName("Albert"); + name.setLastName("Einstein"); + a.assignTheName(name); + ma.glasnost.orika.test.property.TestCaseClasses.Address address = new ma.glasnost.orika.test.property.TestCaseClasses.Address(); + address.city = "Somewhere"; + address.country = "Germany"; + address.postalCode = "A1234FG"; + address.street = "1234 Easy St."; + a.setAddress(address); + + + B b = mapper.map(a, B.class); + + Assert.assertNotNull(b); + + A mapBack = mapper.map(b, A.class); + + Assert.assertEquals(a, mapBack); + + } + + /** + * This test case verifies that properties can be added through a programmatic + * builder interface, explicitly defining the properties using the programming API. + */ + @Test + public void testAdHocResolution_integration_programmaticPropertyBuilder() { + + MapperFactory factory = MappingUtil.getMapperFactory(); + + ClassMapBuilder builder = factory.classMap(Element.class, PersonDto.class); + + { + Property.Builder employment = + Property.Builder.propertyFor(Element.class, "employment") + .type(Element.class) + .getter("getAttribute(\"employment\")") + .setter("setAttribute(\"employment\", %s)"); + + + builder.field(employment.nestedProperty("jobTitle") + .type(new TypeBuilder>(){}.build()) + .getter("getAttribute(\"jobTitle\")") + .setter("setAttribute(\"jobTitle\", %s)") + , "jobTitles"); + + + builder.field(employment.nestedProperty("salary") + .type(Long.class) + .getter("getAttribute(\"salary\")") + .setter("setAttribute(\"salary\", %s)") + , "salary"); + + + Property.Builder name = + Property.Builder.propertyFor(Element.class, "name") + .type(Element.class) + .getter("getAttribute(\"name\")") + .setter("setAttribute(\"name\", %s)"); + + + builder.field(name.nestedProperty("first") + .type(String.class) + .getter("getAttribute(\"first\")") + .setter("setAttribute(\"first\", %s)") + , "firstName"); + + builder.field(name.nestedProperty("last") + .type(String.class) + .getter("getAttribute(\"last\")") + .setter("setAttribute(\"last\", %s)") + , "lastName"); + + } + + factory.registerClassMap(builder); + + MapperFacade mapper = factory.getMapperFacade(); + + Element person = new Element(); + Element employment = new Element(); + List jobTitles = new ArrayList<>(); + jobTitles.add("manager"); + jobTitles.add("executive"); + employment.setAttribute("jobTitle", jobTitles); + employment.setAttribute("salary", 50000L); + person.setAttribute("employment", employment); + Element name = new Element(); + name.setAttribute("first", "Chuck"); + name.setAttribute("last", "Testa"); + person.setAttribute("name", name); + + PersonDto result = mapper.map(person, PersonDto.class); + + Assert.assertEquals(((Element)person.getAttribute("name")).getAttribute("first"), result.firstName); + Assert.assertEquals(((Element)person.getAttribute("name")).getAttribute("last"), result.lastName); + Assert.assertEquals(((Element)person.getAttribute("employment")).getAttribute("salary"), result.salary); + Assert.assertEquals(((Element)person.getAttribute("employment")).getAttribute("jobTitle"), result.jobTitles); + } + + /** + * Demonstrates that you can declare properties in-line using a custom property descriptor format; + * like so: "propertyName{getterName|setterName|type=the.type.Name}" + * setter and type name are optional + * although those arguments must be constants; + */ + @Test + public void testAdHocResolution_integration_declarativeProperties() { + + MapperFactory factory = MappingUtil.getMapperFactory(); + + { + String employmentDef = "employment:{getAttribute(\"employment\")|setAttribute(\"employment\", %s)|type=ma.glasnost.orika.test.property.PropertyResolverTestCase$Element}"; + String jobTitleDef = "jobTitle:{getAttribute(\"jobTitle\")|setAttribute(\"jobTitle\", %s)|type=java.util.List}"; + String salaryDef = "salary:{getAttribute(\"salary\")|setAttribute(\"salary\", %s)|type=java.lang.Long}"; + + String nameDef = "name:{getAttribute(\"name\")|setAttribute(\"name\",%s)|type=ma.glasnost.orika.test.property.PropertyResolverTestCase$Element}"; + String firstNameDef = "first:{getAttribute(\"first\")|setAttribute(\"first\", %s)|type=java.lang.String}"; + String lastNameDef = "last:{getAttribute(\"last\")|setAttribute(\"last\", %s)|type=java.lang.String}"; + + factory.classMap(Element.class, PersonDto.class) + .field(employmentDef + "." + jobTitleDef, "jobTitles") + .field(employmentDef + "." + salaryDef, "salary") + .field(nameDef + "." + firstNameDef, "firstName") + .field(nameDef + "." + lastNameDef, "lastName") + .register(); + } + + MapperFacade mapper = factory.getMapperFacade(); + + Element person = new Element(); + Element employment = new Element(); + List jobTitles = new ArrayList<>(); + jobTitles.add("manager"); + jobTitles.add("executive"); + employment.setAttribute("jobTitle", jobTitles); + employment.setAttribute("salary", 50000L); + person.setAttribute("employment", employment); + Element name = new Element(); + name.setAttribute("first", "Chuck"); + name.setAttribute("last", "Testa"); + person.setAttribute("name", name); + + PersonDto result = mapper.map(person, PersonDto.class); + + Assert.assertEquals(((Element)person.getAttribute("name")).getAttribute("first"), result.firstName); + Assert.assertEquals(((Element)person.getAttribute("name")).getAttribute("last"), result.lastName); + Assert.assertEquals(((Element)person.getAttribute("employment")).getAttribute("salary"), result.salary); + Assert.assertEquals(((Element)person.getAttribute("employment")).getAttribute("jobTitle"), result.jobTitles); + + Element mapBack = mapper.map(result, Element.class); + + Assert.assertEquals(((Element)person.getAttribute("name")).getAttribute("first"), ((Element)mapBack.getAttribute("name")).getAttribute("first")); + Assert.assertEquals(((Element)person.getAttribute("name")).getAttribute("last"), ((Element)mapBack.getAttribute("name")).getAttribute("last")); + Assert.assertEquals(((Element)person.getAttribute("employment")).getAttribute("salary"), ((Element)mapBack.getAttribute("employment")).getAttribute("salary")); + + List original = (List) ((Element)person.getAttribute("employment")).getAttribute("jobTitle"); + List mapBackList = (List) ((Element)mapBack.getAttribute("employment")).getAttribute("jobTitle"); + Assert.assertTrue(original.containsAll(mapBackList)); + Assert.assertTrue(mapBackList.containsAll(original)); + } + + /** + * Demonstrates that you can specify the types as parameterized if necessary, + * such as "List<String>" or "java.util.List<java.lang.String>" + * + */ + @Test + public void testAdHocResolution_integration_declarativePropertiesNestedTypes() { + + MapperFactory factory = MappingUtil.getMapperFactory(); + + { + String employmentDef = "employment:{getAttribute(\"employment\")|setAttribute(\"employment\", %s)|type=ma.glasnost.orika.test.property.PropertyResolverTestCase$Element}"; + String jobTitleDef = "jobTitle:{getAttribute(\"jobTitle\")|setAttribute(\"jobTitle\", %s)|type=List}"; + String salaryDef = "salary:{getAttribute(\"salary\")|setAttribute(\"salary\", %s)|type=java.lang.Long}"; + + String nameDef = "name:{getAttribute(\"name\")|setAttribute(\"name\",%s)|type=ma.glasnost.orika.test.property.PropertyResolverTestCase$Element}"; + String firstNameDef = "first:{getAttribute(\"first\")|setAttribute(\"first\", %s)|type=java.lang.String}"; + String lastNameDef = "last:{getAttribute(\"last\")|setAttribute(\"last\", %s)|type=java.lang.String}"; + + factory.classMap(Element.class, PersonDto.class) + .field(employmentDef + "." + jobTitleDef, "jobTitles") + .field("employment." + salaryDef, "salary") // reuse the in-line declaration of 'employment' property + .field(nameDef + "." + firstNameDef, "firstName") + .field("name." + lastNameDef, "lastName") // reuses the in-line declaration of 'name' property + .register(); + } + + MapperFacade mapper = factory.getMapperFacade(); + + Element person = new Element(); + Element employment = new Element(); + List jobTitles = new ArrayList<>(); + jobTitles.add("manager"); + jobTitles.add("executive"); + employment.setAttribute("jobTitle", jobTitles); + employment.setAttribute("salary", 50000L); + person.setAttribute("employment", employment); + Element name = new Element(); + name.setAttribute("first", "Chuck"); + name.setAttribute("last", "Testa"); + person.setAttribute("name", name); + + PersonDto result = mapper.map(person, PersonDto.class); + + Assert.assertEquals(((Element)person.getAttribute("name")).getAttribute("first"), result.firstName); + Assert.assertEquals(((Element)person.getAttribute("name")).getAttribute("last"), result.lastName); + Assert.assertEquals(((Element)person.getAttribute("employment")).getAttribute("salary"), result.salary); + Assert.assertEquals(((Element)person.getAttribute("employment")).getAttribute("jobTitle"), result.jobTitles); + + Element mapBack = mapper.map(result, Element.class); + + Assert.assertEquals(((Element)person.getAttribute("name")).getAttribute("first"), ((Element)mapBack.getAttribute("name")).getAttribute("first")); + Assert.assertEquals(((Element)person.getAttribute("name")).getAttribute("last"), ((Element)mapBack.getAttribute("name")).getAttribute("last")); + Assert.assertEquals(((Element)person.getAttribute("employment")).getAttribute("salary"), ((Element)mapBack.getAttribute("employment")).getAttribute("salary")); + + List original = (List) ((Element)person.getAttribute("employment")).getAttribute("jobTitle"); + List mapBackList = (List) ((Element)mapBack.getAttribute("employment")).getAttribute("jobTitle"); + Assert.assertTrue(original.containsAll(mapBackList)); + Assert.assertTrue(mapBackList.containsAll(original)); + + } + + /** + * Demonstrates that you can specify the types as parameterized if necessary, + * such as "List<String>" or "java.util.List<java.lang.String>", + * and that single quotes can be used instead of double quotes for convenience. + */ + @Test + public void testAdHocResolution_integration_declarativePropertiesNestedTypesSingleQuote() { + + MapperFactory factory = MappingUtil.getMapperFactory(); + + { + String employmentDef = "employment:{getAttribute('employment')|setAttribute('employment', %s)|type=ma.glasnost.orika.test.property.PropertyResolverTestCase.Element}"; + String jobTitleDef = "jobTitle:{getAttribute(\"job's Title\")|setAttribute(\"job's Title\", %s)|type=List}"; + String salaryDef = "salary:{getAttribute(\"'salary'\")|setAttribute(\"'salary'\", %s)|type=java.lang.Long}"; + + String nameDef = "name:{getAttribute('name')|setAttribute('name',%s)|type=ma.glasnost.orika.test.property.PropertyResolverTestCase.Element}"; + String firstNameDef = "first:{getAttribute('first')|setAttribute('first', %s)|type=java.lang.String}"; + String lastNameDef = "last:{getAttribute('last')|setAttribute('last', %s)|type=java.lang.String}"; + String pointsDef = "points:{getAttribute('points')|setAttribute('points', %s)|type=List}"; + + factory.classMap(Element.class, PersonDto.class) + .field(employmentDef + "." + jobTitleDef, "jobTitles") + .field("employment." + salaryDef, "salary") // reuse the in-line declaration of 'employment' property + .field(nameDef + "." + firstNameDef, "firstName") + .field("name." + lastNameDef, "lastName") // reuses the in-line declaration of 'name' property + .field(pointsDef, "points") + .register(); + } + + MapperFacade mapper = factory.getMapperFacade(); + + Element person = new Element(); + Element employment = new Element(); + List jobTitles = new ArrayList<>(); + jobTitles.add("manager"); + jobTitles.add("executive"); + employment.setAttribute("job's Title", jobTitles); + employment.setAttribute("'salary'", 50000L); + person.setAttribute("employment", employment); + Element name = new Element(); + name.setAttribute("first", "Chuck"); + name.setAttribute("last", "Testa"); + person.setAttribute("name", name); + + PersonDto result = mapper.map(person, PersonDto.class); + + Assert.assertEquals(((Element)person.getAttribute("name")).getAttribute("first"), result.firstName); + Assert.assertEquals(((Element)person.getAttribute("name")).getAttribute("last"), result.lastName); + Assert.assertEquals(((Element)person.getAttribute("employment")).getAttribute("'salary'"), result.salary); + Assert.assertEquals(((Element)person.getAttribute("employment")).getAttribute("job's Title"), result.jobTitles); + + Element mapBack = mapper.map(result, Element.class); + + Assert.assertEquals(((Element)person.getAttribute("name")).getAttribute("first"), ((Element)mapBack.getAttribute("name")).getAttribute("first")); + Assert.assertEquals(((Element)person.getAttribute("name")).getAttribute("last"), ((Element)mapBack.getAttribute("name")).getAttribute("last")); + Assert.assertEquals(((Element)person.getAttribute("employment")).getAttribute("'salary'"), ((Element)mapBack.getAttribute("employment")).getAttribute("'salary'")); + + List original = (List) ((Element)person.getAttribute("employment")).getAttribute("job's Title"); + List mapBackList = (List) ((Element)mapBack.getAttribute("employment")).getAttribute("job's Title"); + Assert.assertTrue(original.containsAll(mapBackList)); + Assert.assertTrue(mapBackList.containsAll(original)); + + } + + @Test + public void resolveGenericTypeFromAncestor() { + + Type type = TypeFactory.valueOf(OrderedMapImpl.class); + PropertyResolverStrategy resolver = new IntrospectorPropertyResolver(); + Property property = resolver.getProperty(type, "map"); + + Type expectedType = new TypeBuilder>(){}.build(); + + Assert.assertEquals(expectedType, property.getType()); + } + + public static abstract class AbstractOrderedMap implements Iterable, Serializable { + + protected final Map resultSet = new LinkedHashMap<>(); + + protected AbstractOrderedMap(Map map) { + resultSet.putAll(map); + } + + public Iterator iterator() { + return Collections.unmodifiableCollection(resultSet.values()).iterator(); + } + + public T get(K id) { + return resultSet.get(id); + } + + public Map getMap() { + return Collections.unmodifiableMap(resultSet); + } + + public int size() { + return resultSet.size(); + } + + public boolean containsId(K id) { + return resultSet.containsKey(id); + } + + public Set idSet() { + return Collections.unmodifiableSet(resultSet.keySet()); + } + + @Override + public String toString() { + return this.getClass().getSimpleName() + "{" + + "resultSet=" + resultSet + + '}'; + } + } + + /** + * This type is not itself a parameterized type, but it extends from one, + * and those parameters should be resolved in properties' types. + */ + public static class OrderedMapImpl extends AbstractOrderedMap { + public OrderedMapImpl(Map map) { + super(map); + } + } + + public static class Element { + + Map attributes = new HashMap<>(); + + public Object getAttribute(String name) { + return attributes.get(name); + } + + public void setAttribute(String name, Object value) { + attributes.put(name, value); + } + } + + public static class PersonDto { + public String firstName; + public String lastName; + public List jobTitles; + public long salary; + public List points; + } + + public static class Point { + private int x, y; + + public int getX() { + return x; + } + + public void setX(int x) { + this.x = x; + } + + public int getY() { + return y; + } + + public void setY(int y) { + this.y = y; + } + } + + public static class Line { + private Point start; + private Point end; + + public Point getStart() { + return start; + } + + public void setStart(Point start) { + this.start = start; + } + + public Point getEnd() { + return end; + } + + public void setEnd(Point end) { + this.end = end; + } + } + + public static class LineDTO { + private int x0, y0, x1, y1; + + public int getX0() { + return x0; + } + + public void setX0(int x0) { + this.x0 = x0; + } + + public int getY0() { + return y0; + } + + public void setY0(int y0) { + this.y0 = y0; + } + + public int getX1() { + return x1; + } + + public void setX1(int x1) { + this.x1 = x1; + } + + public int getY1() { + return y1; + } + + public void setY1(int y1) { + this.y1 = y1; + } + + } + + public static class SpecialCase { + + private Boolean checked; + public BigDecimal totalCost; + + + public Boolean isChecked() { + return checked; + } + + public void setChecked(Boolean checked) { + this.checked = checked; + } + } + + public static class SpecialCaseDto { + + private boolean checked; + private double totalCost; + + public boolean isChecked() { + return checked; + } + public void setChecked(boolean checked) { + this.checked = checked; + } + public double getTotalCost() { + return totalCost; + } + public void setTotalCost(double totalCost) { + this.totalCost = totalCost; + } + } + + public interface Address { + String getStreet(); + String getCity(); + String getSubnational(); + String getPostalCode(); + String getCountry(); + } + + public static class PostalAddress implements Address { + + private String street; + private String city; + private String subnational; + private String postalCode; + private String country; + public String getStreet() { + return street; + } + public void setStreet(String street) { + this.street = street; + } + public String getCity() { + return city; + } + public void setCity(String city) { + this.city = city; + } + public String getSubnational() { + return subnational; + } + public void setSubnational(String subnational) { + this.subnational = subnational; + } + public String getPostalCode() { + return postalCode; + } + public void setPostalCode(String postalCode) { + this.postalCode = postalCode; + } + public String getCountry() { + return country; + } + public void setCountry(String country) { + this.country = country; + } + } + + @Test + public void resolveParameterizedTypeFromAncestor() { + + Type type = TypeFactory.valueOf(Child.class); + PropertyResolverStrategy resolver = new IntrospectorPropertyResolver(); + Property property = resolver.getProperty(type, "content"); + + Type expectedType = new TypeBuilder>() { + }.build(); + + Assert.assertEquals(expectedType, property.getType()); + } + + public static class Parent { + private T content; + + public T getContent() { + return content; + } + + public void setContent(T content) { + this.content = content; + } + } + + public static class Child extends Parent> { + } + + @Test + public void resolveParameterizedTypeFromInterface() { + + Type type = TypeFactory.valueOf(ChildInterface.class); + PropertyResolverStrategy resolver = new IntrospectorPropertyResolver(); + Property property = resolver.getProperty(type, "content"); + + Type expectedType = new TypeBuilder>() { + }.build(); + + Assert.assertEquals(expectedType, property.getType()); + } + + public interface ParentInterface { + T getContent(); + + void setContent(T content); + } + + public interface ChildInterface extends ParentInterface> { + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/property/PublicFieldMappingTestCase.java b/core/src/test/java/ma/glasnost/orika/test/property/PublicFieldMappingTestCase.java new file mode 100644 index 00000000..c513d688 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/property/PublicFieldMappingTestCase.java @@ -0,0 +1,90 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.property; + +import ma.glasnost.orika.DefaultFieldMapper; +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.test.MappingUtil; +import ma.glasnost.orika.test.property.TestCaseClasses.Author; +import ma.glasnost.orika.test.property.TestCaseClasses.AuthorChild; +import ma.glasnost.orika.test.property.TestCaseClasses.Book; +import ma.glasnost.orika.test.property.TestCaseClasses.BookChild; +import ma.glasnost.orika.test.property.TestCaseClasses.BookMyDTO; +import org.junit.Assert; +import org.junit.Test; + +/** + * Verifies that objects that include public fields can also be properly mapped + * + * @author matt.deboer@gmail.com + * + */ +public class PublicFieldMappingTestCase { + + private Author createAuthor(Class type) throws InstantiationException, IllegalAccessException { + Author author = type.newInstance(); + author.setName("Khalil Gebran"); + + return author; + } + + private Book createBook(Class type) throws InstantiationException, IllegalAccessException { + Book book = type.newInstance(); + book.title = "The Prophet"; + + return book; + } + + @Test + public void testMappingInterfaceImplementationNoExistingMapping() throws Exception { + + + DefaultFieldMapper myHint = + /** + * This sample hint converts "myProperty" to "property", and vis-versa. + */ + (fromProperty, fromPropertyType) -> { + if (fromProperty.startsWith("my")) { + return fromProperty.substring(2, 3).toLowerCase() + fromProperty.substring(3); + } else { + return "my" + fromProperty.substring(0, 1).toUpperCase() + fromProperty.substring(1); + } + }; + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.registerDefaultFieldMapper(myHint); + MapperFacade mapper = factory.getMapperFacade(); + + Book book = createBook(BookChild.class); + book.setAuthor(createAuthor(AuthorChild.class)); + + BookMyDTO mappedBook = mapper.map(book, BookMyDTO.class); + Book mapBack = mapper.map(mappedBook, Book.class); + + Assert.assertNotNull(mappedBook); + Assert.assertNotNull(mapBack); + + Assert.assertEquals(book.getAuthor().getName(), mappedBook.getMyAuthor().getMyName()); + Assert.assertEquals(book.title, mappedBook.getMyTitle()); + Assert.assertEquals(book.getAuthor().getName(), mapBack.getAuthor().getName()); + Assert.assertEquals(book.title, mapBack.title); + } + + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/property/RegexPropertyResolverTestCase.java b/core/src/test/java/ma/glasnost/orika/test/property/RegexPropertyResolverTestCase.java new file mode 100644 index 00000000..ca1b42bb --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/property/RegexPropertyResolverTestCase.java @@ -0,0 +1,118 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.property; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.property.RegexPropertyResolver; +import ma.glasnost.orika.test.property.TestCaseClasses.A; +import ma.glasnost.orika.test.property.TestCaseClasses.Address; +import ma.glasnost.orika.test.property.TestCaseClasses.B; +import ma.glasnost.orika.test.property.TestCaseClasses.C; +import ma.glasnost.orika.test.property.TestCaseClasses.D; +import ma.glasnost.orika.test.property.TestCaseClasses.Name; +import org.junit.Assert; +import org.junit.Test; + +/** + * @author matt.deboer@gmail.com + */ +public class RegexPropertyResolverTestCase { + + @Test + public void testRegexResolution() { + + MapperFactory factory = + new DefaultMapperFactory.Builder() + .propertyResolverStrategy( + new RegexPropertyResolver( + "readThe([\\w]+)ForThisBean", + "assignThe([\\w]+)", + true, true)) + .build(); + factory.registerClassMap( + factory.classMap(A.class, B.class) + .field("name.firstName", "givenName") + .field("name.lastName", "sirName") + .field("address.city", "city") + .field("address.street", "street") + .field("address.postalCode", "postalCode") + .field("address.country", "country") + ); + + + MapperFacade mapper = factory.getMapperFacade(); + + A a = new A(); + Name name = new Name(); + name.setFirstName("Albert"); + name.setLastName("Einstein"); + a.assignTheName(name); + Address address = new Address(); + address.city = "Somewhere"; + address.country = "Germany"; + address.postalCode = "A1234FG"; + address.street = "1234 Easy St."; + a.setAddress(address); + + + B b = mapper.map(a, B.class); + + Assert.assertNotNull(b); + + A mapBack = mapper.map(b, A.class); + + Assert.assertEquals(a, mapBack); + + } + + @Test + public void testRegexResolutionWithSpecifiedCaptureGroupIndex() throws Exception { + MapperFactory factory = + new DefaultMapperFactory.Builder() + .propertyResolverStrategy( + new RegexPropertyResolver( + "(get)(\\w+)", //arbitrarily make the getter regex have two capture groups + "(set|with)(\\w+)", //C.Builder has withXXX methods and D.Builder has setXXX methods + true, true, 2, 2)) //our write method regex has two capture groups, index=2 captures the property name + .build(); + + factory.registerClassMap( + factory.classMap(TestCaseClasses.C.class, D.Builder.class) + .byDefault()); + + factory.registerClassMap( + factory.classMap(TestCaseClasses.D.class, C.Builder.class) + .byDefault()); + + + MapperFacade mapper = factory.getMapperFacade(); + + C c = new C.Builder() + .withFoo("hello") + .withBar(33) + .build(); + + D d = mapper.map(c, D.Builder.class).build(); + + C c1 = mapper.map(d, C.Builder.class).build(); + + Assert.assertEquals(c, c1); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/property/TestCaseClasses.java b/core/src/test/java/ma/glasnost/orika/test/property/TestCaseClasses.java new file mode 100644 index 00000000..78b90e1b --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/property/TestCaseClasses.java @@ -0,0 +1,538 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.property; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +public interface TestCaseClasses { + + + class Student { + public Book favoriteBook; + } + + class Book { + + public String title; + + private Author author; + + public Author getAuthor() { + return author; + } + + public void setAuthor(Author author) { + this.author = author; + } + } + + class Author { + + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + } + + class Library { + + private String title; + + public List books; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + } + + class BookChild extends Book { + private String additionalValue; + + public String getAdditionalValue() { + return additionalValue; + } + + public void setAdditionalValue(String additionalValue) { + this.additionalValue = additionalValue; + } + } + + class AuthorChild extends Author { + private String additionalValue; + + public String getAdditionalValue() { + return additionalValue; + } + + public void setAdditionalValue(String additionalValue) { + this.additionalValue = additionalValue; + } + } + + class LibraryChild extends Library { + private String additionalValue; + + public String getAdditionalValue() { + return additionalValue; + } + + public void setAdditionalValue(String additionalValue) { + this.additionalValue = additionalValue; + } + } + + class AuthorDTO { + + private String name; + private String additionalValue; + + public String getAdditionalValue() { + return additionalValue; + } + + public void setAdditionalValue(String additionalValue) { + this.additionalValue = additionalValue; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + class BookDTO { + + private String title; + public AuthorDTO author; + private String additionalValue; + + public String getAdditionalValue() { + return additionalValue; + } + + public void setAdditionalValue(String additionalValue) { + this.additionalValue = additionalValue; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public AuthorDTO getAuthor() { + return author; + } + + public void setAuthor(AuthorDTO author) { + this.author = author; + } + } + + class LibraryDTO { + + public String title; + private List books; + private String additionalValue; + + public String getAdditionalValue() { + return additionalValue; + } + + public void setAdditionalValue(String additionalValue) { + this.additionalValue = additionalValue; + } + + public List getBooks() { + if (books==null) { + books = new ArrayList<>(); + } + return books; + } + } + + + class AuthorMyDTO { + + private String name; + private String additionalValue; + + public String getMyAdditionalValue() { + return additionalValue; + } + + public void setMyAdditionalValue(String additionalValue) { + this.additionalValue = additionalValue; + } + + public String getMyName() { + return name; + } + + public void setMyName(String name) { + this.name = name; + } + } + + class BookMyDTO { + + private String title; + private AuthorMyDTO author; + public String additionalValue; + + public String getMyTitle() { + return title; + } + + public void setMyTitle(String title) { + this.title = title; + } + + public AuthorMyDTO getMyAuthor() { + return author; + } + + public void setMyAuthor(AuthorMyDTO author) { + this.author = author; + } + } + + class LibraryMyDTO { + + public String myTitle; + private List books; + private String additionalValue; + + public String getMyAdditionalValue() { + return additionalValue; + } + + public void setMyAdditionalValue(String additionalValue) { + this.additionalValue = additionalValue; + } + + public List getMyBooks() { + if (books==null) { + books = new ArrayList<>(); + } + return books; + } + } + + class A { + private Name name; + private Address address; + + public Address getAddress() { + return address; + } + + public void setAddress(Address address) { + this.address = address; + } + + public Name readTheNameForThisBean() { + return name; + } + + public void assignTheName(Name name) { + this.name = name; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((address == null) ? 0 : address.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + A other = (A) obj; + if (address == null) { + if (other.address != null) + return false; + } else if (!address.equals(other.address)) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } + + + } + + class B { + public String givenName; + public String sirName; + public String street; + public String city; + public String postalCode; + public String country; + } + + class C { + private final String foo; + private final int bar; + + + private C(String foo, int bar) { + this.foo = foo; + this.bar = bar; + } + + public String getFoo() { + return foo; + } + + public int getBar() { + return bar; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + C c = (C) o; + + if (bar != c.bar) return false; + return Objects.equals(foo, c.foo); + + } + + @Override + public int hashCode() { + int result = foo != null ? foo.hashCode() : 0; + result = 31 * result + bar; + return result; + } + + public static class Builder { + private String foo; + private int bar; + + public Builder() { + } + + public Builder withFoo(String foo) { + this.foo = foo; + return this; + } + + public Builder withBar(int bar) { + this.bar = bar; + return this; + } + + + public C build() { + return new C(foo, bar); + } + } + } + + class D { + private final String foo; + private final int bar; + + + private D(String foo, int bar) { + this.foo = foo; + this.bar = bar; + } + + public String getFoo() { + return foo; + } + + public int getBar() { + return bar; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + D d = (D) o; + + if (bar != d.bar) return false; + return Objects.equals(foo, d.foo); + + } + + @Override + public int hashCode() { + int result = foo != null ? foo.hashCode() : 0; + result = 31 * result + bar; + return result; + } + + public static class Builder { + private String foo; + private int bar; + + public Builder() { + } + + public Builder setFoo(String foo) { + this.foo = foo; + return this; + } + + public Builder setBar(int bar) { + this.bar = bar; + return this; + } + + + public D build() { + return new D(foo, bar); + } + } + } + + + + class Name { + private String firstName; + private String lastName; + + public String getFirstName() { + return firstName; + } + public void setFirstName(String firstName) { + this.firstName = firstName; + } + public String getLastName() { + return lastName; + } + public void setLastName(String lastName) { + this.lastName = lastName; + } + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((firstName == null) ? 0 : firstName.hashCode()); + result = prime * result + ((lastName == null) ? 0 : lastName.hashCode()); + return result; + } + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Name other = (Name) obj; + if (firstName == null) { + if (other.firstName != null) + return false; + } else if (!firstName.equals(other.firstName)) + return false; + if (lastName == null) { + if (other.lastName != null) + return false; + } else if (!lastName.equals(other.lastName)) + return false; + return true; + } + + } + + class Address { + public String street; + public String city; + public String postalCode; + public String country; + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((city == null) ? 0 : city.hashCode()); + result = prime * result + ((country == null) ? 0 : country.hashCode()); + result = prime * result + ((postalCode == null) ? 0 : postalCode.hashCode()); + result = prime * result + ((street == null) ? 0 : street.hashCode()); + return result; + } + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Address other = (Address) obj; + if (city == null) { + if (other.city != null) + return false; + } else if (!city.equals(other.city)) + return false; + if (country == null) { + if (other.country != null) + return false; + } else if (!country.equals(other.country)) + return false; + if (postalCode == null) { + if (other.postalCode != null) + return false; + } else if (!postalCode.equals(other.postalCode)) + return false; + if (street == null) { + if (other.street != null) + return false; + } else if (!street.equals(other.street)) + return false; + return true; + } + + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/unenhance/Author.java b/core/src/test/java/ma/glasnost/orika/test/unenhance/Author.java new file mode 100644 index 00000000..a8f6a977 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/unenhance/Author.java @@ -0,0 +1,70 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.unenhance; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.OneToMany; +import java.util.HashSet; +import java.util.Set; + +@Entity +public class Author { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + @Column + private String name; + + @OneToMany + private Set books; + + public Author() { + this.books = new HashSet<>(); + } + + public Set getBooks() { + return books; + } + + public void setBooks(Set books) { + this.books = books; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/unenhance/AuthorDTO.java b/core/src/test/java/ma/glasnost/orika/test/unenhance/AuthorDTO.java new file mode 100644 index 00000000..aa4aa822 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/unenhance/AuthorDTO.java @@ -0,0 +1,40 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.unenhance; + +public class AuthorDTO { + private Long id; + private String name; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/unenhance/Book.java b/core/src/test/java/ma/glasnost/orika/test/unenhance/Book.java new file mode 100644 index 00000000..f85609b2 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/unenhance/Book.java @@ -0,0 +1,66 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.unenhance; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.ManyToOne; + +@Entity +public class Book { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + @Column + private String title; + + @ManyToOne(fetch = FetchType.LAZY) + private Author author; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public Author getAuthor() { + return author; + } + + public void setAuthor(Author author) { + this.author = author; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/unenhance/BookDTO.java b/core/src/test/java/ma/glasnost/orika/test/unenhance/BookDTO.java new file mode 100644 index 00000000..85323774 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/unenhance/BookDTO.java @@ -0,0 +1,53 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.unenhance; + + + +public class BookDTO { + + private Long id; + private String title; + private AuthorDTO author; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public AuthorDTO getAuthor() { + return author; + } + + public void setAuthor(AuthorDTO author) { + this.author = author; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/unenhance/HibernateProxyTestCase.java b/core/src/test/java/ma/glasnost/orika/test/unenhance/HibernateProxyTestCase.java new file mode 100644 index 00000000..c63d4948 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/unenhance/HibernateProxyTestCase.java @@ -0,0 +1,98 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.unenhance; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.test.MappingUtil; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.BookDTO; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.transaction.annotation.Transactional; + +import java.io.Serializable; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations="classpath:HibernateProxyTestCase-context.xml") +@Transactional +@DirtiesContext +public class HibernateProxyTestCase { + + private final MapperFacade mapper = MappingUtil.getMapperFactory().getMapperFacade(); + + @Autowired + private SessionFactory sessionFactory; + + private Serializable bookId; + + + + protected Session getSession() { + return sessionFactory.getCurrentSession(); + } + + @Before + public void setup() { + + Author author = new Author(); + author.setName("Khalil Gebran"); + getSession().save(author); + + Book book = new Book(); + book.setTitle("The Prophet"); + book.setAuthor(author); + + + Book book2 = new Book(); + book2.setTitle("The Prophet 2"); + book.setAuthor(author); + + bookId = getSession().save(book); + getSession().save(book2); + + /* + * Set books also to complete cyclic relationship + */ + author.getBooks().add(book); + author.getBooks().add(book2); + + + getSession().flush(); + getSession().clear(); + } + + @Test + public void testMappingProxyObject() { + + Book book = (Book) getSession().load(Book.class, bookId); + for (int i=0; i < 100; ++i) { + BookDTO bookDto = mapper.map(book, BookDTO.class); + + Assert.assertEquals("The Prophet", bookDto.getTitle()); + Assert.assertEquals("Khalil Gebran", bookDto.getAuthor().getName()); + } + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/unenhance/InaccessibleTypeTestCase.java b/core/src/test/java/ma/glasnost/orika/test/unenhance/InaccessibleTypeTestCase.java new file mode 100644 index 00000000..625fd90f --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/unenhance/InaccessibleTypeTestCase.java @@ -0,0 +1,51 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.unenhance; + +import java.util.Collections; + +import org.junit.Assert; +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.test.MappingUtil; + +import org.junit.Test; + +public class InaccessibleTypeTestCase { + + + @Test + public void accountInformationToSearchInformationEmptyAccountInformationTest() { + + MapperFactory mapperFactory = MappingUtil.getMapperFactory(); + MapperFacade mapper = mapperFactory.getMapperFacade(); + + B info = mapper.map(Collections. emptyList(),B.class); + Assert.assertNotNull(info); + } + + public static class A { + + } + + public static class B { + + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/unenhance/SuperTypeForGeneratedTestCase.java b/core/src/test/java/ma/glasnost/orika/test/unenhance/SuperTypeForGeneratedTestCase.java new file mode 100644 index 00000000..ce5c8ded --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/unenhance/SuperTypeForGeneratedTestCase.java @@ -0,0 +1,92 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.unenhance; + +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.test.MappingUtil; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.Author; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.AuthorParent; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.Book; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.BookParent; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.Library; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.LibraryDTO; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.LibraryParent; +import org.easymock.EasyMock; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +public class SuperTypeForGeneratedTestCase { + + + private Author createAuthor() throws InstantiationException, IllegalAccessException { + + Author author = EasyMock.createNiceMock(AuthorParent.class); + EasyMock.expect(author.getName()).andReturn("Khalil Gebran").anyTimes(); + EasyMock.replay(author); + + return author; + } + + private Book createBook() throws InstantiationException, IllegalAccessException { + Book book = EasyMock.createNiceMock(BookParent.class); + EasyMock.expect(book.getTitle()).andReturn("The Prophet").anyTimes(); + Author author = createAuthor(); + EasyMock.expect(book.getAuthor()).andReturn(author).anyTimes(); + EasyMock.replay(book); + + return book; + } + + private Library createLibrary() throws InstantiationException, IllegalAccessException { + + Library lib = EasyMock.createNiceMock(LibraryParent.class); + EasyMock.expect(lib.getTitle()).andReturn("Test Library").anyTimes(); + List books = new ArrayList<>(); + Book book = createBook(); + books.add(book); + EasyMock.expect(lib.getBooks()).andReturn(books).anyTimes(); + + EasyMock.replay(lib); + + return lib; + } + + + @Test + public void testSuperTypeMappingForInaccessibleClasses() throws Exception { + + MapperFactory factory = MappingUtil.getMapperFactory(); + + Library lib = createLibrary(); + Book book = lib.getBooks().get(0); + + LibraryDTO mappedLib = factory.getMapperFacade().map(lib, LibraryDTO.class); + + Assert.assertNotNull(mappedLib); + + Assert.assertEquals(lib.getTitle(),mappedLib.getTitle()); + Assert.assertEquals(book.getTitle(),mappedLib.getBooks().get(0).getTitle()); + Assert.assertEquals(book.getAuthor().getName(),mappedLib.getBooks().get(0).getAuthor().getName()); + + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/unenhance/SuperTypeMappingTestCase.java b/core/src/test/java/ma/glasnost/orika/test/unenhance/SuperTypeMappingTestCase.java new file mode 100644 index 00000000..72b5a298 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/unenhance/SuperTypeMappingTestCase.java @@ -0,0 +1,348 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.unenhance; + +import ma.glasnost.orika.DefaultFieldMapper; +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.test.MappingUtil; +import ma.glasnost.orika.test.MavenProjectUtil; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.Author; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.AuthorChild; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.AuthorMyDTO; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.AuthorParent; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.Book; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.BookChild; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.BookMyDTO; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.BookParent; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.Library; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.LibraryChild; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.LibraryMyDTO; +import ma.glasnost.orika.test.unenhance.SuperTypeTestCaseClasses.LibraryParent; +import org.junit.Assert; +import org.junit.Test; + +import javax.xml.datatype.DatatypeFactory; +import javax.xml.datatype.XMLGregorianCalendar; +import java.io.File; +import java.util.Date; +import java.util.GregorianCalendar; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +public class SuperTypeMappingTestCase { + + private Author createAuthor(Class type) throws InstantiationException, IllegalAccessException { + Author author = type.newInstance(); + author.setName("Khalil Gebran"); + + return author; + } + + private Book createBook(Class type) throws InstantiationException, IllegalAccessException { + Book book = type.newInstance(); + book.setTitle("The Prophet"); + + return book; + } + + private Library createLibrary(Class type) throws InstantiationException, IllegalAccessException { + Library lib = type.newInstance(); + lib.setTitle("Test Library"); + + return lib; + } + + @Test + public void testMappingInterfaceImplementationNoExistingMapping() throws Exception { + + MapperFacade mapper = MappingUtil.getMapperFactory().getMapperFacade(); + + Book book = createBook(BookChild.class); + book.setAuthor(createAuthor(AuthorChild.class)); + + BookMyDTO mappedBook = mapper.map(book, BookMyDTO.class); + + Assert.assertNotNull(mappedBook); + Assert.assertNull(mappedBook.getMyTitle()); + Assert.assertNull(mappedBook.getMyAuthor()); + } + + @Test + public void testMappingInterfaceImplementationWithExistingDirectMapping() throws Exception { + + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.classMap(Library.class, LibraryMyDTO.class) + .field("title", "myTitle") + .field("books", "myBooks") + .byDefault() + .register(); + + factory.classMap(Author.class, AuthorMyDTO.class) + .field("name", "myName") + .byDefault() + .register(); + + factory.classMap(Book.class, BookMyDTO.class) + .field("title", "myTitle") + .field("author", "myAuthor") + .byDefault() + .register(); + + + MapperFacade mapper = factory.getMapperFacade(); + + Book book = createBook(BookParent.class); + book.setAuthor(createAuthor(AuthorParent.class)); + Library lib = createLibrary(LibraryParent.class); + lib.getBooks().add(book); + + LibraryMyDTO mappedLib = mapper.map(lib, LibraryMyDTO.class); + + Assert.assertEquals(lib.getTitle(), mappedLib.getMyTitle()); + Assert.assertEquals(book.getTitle(), mappedLib.getMyBooks().get(0).getMyTitle()); + Assert.assertEquals(book.getAuthor().getName(), mappedLib.getMyBooks().get(0).getMyAuthor().getMyName()); + } + + @Test + public void testMappingInterfaceImplementationWithExistingInheritedMapping() throws Exception { + + MapperFactory factory = MappingUtil.getMapperFactory(); + factory.classMap(Library.class, LibraryMyDTO.class) + .field("title", "myTitle") + .field("books", "myBooks") + .byDefault() + .register(); + + factory.classMap(Author.class, AuthorMyDTO.class) + .field("name", "myName") + .byDefault() + .register(); + + factory.classMap(Book.class, BookMyDTO.class) + .field("title", "myTitle") + .field("author", "myAuthor") + .byDefault() + .register(); + + + + MapperFacade mapper = factory.getMapperFacade(); + + // BookChild, AuthorChild, LibraryChild don't directly + // implement Book, Author and Library + Book book = createBook(BookChild.class); + book.setAuthor(createAuthor(AuthorChild.class)); + Library lib = createLibrary(LibraryChild.class); + lib.getBooks().add(book); + + LibraryMyDTO mappedLib = mapper.map(lib, LibraryMyDTO.class); + + Assert.assertEquals(lib.getTitle(), mappedLib.getMyTitle()); + Assert.assertEquals(book.getTitle(), mappedLib.getMyBooks().get(0).getMyTitle()); + Assert.assertEquals(book.getAuthor().getName(), mappedLib.getMyBooks().get(0).getMyAuthor().getMyName()); + } + + @Test + public void testMappingSubclassImplementationWithoutExistingMapping() throws Exception { + + MapperFactory factory = MappingUtil.getMapperFactory(); + + /** + * This sample hint converts "myProperty" to "property", and vis-versa. + */ + DefaultFieldMapper myDefaultFieldMapper = (fromProperty, fromPropertyType) -> { + if (fromProperty.startsWith("my")) { + return fromProperty.substring(2, 1).toLowerCase() + fromProperty.substring(3); + } else { + return "my" + fromProperty.substring(0, 1).toUpperCase() + fromProperty.substring(1); + } + }; + factory.registerDefaultFieldMapper(myDefaultFieldMapper); + + + MapperFacade mapper = factory.getMapperFacade(); + + Book book = createBook(BookChild.class); + book.setAuthor(createAuthor(AuthorChild.class)); + + BookMyDTO mappedBook = mapper.map(book, BookMyDTO.class); + + Assert.assertEquals(book.getTitle(), mappedBook.getMyTitle()); + Assert.assertEquals(book.getAuthor().getName(), mappedBook.getMyAuthor().getMyName()); + } + + @Test + public void testMappingSubclassImplementationWithExistingMapping() throws Exception { + + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.registerClassMap(factory.classMap(AuthorParent.class, AuthorMyDTO.class) + .field("name", "myName") + .byDefault() + .toClassMap()); + factory.registerClassMap(factory.classMap(BookParent.class, BookMyDTO.class) + .field("title", "myTitle") + .field("author", "myAuthor") + .byDefault() + .toClassMap()); + + MapperFacade mapper = factory.getMapperFacade(); + + Book book = createBook(BookChild.class); + book.setAuthor(createAuthor(AuthorChild.class)); + + BookMyDTO mappedBook = mapper.map(book, BookMyDTO.class); + + Assert.assertEquals(book.getTitle(), mappedBook.getMyTitle()); + Assert.assertEquals(book.getAuthor().getName(), mappedBook.getMyAuthor().getMyName()); + } + + public static class A { + XMLGregorianCalendar time; + + public A() { + } + + public XMLGregorianCalendar getTime() { + return time; + } + + public void setTime(XMLGregorianCalendar time) { + this.time = time; + } + } + + public static class B { + Date time; + + public B() { + } + + public Date getTime() { + return time; + } + + public void setTime(Date time) { + this.time = time; + } + } + + @Test + public void testSuperTypeConverterMapping() throws Exception { + + MapperFactory factory = MappingUtil.getMapperFactory(); + + factory.getConverterFactory().registerConverter(new XMLGregorianCalendarToDateConverter()); + + A a = new A(); + Date date = new Date(); + GregorianCalendar c = new GregorianCalendar(); + c.setTime(date); + a.setTime(DatatypeFactory.newInstance().newXMLGregorianCalendar(c)); + + B mapped = factory.getMapperFacade().map(a, B.class); + + assertNotNull(mapped); + assertEquals(date, mapped.getTime()); + + } + + /** + * This test is a bit complicated: it verifies that super-type lookup occurs + * properly if presented with a class that is not accessible from the + * current class loader, but which extends some super-type (or implements an + * interface) which is accessible.
+ * This type of scenario might occur in web-module to ejb jar + * interactions... + * + * + * @throws Exception + */ +// @Test +// public void testSuperTypeForInaccessibleClassWithAccessibleSupertype() throws Exception { +// +// MapperFactory factory = MappingUtil.getMapperFactory(); +// DefaultFieldMapper myHint = +// /** +// * This sample hint converts "myProperty" to "property", and vis-versa. +// */ +// (fromProperty, fromPropertyType) -> { +// if (fromProperty.startsWith("my")) { +// return fromProperty.substring(2, 3).toLowerCase() + fromProperty.substring(3); +// } else { +// return "my" + fromProperty.substring(0, 1).toUpperCase() + fromProperty.substring(1); +// } +// }; +// factory.registerDefaultFieldMapper(myHint); +// +// MapperFacade mapper = factory.getMapperFacade(); +// +// // ----------------------------------------------------------------------------- +// File projectRoot = MavenProjectUtil.findProjectRoot(); +// +// ClassLoader threadContextLoader = Thread.currentThread().getContextClassLoader(); +// +// EclipseJdtCompiler complier = new EclipseJdtCompiler(threadContextLoader); +// ClassLoader childLoader = complier.compile(new File(projectRoot, "src/main/java-hidden"),threadContextLoader); +// +// @SuppressWarnings("unchecked") +// Class hiddenAuthorType = (Class) childLoader.loadClass("types.AuthorHidden"); +// @SuppressWarnings("unchecked") +// Class hiddenBookType = (Class) childLoader.loadClass("types.BookHidden"); +// @SuppressWarnings("unchecked") +// Class hiddenLibraryType = (Class) childLoader.loadClass("types.LibraryHidden"); +// +// try { +// threadContextLoader.loadClass("types.LibraryHidden"); +// Assert.fail("types.LibraryHidden should not be accessible to the thread context class loader"); +// } catch (ClassNotFoundException e0) { +// try { +// threadContextLoader.loadClass("types.AuthorHidden"); +// Assert.fail("types.AuthorHidden should not be accessible to the thread context class loader"); +// } catch (ClassNotFoundException e1) { +// try { +// threadContextLoader.loadClass("types.BookHidden"); +// Assert.fail("types.BookHidden should not be accessible to the thread context class loader"); +// } catch (ClassNotFoundException e2) { +// /* good: all of these types should be inaccessible */ +// } +// } +// } +// // Now, these types are hidden from the current class-loader, but they +// // implement types +// // that are accessible to this loader +// // ----------------------------------------------------------------------------- +// +// Book book = createBook(hiddenBookType); +// book.setAuthor(createAuthor(hiddenAuthorType)); +// Library lib = createLibrary(hiddenLibraryType); +// lib.getBooks().add(book); +// +// LibraryMyDTO mappedLib = mapper.map(lib, LibraryMyDTO.class); +// +// Assert.assertEquals(lib.getTitle(), mappedLib.getMyTitle()); +// Assert.assertEquals(book.getTitle(), mappedLib.getMyBooks().get(0).getMyTitle()); +// Assert.assertEquals(book.getAuthor().getName(), mappedLib.getMyBooks().get(0).getMyAuthor().getMyName()); +// +// } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/unenhance/SuperTypeTestCaseClasses.java b/core/src/test/java/ma/glasnost/orika/test/unenhance/SuperTypeTestCaseClasses.java new file mode 100644 index 00000000..38f59262 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/unenhance/SuperTypeTestCaseClasses.java @@ -0,0 +1,318 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.unenhance; + +import java.util.ArrayList; +import java.util.List; + +public interface SuperTypeTestCaseClasses { + + interface Book { + + String getTitle(); + + void setTitle(String title); + + Author getAuthor(); + + void setAuthor(Author author); + + } + + interface Author { + + String getName(); + + void setName(String name); + + } + + interface Library { + + String getTitle(); + + void setTitle(String title); + + List getBooks(); + } + + class BookParent implements Book { + + private String title; + private Author author; + + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public Author getAuthor() { + return author; + } + + public void setAuthor(Author author) { + this.author = author; + } + + } + + class AuthorParent implements Author { + + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + } + + class LibraryParent implements Library { + + private String title; + + private List books; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public List getBooks() { + if (books==null) { + books = new ArrayList<>(); + } + return books; + } + + } + + class BookChild extends BookParent { + private String additionalValue; + + public String getAdditionalValue() { + return additionalValue; + } + + public void setAdditionalValue(String additionalValue) { + this.additionalValue = additionalValue; + } + } + + class AuthorChild extends AuthorParent { + private String additionalValue; + + public String getAdditionalValue() { + return additionalValue; + } + + public void setAdditionalValue(String additionalValue) { + this.additionalValue = additionalValue; + } + } + + class LibraryChild extends LibraryParent { + private String additionalValue; + + public String getAdditionalValue() { + return additionalValue; + } + + public void setAdditionalValue(String additionalValue) { + this.additionalValue = additionalValue; + } + } + + class AuthorDTO { + + private String name; + private String additionalValue; + + public String getAdditionalValue() { + return additionalValue; + } + + public void setAdditionalValue(String additionalValue) { + this.additionalValue = additionalValue; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + class BookDTO { + + private String title; + private AuthorDTO author; + private String additionalValue; + + public String getAdditionalValue() { + return additionalValue; + } + + public void setAdditionalValue(String additionalValue) { + this.additionalValue = additionalValue; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public AuthorDTO getAuthor() { + return author; + } + + public void setAuthor(AuthorDTO author) { + this.author = author; + } + } + + class LibraryDTO { + + private String title; + private List books; + private String additionalValue; + + public String getAdditionalValue() { + return additionalValue; + } + + public void setAdditionalValue(String additionalValue) { + this.additionalValue = additionalValue; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public List getBooks() { + if (books==null) { + books = new ArrayList<>(); + } + return books; + } + } + + + class AuthorMyDTO { + + private String name; + private String additionalValue; + + public String getMyAdditionalValue() { + return additionalValue; + } + + public void setMyAdditionalValue(String additionalValue) { + this.additionalValue = additionalValue; + } + + public String getMyName() { + return name; + } + + public void setMyName(String name) { + this.name = name; + } + } + + class BookMyDTO { + + private String title; + private AuthorMyDTO author; + private String additionalValue; + + public String getMyAdditionalValue() { + return additionalValue; + } + + public void setMyAdditionalValue(String additionalValue) { + this.additionalValue = additionalValue; + } + + public String getMyTitle() { + return title; + } + + public void setMyTitle(String title) { + this.title = title; + } + + public AuthorMyDTO getMyAuthor() { + return author; + } + + public void setMyAuthor(AuthorMyDTO author) { + this.author = author; + } + } + + class LibraryMyDTO { + + private String title; + private List books; + private String additionalValue; + + public String getMyAdditionalValue() { + return additionalValue; + } + + public void setMyAdditionalValue(String additionalValue) { + this.additionalValue = additionalValue; + } + + public String getMyTitle() { + return title; + } + + public void setMyTitle(String title) { + this.title = title; + } + + public List getMyBooks() { + if (books==null) { + books = new ArrayList<>(); + } + return books; + } + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/unenhance/XMLGregorianCalendarToDateConverter.java b/core/src/test/java/ma/glasnost/orika/test/unenhance/XMLGregorianCalendarToDateConverter.java new file mode 100644 index 00000000..47541709 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/unenhance/XMLGregorianCalendarToDateConverter.java @@ -0,0 +1,37 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.unenhance; + +import java.util.Date; + +import javax.xml.datatype.XMLGregorianCalendar; + +import ma.glasnost.orika.CustomConverter; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.metadata.Type; + +public class XMLGregorianCalendarToDateConverter extends CustomConverter { + + public Date convert(XMLGregorianCalendar source, Type destinationClass, MappingContext context) { + Date target = null; + if (source != null) { + target = source.toGregorianCalendar().getTime(); + } + return target; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance/AbstractDTO.java b/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance/AbstractDTO.java new file mode 100644 index 00000000..26b0ac18 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance/AbstractDTO.java @@ -0,0 +1,34 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.unenhance.inheritance; + +public class AbstractDTO { + private Long id; + + public AbstractDTO() { + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance/AbstractEntity.java b/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance/AbstractEntity.java new file mode 100644 index 00000000..4f08d856 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance/AbstractEntity.java @@ -0,0 +1,42 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.unenhance.inheritance; + +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.MappedSuperclass; + +@MappedSuperclass +public class AbstractEntity { + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + public AbstractEntity() { + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance/HibernateProxyTestCase.java b/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance/HibernateProxyTestCase.java new file mode 100644 index 00000000..f90b7ec6 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance/HibernateProxyTestCase.java @@ -0,0 +1,165 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.unenhance.inheritance; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.List; + +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.proxy.HibernateProxy; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.transaction.annotation.Transactional; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.unenhance.HibernateUnenhanceStrategy; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = "classpath:HibernateProxyTestCase-context.xml") +@Transactional +@DirtiesContext +public class HibernateProxyTestCase { + @Autowired + private SessionFactory sessionFactory; + + private Serializable sub1Id; + private Serializable sub21Id; + private Serializable sub22Id; + + protected Session getSession() { + return sessionFactory.getCurrentSession(); + } + + @Before + public void setup() { + Sub1Entity sub1 = new Sub1Entity(); + sub1.setMyProperty("my property on sub1"); + sub1.setSub1Property(1); + sub1Id = getSession().save(sub1); + + Sub2Entity sub21 = new Sub2Entity(); + sub21.setMyProperty("my property on sub2"); + sub21.setSub2Property(2); + sub21.setReferences(sub1); + sub21Id = getSession().save(sub21); + + Sub2Entity sub22 = new Sub2Entity(); + sub22.setMyProperty("my property on sub2-2"); + sub22.setSub2Property(3); + sub22.setReferences(sub21); + sub22Id = getSession().save(sub22); + + getSession().flush(); + getSession().clear(); + } + + private MapperFacade buildMapper() { + MapperFactory mf = new DefaultMapperFactory.Builder() + .unenhanceStrategy(new HibernateUnenhanceStrategy()).build(); + mf.registerClassMap(mf + .classMap(AbstractEntity.class, AbstractDTO.class).byDefault() + .toClassMap()); + mf.registerClassMap(mf.classMap(Sub1Entity.class, Sub1EntityDTO.class) + .use(AbstractEntity.class, AbstractDTO.class).byDefault() + .toClassMap()); + mf.registerClassMap(mf.classMap(Sub2Entity.class, Sub2EntityDTO.class) + .use(AbstractEntity.class, AbstractDTO.class).byDefault() + .toClassMap()); + return mf.getMapperFacade(); + } + + @Test + public void testMappingNonProxyObject() { + MapperFacade mapper = buildMapper(); + + Sub2Entity sub2 = (Sub2Entity) getSession().get(Sub2Entity.class, + sub21Id); + sub2.setReferences((MyEntity) ((HibernateProxy) sub2.getReferences()) + .getHibernateLazyInitializer().getImplementation()); + Sub2EntityDTO sub2Dto = mapper.map(sub2, Sub2EntityDTO.class); + + Assert.assertEquals(sub2.getMyProperty(), sub2Dto.getMyProperty()); + Assert.assertEquals(sub2.getSub2Property(), sub2Dto.getSub2Property()); + Assert.assertNotNull(sub2Dto.getReferences()); + Assert.assertEquals(sub2.getReferences().getMyProperty(), sub2Dto + .getReferences().getMyProperty()); + Assert.assertEquals(Sub1EntityDTO.class, sub2Dto.getReferences() + .getClass()); + Assert.assertEquals(1, + ((Sub1EntityDTO) sub2Dto.getReferences()).getSub1Property()); + } + + @Test + public void testMappingProxyObject() { + MapperFacade mapper = buildMapper(); + + Sub2Entity sub2 = (Sub2Entity) getSession().get(Sub2Entity.class, + sub21Id); + Sub2EntityDTO sub2Dto = mapper.map(sub2, Sub2EntityDTO.class); + + Assert.assertEquals(sub2.getMyProperty(), sub2Dto.getMyProperty()); + Assert.assertEquals(sub2.getSub2Property(), sub2Dto.getSub2Property()); + Assert.assertNotNull(sub2Dto.getReferences()); + Assert.assertEquals(sub2.getReferences().getMyProperty(), sub2Dto + .getReferences().getMyProperty()); + Assert.assertEquals(Sub1EntityDTO.class, sub2Dto.getReferences() + .getClass()); + Assert.assertEquals(1, + ((Sub1EntityDTO) sub2Dto.getReferences()).getSub1Property()); + } + + @Test + public void testMappingCaching() { + MapperFacade mapper = buildMapper(); + + Sub2Entity sub22 = (Sub2Entity) getSession().get(Sub2Entity.class, + sub22Id); + Sub2Entity sub21 = (Sub2Entity) getSession().get(Sub2Entity.class, + sub21Id); + Sub2EntityDTO sub21Dto = mapper.map(sub21, Sub2EntityDTO.class); + Sub2EntityDTO sub22Dto = mapper.map(sub22, Sub2EntityDTO.class); + + Assert.assertEquals(Sub1EntityDTO.class, sub21Dto.getReferences().getClass()); + Assert.assertEquals(Sub2EntityDTO.class, sub22Dto.getReferences().getClass()); + } + + @Test + public void testMappingCollections() { + MapperFacade mapper = buildMapper(); + + List entities = Arrays.asList((MyEntity) getSession().load(MyEntity.class, sub22Id), + (MyEntity) getSession().load(MyEntity.class, sub21Id), + (MyEntity) getSession().load(MyEntity.class, sub1Id)); + + List mappedList = mapper.mapAsList(entities, MyEntityDTO.class); + Assert.assertEquals(Sub2EntityDTO.class, mappedList.get(0).getClass()); + Assert.assertEquals(Sub2EntityDTO.class, mappedList.get(1).getClass()); + Assert.assertEquals(Sub1EntityDTO.class, mappedList.get(2).getClass()); + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance/MyEntity.java b/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance/MyEntity.java new file mode 100644 index 00000000..a84b2127 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance/MyEntity.java @@ -0,0 +1,54 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.unenhance.inheritance; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; + +@Entity +public class MyEntity extends AbstractEntity { + @Column + private String myProperty; + + @ManyToOne(fetch=FetchType.LAZY) + @JoinColumn(name = "references") + private MyEntity references; + + public MyEntity() { + } + + public String getMyProperty() { + return myProperty; + } + + public void setMyProperty(String myProperty) { + this.myProperty = myProperty; + } + + public MyEntity getReferences() { + return references; + } + + public void setReferences(MyEntity references) { + this.references = references; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance/MyEntityDTO.java b/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance/MyEntityDTO.java new file mode 100644 index 00000000..c4733c5b --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance/MyEntityDTO.java @@ -0,0 +1,44 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.unenhance.inheritance; + +public class MyEntityDTO extends AbstractDTO { + private String myProperty; + + private MyEntityDTO references; + + public MyEntityDTO() { + } + + public String getMyProperty() { + return myProperty; + } + + public void setMyProperty(String myProperty) { + this.myProperty = myProperty; + } + + public MyEntityDTO getReferences() { + return references; + } + + public void setReferences(MyEntityDTO references) { + this.references = references; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance/Sub1Entity.java b/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance/Sub1Entity.java new file mode 100644 index 00000000..cda0b3b4 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance/Sub1Entity.java @@ -0,0 +1,39 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.unenhance.inheritance; + +import javax.persistence.Column; +import javax.persistence.Entity; + +@Entity +public class Sub1Entity extends MyEntity { + @Column + private int sub1Property; + + public Sub1Entity() { + } + + public int getSub1Property() { + return sub1Property; + } + + public void setSub1Property(int sub1Property) { + this.sub1Property = sub1Property; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance/Sub1EntityDTO.java b/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance/Sub1EntityDTO.java new file mode 100644 index 00000000..ae04572b --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance/Sub1EntityDTO.java @@ -0,0 +1,34 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.unenhance.inheritance; + +public class Sub1EntityDTO extends MyEntityDTO { + private int sub1Property; + + public Sub1EntityDTO() { + } + + public int getSub1Property() { + return sub1Property; + } + + public void setSub1Property(int sub1Property) { + this.sub1Property = sub1Property; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance/Sub2Entity.java b/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance/Sub2Entity.java new file mode 100644 index 00000000..93d0c05e --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance/Sub2Entity.java @@ -0,0 +1,39 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.unenhance.inheritance; + +import javax.persistence.Column; +import javax.persistence.Entity; + +@Entity +public class Sub2Entity extends MyEntity { + @Column + private int sub2Property; + + public Sub2Entity() { + } + + public int getSub2Property() { + return sub2Property; + } + + public void setSub2Property(int sub2Property) { + this.sub2Property = sub2Property; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance/Sub2EntityDTO.java b/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance/Sub2EntityDTO.java new file mode 100644 index 00000000..40f89708 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance/Sub2EntityDTO.java @@ -0,0 +1,34 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.unenhance.inheritance; + +public class Sub2EntityDTO extends MyEntityDTO { + private int sub2Property; + + public Sub2EntityDTO() { + } + + public int getSub2Property() { + return sub2Property; + } + + public void setSub2Property(int sub2Property) { + this.sub2Property = sub2Property; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance2/AbstractDto.java b/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance2/AbstractDto.java new file mode 100644 index 00000000..b1ca1ddc --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance2/AbstractDto.java @@ -0,0 +1,17 @@ +package ma.glasnost.orika.test.unenhance.inheritance2; + +/** + * @author Sergey Vasilyev + */ +public class AbstractDto { + private Long id; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance2/AbstractEntity.java b/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance2/AbstractEntity.java new file mode 100644 index 00000000..a06c5e9a --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance2/AbstractEntity.java @@ -0,0 +1,24 @@ +package ma.glasnost.orika.test.unenhance.inheritance2; + +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.MappedSuperclass; + +/** + * @author Sergey Vasilyev + */ +@MappedSuperclass +public class AbstractEntity { + private Long id; + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance2/HibernateProxyTestCase.java b/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance2/HibernateProxyTestCase.java new file mode 100644 index 00000000..61d87e2d --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance2/HibernateProxyTestCase.java @@ -0,0 +1,103 @@ +package ma.glasnost.orika.test.unenhance.inheritance2; + +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.impl.DefaultMapperFactory; +import ma.glasnost.orika.unenhance.HibernateUnenhanceStrategy; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.transaction.annotation.Transactional; + +import java.io.Serializable; +import java.util.HashSet; +import java.util.Set; + +/** + * @author Sergey Vasilyev + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = "classpath:HibernateProxyTestCase-context.xml") +@Transactional +@DirtiesContext +public class HibernateProxyTestCase { + + private Serializable roomId; + private Serializable peterId; + private Serializable johnId; + + @Autowired + private SessionFactory sessionFactory; + + protected Session getSession() { + return sessionFactory.getCurrentSession(); + } + + @Before + public void setup() { + RoomEntity room = new RoomEntity(); + + Set tenants = new HashSet<>(); + + OwnerEntity john = new OwnerEntity(); + john.setName("John"); + johnId = getSession().save(john); + tenants.add(john); + + PersonEntity peter = new OwnerEntity(); + peter.setName("Peter"); + peterId = getSession().save(peter); + tenants.add(peter); + + room.setTenants(tenants); + + roomId = getSession().save(room); + + getSession().flush(); + getSession().clear(); + } + + private MapperFacade buildMapper() { + MapperFactory mf = new DefaultMapperFactory.Builder().unenhanceStrategy(new HibernateUnenhanceStrategy()).build(); + mf.registerClassMap(mf.classMap(AbstractEntity.class, AbstractDto.class).byDefault().toClassMap()); + mf.registerClassMap(mf.classMap(OwnerEntity.class, OwnerDto.class) + .use(PersonEntity.class, PersonDto.class) + .byDefault() + .toClassMap()); + mf.registerClassMap(mf.classMap(PersonEntity.class, PersonDto.class) + .use(AbstractEntity.class, AbstractDto.class) + .byDefault() + .toClassMap()); + mf.registerClassMap(mf.classMap(RoomEntity.class, RoomDto.class) + .use(AbstractEntity.class, AbstractDto.class) + .byDefault() + .toClassMap()); + return mf.getMapperFacade(); + } + + @Test + public void testInheritance() { + MapperFacade mapper = buildMapper(); + + OwnerEntity john = (OwnerEntity) getSession().load(OwnerEntity.class, johnId); + PersonEntity peter = (PersonEntity) getSession().load(PersonEntity.class, peterId); + + Assert.assertEquals("John", john.getName()); + Assert.assertEquals("Peter", peter.getName()); + + RoomEntity room = (RoomEntity) getSession().load(RoomEntity.class, roomId); + + RoomDto roomDto = mapper.map(room, RoomDto.class); + Assert.assertNotNull(roomDto); + // Iterator tenantsIter = roomDto.getTenants().iterator(); + // Assert.assertEquals("John",tenantsIter.next().getName()); + // Assert.assertEquals("Peter",tenantsIter.next().getName()); + } +} \ No newline at end of file diff --git a/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance2/OwnerDto.java b/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance2/OwnerDto.java new file mode 100644 index 00000000..a2387c52 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance2/OwnerDto.java @@ -0,0 +1,19 @@ +package ma.glasnost.orika.test.unenhance.inheritance2; + +import javax.persistence.Entity; + +/** + * @author Sergey Vasilyev + */ +@Entity +public class OwnerDto extends PersonDto { + private String specialInformation; + + public String getSpecialInformation() { + return specialInformation; + } + + public void setSpecialInformation(String specialInformation) { + this.specialInformation = specialInformation; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance2/OwnerEntity.java b/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance2/OwnerEntity.java new file mode 100644 index 00000000..702fe756 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance2/OwnerEntity.java @@ -0,0 +1,19 @@ +package ma.glasnost.orika.test.unenhance.inheritance2; + +import javax.persistence.Entity; + +/** + * @author Sergey Vasilyev + */ +@Entity +public class OwnerEntity extends PersonEntity { + private String specialInformation; + + public String getSpecialInformation() { + return specialInformation; + } + + public void setSpecialInformation(String specialInformation) { + this.specialInformation = specialInformation; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance2/PersonDto.java b/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance2/PersonDto.java new file mode 100644 index 00000000..422bb83c --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance2/PersonDto.java @@ -0,0 +1,18 @@ +package ma.glasnost.orika.test.unenhance.inheritance2; + +/** + * @author Sergey Vasilyev + */ +public class PersonDto extends AbstractDto { + private String name; + + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance2/PersonEntity.java b/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance2/PersonEntity.java new file mode 100644 index 00000000..7e59c615 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance2/PersonEntity.java @@ -0,0 +1,21 @@ +package ma.glasnost.orika.test.unenhance.inheritance2; + +import javax.persistence.Entity; + +/** + * @author Sergey Vasilyev + */ +@Entity +public class PersonEntity extends AbstractEntity { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance2/RoomDto.java b/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance2/RoomDto.java new file mode 100644 index 00000000..70326a2d --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance2/RoomDto.java @@ -0,0 +1,20 @@ +package ma.glasnost.orika.test.unenhance.inheritance2; + +import javax.persistence.Entity; +import java.util.Set; + +/** + * @author Sergey Vasilyev + */ +@Entity +public class RoomDto extends AbstractDto { + private Set tenants; + + public Set getTenants() { + return tenants; + } + + public void setTenants(Set tenants) { + this.tenants = tenants; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance2/RoomEntity.java b/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance2/RoomEntity.java new file mode 100644 index 00000000..3cb2036b --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/unenhance/inheritance2/RoomEntity.java @@ -0,0 +1,25 @@ +package ma.glasnost.orika.test.unenhance.inheritance2; + +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.OneToMany; +import javax.persistence.OrderBy; +import java.util.Set; + +/** + * @author Sergey Vasilyev + */ +@Entity +public class RoomEntity extends AbstractEntity { + private Set tenants; + + @OneToMany(fetch = FetchType.LAZY) + @OrderBy + public Set getTenants() { + return tenants; + } + + public void setTenants(Set tenants) { + this.tenants = tenants; + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/util/ClassHelperTest.java b/core/src/test/java/ma/glasnost/orika/test/util/ClassHelperTest.java new file mode 100644 index 00000000..fcf1df7c --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/util/ClassHelperTest.java @@ -0,0 +1,75 @@ +package ma.glasnost.orika.test.util; + +import java.lang.reflect.ParameterizedType; +import ma.glasnost.orika.util.ClassHelper; +import org.junit.Assert; +import org.junit.Test; + +/** + * + * @author Eduard Drenth at VectorPrint.nl + */ +public class ClassHelperTest { + + @Test + public void testGenericParamTyping() { + GenericInterface l1 = new DirectSub(); + GenericInterface l2 = new Level2Sub(); + GenericInterface l3 = new Level3Sub(); + + Assert.assertEquals(Integer.class,ClassHelper.findParameterClasses(l1.getClass(), GenericInterface.class).get(2)); + + /* + * we cannot resolve these (yet) because the actual class of these parameters are not known + * in the declaration of the classes, only on the instance + */ + Assert.assertEquals(null,ClassHelper.findParameterClasses(l1.getClass(), GenericInterface.class).get(0)); + Assert.assertEquals(null,ClassHelper.findParameterClasses(l2.getClass(), GenericInterface.class).get(1)); + + Assert.assertEquals(Integer.class, ClassHelper.findParameterClasses(DirectSub.class, GenericInterface.class).get(2)); + Assert.assertEquals(Long.class, ClassHelper.findParameterClasses(Level2Sub.class, GenericInterface.class).get(0)); + + Assert.assertEquals(Long.class, ClassHelper.findParameterClasses(Level3Sub.class, GenericInterface.class).get(0)); + Assert.assertEquals(Float.class, ClassHelper.findParameterClasses(Level3Sub.class, GenericInterface.class).get(1)); + Assert.assertEquals(Integer.class, ClassHelper.findParameterClasses(Level3Sub.class, GenericInterface.class).get(2)); + } + + @Test + public void testClassOfType() { + GenericInterface l1 = new DirectSub(); + GenericInterface l2 = new Level2Sub(); + GenericInterface l3 = new Level3Sub(); + + Assert.assertEquals(Integer.class, ClassHelper.getClass( + ( (ParameterizedType) DirectSub.class.getGenericInterfaces()[0] ) + .getActualTypeArguments()[2])); + + Assert.assertNull(ClassHelper.getClass( + ( (ParameterizedType) DirectSub.class.getGenericInterfaces()[0] ) + .getActualTypeArguments()[1])); + + Assert.assertEquals(Float[].class, ClassHelper.getClass( + ( (ParameterizedType) ArraySub.class.getGenericSuperclass() ) + .getActualTypeArguments()[0])); + + Assert.assertEquals(Level2Sub.class, ClassHelper.getClass( + ArraySub.class.getGenericSuperclass())); + + } + + private class DirectSub implements GenericInterface { + + } + // deliberately switch parameter position + private class Level2Sub extends DirectSub{ + + } + private class Level3Sub extends Level2Sub{ + + } + private class ArraySub extends Level2Sub{ + + } + + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/util/ConfigurableMapperTestCase.java b/core/src/test/java/ma/glasnost/orika/test/util/ConfigurableMapperTestCase.java new file mode 100644 index 00000000..da341abb --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/util/ConfigurableMapperTestCase.java @@ -0,0 +1,180 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.util; + +import ma.glasnost.orika.CustomConverter; +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.impl.ConfigurableMapper; +import ma.glasnost.orika.metadata.Type; +import org.junit.Assert; +import org.junit.Test; + +public class ConfigurableMapperTestCase { + + public static class CustomConfigurableMapper extends ConfigurableMapper { + + protected void configure(MapperFactory mapperFactory) { + mapperFactory.getConverterFactory().registerConverter(new CustomConverter() { + + public String convert(Address source, Type destinationType, MappingContext context) { + return source.getLine1() + " " + source.getLine2(); + } + }); + + mapperFactory.classMap(Order.class, OrderDTO.class) + .fieldMap("customer.address", "shippingAddress") + .add() + .byDefault() + .register(); + } + + } + + private final MapperFacade mapper = new CustomConfigurableMapper(); + + @Test + public void testConfigurableMapper() { + + Address address = new Address(); + address.setLine1("5 rue Blida"); + address.setLine2("Casablanca"); + + Customer customer = new Customer(); + customer.setName("Sidi Mohammed El Aatifi"); + customer.setAddress(address); + + Order order = new Order(); + order.setNumber("CPC6128"); + order.setCustomer(customer); + + OrderDTO orderDto = mapper.map(order, OrderDTO.class); + + Assert.assertEquals(address.line1 + " " + address.line2, orderDto.getShippingAddress()); + + } + + public static class Address { + + private String line1; + + private String line2; + + public String getLine1() { + return line1; + } + + public void setLine1(String line1) { + this.line1 = line1; + } + + public String getLine2() { + return line2; + } + + public void setLine2(String line2) { + this.line2 = line2; + } + + } + + public static class Customer { + + private String name; + + private Address address; + + 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 static class Order { + + private String number; + + private Customer customer; + + public String getNumber() { + return number; + } + + public void setNumber(String number) { + this.number = number; + } + + public Customer getCustomer() { + return customer; + } + + public void setCustomer(Customer customer) { + this.customer = customer; + } + + } + + public static class OrderDTO { + + public String getNumber() { + return number; + } + + public void setNumber(String number) { + this.number = number; + } + + public String getCustomerName() { + return customerName; + } + + public void setCustomerName(String customerName) { + this.customerName = customerName; + } + + public String getShippingAddress() { + return shippingAddress; + } + + public void setShippingAddress(String shippingAddress) { + this.shippingAddress = shippingAddress; + } + + private String number; + + private String customerName; + + private String shippingAddress; + + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/util/GenericInterface.java b/core/src/test/java/ma/glasnost/orika/test/util/GenericInterface.java new file mode 100644 index 00000000..942428a3 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/util/GenericInterface.java @@ -0,0 +1,9 @@ +package ma.glasnost.orika.test.util; + +/** + * + * @author Eduard Drenth at VectorPrint.nl + */ +public interface GenericInterface { + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/util/PropertiesTestCase.java b/core/src/test/java/ma/glasnost/orika/test/util/PropertiesTestCase.java new file mode 100644 index 00000000..c2ded4e2 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/util/PropertiesTestCase.java @@ -0,0 +1,117 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.util; + +import org.junit.Assert; +import org.junit.Test; + +import ma.glasnost.orika.impl.UtilityResolver; +import ma.glasnost.orika.metadata.Property; +import ma.glasnost.orika.property.PropertyResolverStrategy; + +public class PropertiesTestCase { + + @Test + public void testNestedProperty() { + String np = "start.x"; + PropertyResolverStrategy propertyResolver = UtilityResolver.getDefaultPropertyResolverStrategy(); + Property p = propertyResolver.getProperty(Line.class, np); + + Assert.assertEquals(Integer.TYPE, p.getRawType()); + } + + public static class Point { + private int x, y; + + public int getX() { + return x; + } + + public void setX(int x) { + this.x = x; + } + + public int getY() { + return y; + } + + public void setY(int y) { + this.y = y; + } + } + + public static class Line { + private Point start; + private Point end; + + public Point getStart() { + return start; + } + + public void setStart(Point start) { + this.start = start; + } + + public Point getEnd() { + return end; + } + + public void setEnd(Point end) { + this.end = end; + } + } + + public static class LineDTO { + private int x0, y0, x1, y1; + + public int getX0() { + return x0; + } + + public void setX0(int x0) { + this.x0 = x0; + } + + public int getY0() { + return y0; + } + + public void setY0(int y0) { + this.y0 = y0; + } + + public int getX1() { + return x1; + } + + public void setX1(int x1) { + this.x1 = x1; + } + + public int getY1() { + return y1; + } + + public void setY1(int y1) { + this.y1 = y1; + } + + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/util/SortedCollectionConcurrencyTestCase.java b/core/src/test/java/ma/glasnost/orika/test/util/SortedCollectionConcurrencyTestCase.java new file mode 100644 index 00000000..1f347ab8 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/util/SortedCollectionConcurrencyTestCase.java @@ -0,0 +1,244 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.util; + +import ma.glasnost.orika.metadata.MapperKey; +import ma.glasnost.orika.metadata.TypeFactory; +import ma.glasnost.orika.test.ConcurrentRule; +import ma.glasnost.orika.test.ConcurrentRule.Concurrent; +import ma.glasnost.orika.util.Ordering; +import ma.glasnost.orika.util.SortedCollection; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Queue; +import java.util.Set; +import java.util.concurrent.ConcurrentLinkedQueue; + +/** + * This test is an attempt to trigger invalid insertion order + * in SortedCollection; + * + */ +public class SortedCollectionConcurrencyTestCase { + + @Rule + public ConcurrentRule rule = new ConcurrentRule(); + + private static Queue mapperKeys; + private static SortedCollection sortedCollection; + private static int initialSize = 0; + + @BeforeClass + public static void setup() { + + + List keys = new ArrayList<>(); + + keys.add(new MapperKey(TypeFactory.valueOf(A1.class), TypeFactory.valueOf(B1.class))); + keys.add(new MapperKey(TypeFactory.valueOf(A2.class), TypeFactory.valueOf(B2.class))); + keys.add(new MapperKey(TypeFactory.valueOf(A3.class), TypeFactory.valueOf(B3.class))); + keys.add(new MapperKey(TypeFactory.valueOf(A4.class), TypeFactory.valueOf(B4.class))); + keys.add(new MapperKey(TypeFactory.valueOf(A5.class), TypeFactory.valueOf(B5.class))); + + keys.add(new MapperKey(TypeFactory.valueOf(A1.class), TypeFactory.valueOf(C1.class))); + keys.add(new MapperKey(TypeFactory.valueOf(A2.class), TypeFactory.valueOf(C2.class))); + keys.add(new MapperKey(TypeFactory.valueOf(A3.class), TypeFactory.valueOf(C3.class))); + keys.add(new MapperKey(TypeFactory.valueOf(A4.class), TypeFactory.valueOf(C4.class))); + keys.add(new MapperKey(TypeFactory.valueOf(A5.class), TypeFactory.valueOf(C5.class))); + + keys.add(new MapperKey(TypeFactory.valueOf(A1.class), TypeFactory.valueOf(D1.class))); + keys.add(new MapperKey(TypeFactory.valueOf(A2.class), TypeFactory.valueOf(D2.class))); + keys.add(new MapperKey(TypeFactory.valueOf(A3.class), TypeFactory.valueOf(D3.class))); + keys.add(new MapperKey(TypeFactory.valueOf(A4.class), TypeFactory.valueOf(D4.class))); + keys.add(new MapperKey(TypeFactory.valueOf(A5.class), TypeFactory.valueOf(D5.class))); + + keys.add(new MapperKey(TypeFactory.valueOf(B1.class), TypeFactory.valueOf(C1.class))); + keys.add(new MapperKey(TypeFactory.valueOf(B2.class), TypeFactory.valueOf(C2.class))); + keys.add(new MapperKey(TypeFactory.valueOf(B3.class), TypeFactory.valueOf(C3.class))); + keys.add(new MapperKey(TypeFactory.valueOf(B4.class), TypeFactory.valueOf(C4.class))); + keys.add(new MapperKey(TypeFactory.valueOf(B5.class), TypeFactory.valueOf(C5.class))); + + keys.add(new MapperKey(TypeFactory.valueOf(B1.class), TypeFactory.valueOf(D1.class))); + keys.add(new MapperKey(TypeFactory.valueOf(B2.class), TypeFactory.valueOf(D2.class))); + keys.add(new MapperKey(TypeFactory.valueOf(B3.class), TypeFactory.valueOf(D3.class))); + keys.add(new MapperKey(TypeFactory.valueOf(B4.class), TypeFactory.valueOf(D4.class))); + keys.add(new MapperKey(TypeFactory.valueOf(B5.class), TypeFactory.valueOf(D5.class))); + + keys.add(new MapperKey(TypeFactory.valueOf(C1.class), TypeFactory.valueOf(D1.class))); + keys.add(new MapperKey(TypeFactory.valueOf(C2.class), TypeFactory.valueOf(D2.class))); + keys.add(new MapperKey(TypeFactory.valueOf(C3.class), TypeFactory.valueOf(D3.class))); + keys.add(new MapperKey(TypeFactory.valueOf(C4.class), TypeFactory.valueOf(D4.class))); + keys.add(new MapperKey(TypeFactory.valueOf(C5.class), TypeFactory.valueOf(D5.class))); + + // ~~~~~~~~~~~~~~~~~~ + // Add some mismatched mapper keys, in attempt to confuse the ordering + // process + + keys.add(new MapperKey(TypeFactory.valueOf(A1.class), TypeFactory.valueOf(B5.class))); + keys.add(new MapperKey(TypeFactory.valueOf(A2.class), TypeFactory.valueOf(B4.class))); + keys.add(new MapperKey(TypeFactory.valueOf(A4.class), TypeFactory.valueOf(B2.class))); + keys.add(new MapperKey(TypeFactory.valueOf(A5.class), TypeFactory.valueOf(B1.class))); + + keys.add(new MapperKey(TypeFactory.valueOf(A1.class), TypeFactory.valueOf(C5.class))); + keys.add(new MapperKey(TypeFactory.valueOf(A2.class), TypeFactory.valueOf(C4.class))); + keys.add(new MapperKey(TypeFactory.valueOf(A4.class), TypeFactory.valueOf(C2.class))); + keys.add(new MapperKey(TypeFactory.valueOf(A5.class), TypeFactory.valueOf(C1.class))); + + keys.add(new MapperKey(TypeFactory.valueOf(A1.class), TypeFactory.valueOf(D5.class))); + keys.add(new MapperKey(TypeFactory.valueOf(A2.class), TypeFactory.valueOf(D4.class))); + keys.add(new MapperKey(TypeFactory.valueOf(A4.class), TypeFactory.valueOf(D2.class))); + keys.add(new MapperKey(TypeFactory.valueOf(A5.class), TypeFactory.valueOf(D1.class))); + + keys.add(new MapperKey(TypeFactory.valueOf(B1.class), TypeFactory.valueOf(C5.class))); + keys.add(new MapperKey(TypeFactory.valueOf(B2.class), TypeFactory.valueOf(C4.class))); + keys.add(new MapperKey(TypeFactory.valueOf(B4.class), TypeFactory.valueOf(C2.class))); + keys.add(new MapperKey(TypeFactory.valueOf(B5.class), TypeFactory.valueOf(C1.class))); + + keys.add(new MapperKey(TypeFactory.valueOf(B1.class), TypeFactory.valueOf(D5.class))); + keys.add(new MapperKey(TypeFactory.valueOf(B2.class), TypeFactory.valueOf(D4.class))); + keys.add(new MapperKey(TypeFactory.valueOf(B4.class), TypeFactory.valueOf(D2.class))); + keys.add(new MapperKey(TypeFactory.valueOf(B5.class), TypeFactory.valueOf(D1.class))); + + keys.add(new MapperKey(TypeFactory.valueOf(C1.class), TypeFactory.valueOf(D5.class))); + keys.add(new MapperKey(TypeFactory.valueOf(C2.class), TypeFactory.valueOf(D4.class))); + keys.add(new MapperKey(TypeFactory.valueOf(C4.class), TypeFactory.valueOf(D2.class))); + keys.add(new MapperKey(TypeFactory.valueOf(C5.class), TypeFactory.valueOf(D1.class))); + + Collections.shuffle(keys); + mapperKeys = new ConcurrentLinkedQueue<>(keys); + initialSize = mapperKeys.size(); + sortedCollection = new SortedCollection<>(Ordering.MAPPER_KEY); + } + + @Test + @Concurrent(200) + public void testOrdering() { + try { + while (!mapperKeys.isEmpty()) + sortedCollection.add(mapperKeys.remove()); + } catch (NoSuchElementException e) { + + } + } + + @AfterClass + public static void teardown() { + Assert.assertEquals(initialSize, sortedCollection.size()); + + Set seen = new HashSet<>(); + for (MapperKey key : sortedCollection) { + for (MapperKey seenKey : seen) { + if ((seenKey.getAType().isAssignableFrom(key.getAType()) && seenKey.getBType().isAssignableFrom(key.getBType())) + || (seenKey.getAType().isAssignableFrom(key.getBType()) && seenKey.getBType().isAssignableFrom(key.getAType()))) { + Assert.fail("saw a parent " + seenKey + " before it's child " + key); + } + } + seen.add(key); + } + } + + public static class A1 { + + } + + public static class A2 extends A1 { + + } + + public static class A3 extends A2 { + + } + + public static class A4 extends A3 { + + } + + public static class A5 extends A4 { + + } + + public static class B1 { + + } + + public static class B2 extends B1 { + + } + + public static class B3 extends B2 { + + } + + public static class B4 extends B3 { + + } + + public static class B5 extends B4 { + + } + + public static class C1 { + + } + + public static class C2 extends C1 { + + } + + public static class C3 extends C2 { + + } + + public static class C4 extends C3 { + + } + + public static class C5 extends C4 { + + } + + public static class D1 { + + } + + public static class D2 extends D1 { + + } + + public static class D3 extends D2 { + + } + + public static class D4 extends D3 { + + } + + public static class D5 extends D4 { + + } + +} diff --git a/core/src/test/java/ma/glasnost/orika/test/util/SortedCollectionTestCase.java b/core/src/test/java/ma/glasnost/orika/test/util/SortedCollectionTestCase.java new file mode 100644 index 00000000..075bb355 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/util/SortedCollectionTestCase.java @@ -0,0 +1,291 @@ +/* + * Orika - simpler, better and faster Java bean mapping + * + * Copyright (C) 2011-2013 Orika 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 ma.glasnost.orika.test.util; + +import ma.glasnost.orika.metadata.MapperKey; +import ma.glasnost.orika.metadata.TypeFactory; +import ma.glasnost.orika.util.Ordering; +import ma.glasnost.orika.util.Ordering.OrderingRelation; +import ma.glasnost.orika.util.SortedCollection; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +/** + * @author matt.deboer@gmail.com + * + */ +public class SortedCollectionTestCase { + + public static class A1 { + + } + + public static class A2 extends A1 { + + } + + public static class A3 extends A2 { + + } + + public static class A4 extends A3 { + + } + + public static class A5 extends A4 { + + } + + public static class B1 { + + } + + public static class B2 extends B1 { + + } + + public static class B3 extends B2 { + + } + + public static class B4 extends B3 { + + } + + public static class B5 extends B4 { + + } + + public static class C1 { + + } + + public static class C2 extends C1 { + + } + + public static class C3 extends C2 { + + } + + public static class C4 extends C3 { + + } + + public static class C5 extends C4 { + + } + + public static class D1 { + + } + + public static class D2 extends D1 { + + } + + public static class D3 extends D2 { + + } + + public static class D4 extends D3 { + + } + + public static class D5 extends D4 { + + } + + @Test + public void simpleOrdering() { + final OrderingRelation[][] relations = new OrderingRelation[][] { + { OrderingRelation.EQUAL, OrderingRelation.AFTER, OrderingRelation.UNDEFINED, OrderingRelation.UNDEFINED }, + { OrderingRelation.BEFORE, OrderingRelation.EQUAL, OrderingRelation.AFTER, OrderingRelation.UNDEFINED }, + { OrderingRelation.UNDEFINED, OrderingRelation.BEFORE, OrderingRelation.EQUAL, OrderingRelation.AFTER }, + { OrderingRelation.UNDEFINED, OrderingRelation.UNDEFINED, OrderingRelation.BEFORE, OrderingRelation.EQUAL } + }; + Ordering testOrdering = new Ordering() { + @Override + public OrderingRelation order(Integer object1, Integer object2) { + int val1 = object1; + int val2 = object2; + return relations[val1][val2]; + } + }; + SortedCollection sorted = new SortedCollection<>(Arrays.asList(3, 1, 0, 2), testOrdering); + Assert.assertEquals(Arrays.asList(0, 1, 2, 3), new ArrayList<>(sorted)); + } + + @Test + public void testOrdering2() { + + Set set = new HashSet<>(); + + set.add(new MapperKey(TypeFactory.valueOf(A1.class), TypeFactory.valueOf(B1.class))); + set.add(new MapperKey(TypeFactory.valueOf(A2.class), TypeFactory.valueOf(B2.class))); + set.add(new MapperKey(TypeFactory.valueOf(A3.class), TypeFactory.valueOf(B3.class))); + set.add(new MapperKey(TypeFactory.valueOf(A4.class), TypeFactory.valueOf(B4.class))); + set.add(new MapperKey(TypeFactory.valueOf(A5.class), TypeFactory.valueOf(B5.class))); + + set.add(new MapperKey(TypeFactory.valueOf(A1.class), TypeFactory.valueOf(C1.class))); + set.add(new MapperKey(TypeFactory.valueOf(A2.class), TypeFactory.valueOf(C2.class))); + set.add(new MapperKey(TypeFactory.valueOf(A3.class), TypeFactory.valueOf(C3.class))); + set.add(new MapperKey(TypeFactory.valueOf(A4.class), TypeFactory.valueOf(C4.class))); + set.add(new MapperKey(TypeFactory.valueOf(A5.class), TypeFactory.valueOf(C5.class))); + + set.add(new MapperKey(TypeFactory.valueOf(A1.class), TypeFactory.valueOf(D1.class))); + set.add(new MapperKey(TypeFactory.valueOf(A2.class), TypeFactory.valueOf(D2.class))); + set.add(new MapperKey(TypeFactory.valueOf(A3.class), TypeFactory.valueOf(D3.class))); + set.add(new MapperKey(TypeFactory.valueOf(A4.class), TypeFactory.valueOf(D4.class))); + set.add(new MapperKey(TypeFactory.valueOf(A5.class), TypeFactory.valueOf(D5.class))); + + set.add(new MapperKey(TypeFactory.valueOf(B1.class), TypeFactory.valueOf(C1.class))); + set.add(new MapperKey(TypeFactory.valueOf(B2.class), TypeFactory.valueOf(C2.class))); + set.add(new MapperKey(TypeFactory.valueOf(B3.class), TypeFactory.valueOf(C3.class))); + set.add(new MapperKey(TypeFactory.valueOf(B4.class), TypeFactory.valueOf(C4.class))); + set.add(new MapperKey(TypeFactory.valueOf(B5.class), TypeFactory.valueOf(C5.class))); + + set.add(new MapperKey(TypeFactory.valueOf(B1.class), TypeFactory.valueOf(D1.class))); + set.add(new MapperKey(TypeFactory.valueOf(B2.class), TypeFactory.valueOf(D2.class))); + set.add(new MapperKey(TypeFactory.valueOf(B3.class), TypeFactory.valueOf(D3.class))); + set.add(new MapperKey(TypeFactory.valueOf(B4.class), TypeFactory.valueOf(D4.class))); + set.add(new MapperKey(TypeFactory.valueOf(B5.class), TypeFactory.valueOf(D5.class))); + + set.add(new MapperKey(TypeFactory.valueOf(C1.class), TypeFactory.valueOf(D1.class))); + set.add(new MapperKey(TypeFactory.valueOf(C2.class), TypeFactory.valueOf(D2.class))); + set.add(new MapperKey(TypeFactory.valueOf(C3.class), TypeFactory.valueOf(D3.class))); + set.add(new MapperKey(TypeFactory.valueOf(C4.class), TypeFactory.valueOf(D4.class))); + set.add(new MapperKey(TypeFactory.valueOf(C5.class), TypeFactory.valueOf(D5.class))); + + // ~~~~~~~~~~~~~~~~~~ + // Add some mismatched mapper keys, in attempt to confuse the ordering + // process + + set.add(new MapperKey(TypeFactory.valueOf(A1.class), TypeFactory.valueOf(B5.class))); + set.add(new MapperKey(TypeFactory.valueOf(A2.class), TypeFactory.valueOf(B4.class))); + set.add(new MapperKey(TypeFactory.valueOf(A4.class), TypeFactory.valueOf(B2.class))); + set.add(new MapperKey(TypeFactory.valueOf(A5.class), TypeFactory.valueOf(B1.class))); + + set.add(new MapperKey(TypeFactory.valueOf(A1.class), TypeFactory.valueOf(C5.class))); + set.add(new MapperKey(TypeFactory.valueOf(A2.class), TypeFactory.valueOf(C4.class))); + set.add(new MapperKey(TypeFactory.valueOf(A4.class), TypeFactory.valueOf(C2.class))); + set.add(new MapperKey(TypeFactory.valueOf(A5.class), TypeFactory.valueOf(C1.class))); + + set.add(new MapperKey(TypeFactory.valueOf(A1.class), TypeFactory.valueOf(D5.class))); + set.add(new MapperKey(TypeFactory.valueOf(A2.class), TypeFactory.valueOf(D4.class))); + set.add(new MapperKey(TypeFactory.valueOf(A4.class), TypeFactory.valueOf(D2.class))); + set.add(new MapperKey(TypeFactory.valueOf(A5.class), TypeFactory.valueOf(D1.class))); + + set.add(new MapperKey(TypeFactory.valueOf(B1.class), TypeFactory.valueOf(C5.class))); + set.add(new MapperKey(TypeFactory.valueOf(B2.class), TypeFactory.valueOf(C4.class))); + set.add(new MapperKey(TypeFactory.valueOf(B4.class), TypeFactory.valueOf(C2.class))); + set.add(new MapperKey(TypeFactory.valueOf(B5.class), TypeFactory.valueOf(C1.class))); + + set.add(new MapperKey(TypeFactory.valueOf(B1.class), TypeFactory.valueOf(D5.class))); + set.add(new MapperKey(TypeFactory.valueOf(B2.class), TypeFactory.valueOf(D4.class))); + set.add(new MapperKey(TypeFactory.valueOf(B4.class), TypeFactory.valueOf(D2.class))); + set.add(new MapperKey(TypeFactory.valueOf(B5.class), TypeFactory.valueOf(D1.class))); + + set.add(new MapperKey(TypeFactory.valueOf(C1.class), TypeFactory.valueOf(D5.class))); + set.add(new MapperKey(TypeFactory.valueOf(C2.class), TypeFactory.valueOf(D4.class))); + set.add(new MapperKey(TypeFactory.valueOf(C4.class), TypeFactory.valueOf(D2.class))); + set.add(new MapperKey(TypeFactory.valueOf(C5.class), TypeFactory.valueOf(D1.class))); + + SortedCollection queue = new SortedCollection<>(Ordering.MAPPER_KEY); + + queue.addAll(set); + + Assert.assertEquals(set.size(), queue.size()); + + Set seen = new HashSet<>(); + for (MapperKey key : queue) { + for (MapperKey seenKey : seen) { + if ((seenKey.getAType().isAssignableFrom(key.getAType()) && seenKey.getBType().isAssignableFrom(key.getBType())) + || (seenKey.getAType().isAssignableFrom(key.getBType()) && seenKey.getBType().isAssignableFrom(key.getAType()))) { + Assert.fail("saw a parent " + seenKey + " before it's child " + key); + } + } + seen.add(key); + } + } + + @Test + public void testOrdering3() { + + Set set = new HashSet<>(); + + set.add(new MapperKey(TypeFactory.valueOf(A1.class), TypeFactory.valueOf(B1.class))); + set.add(new MapperKey(TypeFactory.valueOf(A2.class), TypeFactory.valueOf(B2.class))); + set.add(new MapperKey(TypeFactory.valueOf(A3.class), TypeFactory.valueOf(B3.class))); + set.add(new MapperKey(TypeFactory.valueOf(A4.class), TypeFactory.valueOf(B4.class))); + set.add(new MapperKey(TypeFactory.valueOf(A5.class), TypeFactory.valueOf(B5.class))); + + set.add(new MapperKey(TypeFactory.valueOf(A1.class), TypeFactory.valueOf(C1.class))); + set.add(new MapperKey(TypeFactory.valueOf(A2.class), TypeFactory.valueOf(C2.class))); + set.add(new MapperKey(TypeFactory.valueOf(A3.class), TypeFactory.valueOf(C3.class))); + set.add(new MapperKey(TypeFactory.valueOf(A4.class), TypeFactory.valueOf(C4.class))); + set.add(new MapperKey(TypeFactory.valueOf(A5.class), TypeFactory.valueOf(C5.class))); + + set.add(new MapperKey(TypeFactory.valueOf(A1.class), TypeFactory.valueOf(D1.class))); + set.add(new MapperKey(TypeFactory.valueOf(A2.class), TypeFactory.valueOf(D2.class))); + set.add(new MapperKey(TypeFactory.valueOf(A3.class), TypeFactory.valueOf(D3.class))); + set.add(new MapperKey(TypeFactory.valueOf(A4.class), TypeFactory.valueOf(D4.class))); + set.add(new MapperKey(TypeFactory.valueOf(A5.class), TypeFactory.valueOf(D5.class))); + + set.add(new MapperKey(TypeFactory.valueOf(B1.class), TypeFactory.valueOf(C1.class))); + set.add(new MapperKey(TypeFactory.valueOf(B2.class), TypeFactory.valueOf(C2.class))); + set.add(new MapperKey(TypeFactory.valueOf(B3.class), TypeFactory.valueOf(C3.class))); + set.add(new MapperKey(TypeFactory.valueOf(B4.class), TypeFactory.valueOf(C4.class))); + set.add(new MapperKey(TypeFactory.valueOf(B5.class), TypeFactory.valueOf(C5.class))); + + set.add(new MapperKey(TypeFactory.valueOf(B1.class), TypeFactory.valueOf(D1.class))); + set.add(new MapperKey(TypeFactory.valueOf(B2.class), TypeFactory.valueOf(D2.class))); + set.add(new MapperKey(TypeFactory.valueOf(B3.class), TypeFactory.valueOf(D3.class))); + set.add(new MapperKey(TypeFactory.valueOf(B4.class), TypeFactory.valueOf(D4.class))); + set.add(new MapperKey(TypeFactory.valueOf(B5.class), TypeFactory.valueOf(D5.class))); + + set.add(new MapperKey(TypeFactory.valueOf(C1.class), TypeFactory.valueOf(D1.class))); + set.add(new MapperKey(TypeFactory.valueOf(C2.class), TypeFactory.valueOf(D2.class))); + set.add(new MapperKey(TypeFactory.valueOf(C3.class), TypeFactory.valueOf(D3.class))); + set.add(new MapperKey(TypeFactory.valueOf(C4.class), TypeFactory.valueOf(D4.class))); + set.add(new MapperKey(TypeFactory.valueOf(C5.class), TypeFactory.valueOf(D5.class))); + + + SortedCollection queue = new SortedCollection<>(Ordering.MAPPER_KEY); + + queue.addAll(set); + + Assert.assertEquals(set.size(), queue.size()); + + Set seen = new HashSet<>(); + for (MapperKey key : queue) { + for (MapperKey seenKey : seen) { + if ((seenKey.getAType().isAssignableFrom(key.getAType()) && seenKey.getBType().isAssignableFrom(key.getBType())) + || (seenKey.getAType().isAssignableFrom(key.getBType()) && seenKey.getBType().isAssignableFrom(key.getAType()))) { + Assert.fail("saw a parent " + seenKey + " before it's child " + key); + } + } + seen.add(key); + } + } +} diff --git a/core/src/test/java/ma/glasnost/orika/test/util/StringUtilTest.java b/core/src/test/java/ma/glasnost/orika/test/util/StringUtilTest.java new file mode 100644 index 00000000..e571d704 --- /dev/null +++ b/core/src/test/java/ma/glasnost/orika/test/util/StringUtilTest.java @@ -0,0 +1,46 @@ +package ma.glasnost.orika.test.util; + +import org.junit.Test; + +import ma.glasnost.orika.impl.util.StringUtil; + +import static ma.glasnost.orika.impl.util.StringUtil.toValidVariableName; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +public class StringUtilTest { + private static final String FOO_UNCAP = "foo"; + private static final String FOO_CAP = "Foo"; + + @Test + public void to_valid_variable_name_replaces_all_invalid_characters_with_underscore() { + assertEquals("foo_bar_baz", toValidVariableName("foo/bar baz")); + } + + @Test + public void to_valid_variable_name_add_underscore__when_string_start_with_number() { + assertEquals("_42", toValidVariableName("42")); + } + + /** + * Remark: Copied from commons-lang3 v3.5 + */ + @Test + public void testUnCapitalize() { + assertNull(StringUtil.uncapitalize(null)); + + assertEquals("uncapitalize(String) failed", + FOO_UNCAP, StringUtil.uncapitalize(FOO_CAP)); + assertEquals("uncapitalize(string) failed", + FOO_UNCAP, StringUtil.uncapitalize(FOO_UNCAP)); + assertEquals("uncapitalize(empty-string) failed", + "", StringUtil.uncapitalize("")); + assertEquals("uncapitalize(single-char-string) failed", + "x", StringUtil.uncapitalize("X")); + + // Examples from uncapitalize Javadoc + assertEquals("cat", StringUtil.uncapitalize("cat")); + assertEquals("cat", StringUtil.uncapitalize("Cat")); + assertEquals("cAT", StringUtil.uncapitalize("CAT")); + } +} diff --git a/core/src/test/resources/HibernateProxyTestCase-context.xml b/core/src/test/resources/HibernateProxyTestCase-context.xml new file mode 100644 index 00000000..254ecfb3 --- /dev/null +++ b/core/src/test/resources/HibernateProxyTestCase-context.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + ma.glasnost.orika.test.unenhance.Author + ma.glasnost.orika.test.unenhance.Book + ma.glasnost.orika.test.unenhance.inheritance.AbstractEntity + ma.glasnost.orika.test.unenhance.inheritance.MyEntity + ma.glasnost.orika.test.unenhance.inheritance.Sub1Entity + ma.glasnost.orika.test.unenhance.inheritance.Sub2Entity + ma.glasnost.orika.test.unenhance.inheritance2.AbstractEntity + ma.glasnost.orika.test.unenhance.inheritance2.RoomEntity + ma.glasnost.orika.test.unenhance.inheritance2.PersonEntity + ma.glasnost.orika.test.unenhance.inheritance2.OwnerEntity + + + + + hibernate.dialect=org.hibernate.dialect.H2Dialect + hibernate.hbm2ddl.auto = create-drop + + + + + + + + \ No newline at end of file diff --git a/core/src/test/resources/Issue20TestCase-context.xml b/core/src/test/resources/Issue20TestCase-context.xml new file mode 100644 index 00000000..d7dc081d --- /dev/null +++ b/core/src/test/resources/Issue20TestCase-context.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + ma.glasnost.orika.test.community.issue20.User + ma.glasnost.orika.test.community.issue20.UsrGroup + + + + + hibernate.dialect=org.hibernate.dialect.H2Dialect + hibernate.hbm2ddl.auto = create-drop + + + + + + + + \ No newline at end of file diff --git a/core/src/test/resources/Issue21TestCase-context.xml b/core/src/test/resources/Issue21TestCase-context.xml new file mode 100644 index 00000000..c66fe5e3 --- /dev/null +++ b/core/src/test/resources/Issue21TestCase-context.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + ma.glasnost.orika.test.community.issue21.User + ma.glasnost.orika.test.community.issue21.UserGroup + ma.glasnost.orika.test.community.issue21.Authority + + + + + hibernate.dialect=org.hibernate.dialect.H2Dialect + hibernate.hbm2ddl.auto = create-drop + + + + + + + + \ No newline at end of file diff --git a/core/src/test/resources/logback-test.xml b/core/src/test/resources/logback-test.xml new file mode 100644 index 00000000..da590713 --- /dev/null +++ b/core/src/test/resources/logback-test.xml @@ -0,0 +1,40 @@ + + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + + + +