├── .gitignore ├── .travis.yml ├── LICENSE.txt ├── README.md ├── datatypes ├── pom.xml └── src │ ├── main │ └── java │ │ └── org │ │ └── modelmapper │ │ └── module │ │ └── jdk8 │ │ ├── FromOptionalConverter.java │ │ ├── FromOptionalToOptionalConverter.java │ │ ├── Jdk8Module.java │ │ └── ToOptionalConverter.java │ └── test │ └── java │ └── org │ └── modelmapper │ └── module │ └── jdk8 │ ├── FromOptionalConverterTest.java │ ├── FromOptionalToOptionalConverterTest.java │ └── ToOptionalConverterTest.java ├── datetime ├── pom.xml └── src │ ├── main │ └── java │ │ └── org │ │ └── modelmapper │ │ └── module │ │ └── jsr310 │ │ ├── FromTemporalConverter.java │ │ ├── Jsr310Module.java │ │ ├── Jsr310ModuleConfig.java │ │ ├── TemporalToTemporalConverter.java │ │ └── ToTemporalConverter.java │ └── test │ └── java │ └── org │ └── modelmapper │ └── module │ └── jsr310 │ ├── FromInstantConverterTest.java │ ├── FromLocalDateConverterTest.java │ ├── FromLocalDateTimeConverterTest.java │ ├── FromOffsetDateTimeConverterTest.java │ ├── FromZonedDateTimeConverterTest.java │ ├── Jsr310ModuleTest.java │ ├── TestHelper.java │ ├── ToInstantConverterTest.java │ ├── ToLocalDateConverterTest.java │ ├── ToLocalDateTimeConverterTest.java │ ├── ToOffsetDateTimeConverterTest.java │ └── ToZonedDateTimeConverterTest.java └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | target/ 3 | docs/ 4 | test-output/ 5 | release.properties 6 | .project 7 | .classpath 8 | .settings/ 9 | _site/ 10 | user-manual/ 11 | .idea 12 | *.iml -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | sudo: required 3 | dist: trusty 4 | 5 | jdk: 6 | - oraclejdk8 7 | - oraclejdk9 8 | 9 | notifications: 10 | email: false 11 | 12 | # whitelist 13 | branches: 14 | only: 15 | - master 16 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ModelMapper Module for Java8 2 | 3 | [![Build Status](https://travis-ci.org/modelmapper/modelmapper-module-java8.svg)](https://travis-ci.org/modelmapper/modelmapper-module-java8) 4 | [![License](http://img.shields.io/:license-apache-brightgreen.svg)](http://www.apache.org/licenses/LICENSE-2.0.html) 5 | [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.github.chhsiao90/modelmapper-module-java8/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.github.chhsiao90/modelmapper-module-java8) 6 | 7 | This is a module for [ModelMapper](http://modelmapper.org) to support Java 8 features. 8 | 9 | ## Java 8 Date/Time 10 | 11 | ### Registers the module 12 | 13 | ```java 14 | modelMapper.registerModule(new Jsr310Module()); 15 | ``` 16 | 17 | ### Configuration 18 | 19 | We also support for configuration. 20 | 21 | ```java 22 | // using String patterns 23 | Jsr310ModuleConfig config = Jsr310ModuleConfig.builder() 24 | .dateTimePattern("yyyy-MM-dd HH:mm:ss") // default is yyyy-MM-dd HH:mm:ss 25 | .datePattern("yyyy-MM-dd") // default is yyyy-MM-dd 26 | .zoneId(ZoneOffset.UTC) // default is ZoneId.systemDefault() 27 | .build() 28 | modelMapper.registerModule(new Jsr310Module(config)); 29 | ``` 30 | ```java 31 | // using DateTimeFormatter directly 32 | Jsr310ModuleConfig config = Jsr310ModuleConfig.builder() 33 | .dateTimeFormatter(DateTimeFormatter.ISO_LOCAL_DATE_TIME) 34 | .dateFormatter(DateTimeFormatter.ISO_LOCAL_DATE) 35 | .zoneId(ZoneOffset.UTC) 36 | .build() 37 | modelMapper.registerModule(new Jsr310Module(config)); 38 | ``` 39 | 40 | ### Support Mappings 41 | 42 | | Source Type | Destination Type | 43 | |---------------|------------------| 44 | | LocalDateTime | String | 45 | | LocalDateTime | Long/long | 46 | | LocalDateTime | BigDecimal | 47 | | LocalDateTime | BigInteger | 48 | | LocalDateTime | Date | 49 | | LocalDateTime | Calendar | 50 | | LocalDate | String | 51 | | LocalDate | Long/long | 52 | | LocalDate | BigDecimal | 53 | | LocalDate | BigInteger | 54 | | LocalDate | Date | 55 | | LocalDate | Calendar | 56 | | OffsetDateTime| String | 57 | | OffsetDateTime| Long/long | 58 | | OffsetDateTime| BigDecimal | 59 | | OffsetDateTime| BigInteger | 60 | | OffsetDateTime| Date | 61 | | OffsetDateTime| Calendar | 62 | | Instant | String | 63 | | Instant | Long/long | 64 | | Instant | BigDecimal | 65 | | Instant | BigInteger | 66 | | Instant | Date | 67 | | Instant | Calendar | 68 | | String | LocalDateTime | 69 | | Long/long | LocalDateTime | 70 | | BigDecimal | LocalDateTime | 71 | | BigInteger | LocalDateTime | 72 | | Date | LocalDateTime | 73 | | Calendar | LocalDateTime | 74 | | String | DateTime | 75 | | Long/long | DateTime | 76 | | BigDecimal | DateTime | 77 | | BigInteger | DateTime | 78 | | Date | DateTime | 79 | | Calendar | DateTime | 80 | | String | OffsetDateTime | 81 | | Long/long | OffsetDateTime | 82 | | BigDecimal | OffsetDateTime | 83 | | BigInteger | OffsetDateTime | 84 | | Date | OffsetDateTime | 85 | | Calendar | OffsetDateTime | 86 | | String | Instant | 87 | | Long/long | Instant | 88 | | BigDecimal | Instant | 89 | | BigInteger | Instant | 90 | | Date | Instant | 91 | | Calendar | Instant | 92 | -------------------------------------------------------------------------------- /datatypes/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | org.modelmapper 5 | modelmapper-module-java8 6 | 1.2.4-SNAPSHOT 7 | 8 | 4.0.0 9 | modelmapper-module-java8-datatypes 10 | ModelMapper Module Java8 Data Types 11 | ModelMapper Module for Java8 Data Types 12 | 13 | 14 | org.modelmapper 15 | modelmapper 16 | 17 | 18 | org.projectlombok 19 | lombok 20 | true 21 | 22 | 23 | -------------------------------------------------------------------------------- /datatypes/src/main/java/org/modelmapper/module/jdk8/FromOptionalConverter.java: -------------------------------------------------------------------------------- 1 | package org.modelmapper.module.jdk8; 2 | 3 | import java.util.Optional; 4 | import org.modelmapper.spi.ConditionalConverter; 5 | import org.modelmapper.spi.MappingContext; 6 | 7 | /** 8 | * Converts {@link Optional} to {@link Object} 9 | * 10 | * @author Chun Han Hsiao 11 | */ 12 | public class FromOptionalConverter implements ConditionalConverter, Object> { 13 | @Override 14 | public MatchResult match(Class sourceType, Class destinationType) { 15 | return (Optional.class.equals(sourceType) && !Optional.class.equals(destinationType)) 16 | ? MatchResult.FULL 17 | : MatchResult.NONE; 18 | } 19 | 20 | @Override 21 | public Object convert(MappingContext, Object> mappingContext) { 22 | if (mappingContext.getSource() == null || !mappingContext.getSource().isPresent()) { 23 | return null; 24 | } 25 | 26 | MappingContext propertyContext = mappingContext.create( 27 | mappingContext.getSource().get(), mappingContext.getDestinationType()); 28 | return mappingContext.getMappingEngine().map(propertyContext); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /datatypes/src/main/java/org/modelmapper/module/jdk8/FromOptionalToOptionalConverter.java: -------------------------------------------------------------------------------- 1 | package org.modelmapper.module.jdk8; 2 | 3 | import org.modelmapper.internal.typetools.TypeResolver; 4 | import org.modelmapper.internal.util.Types; 5 | import org.modelmapper.spi.ConditionalConverter; 6 | import org.modelmapper.spi.Mapping; 7 | import org.modelmapper.spi.MappingContext; 8 | import org.modelmapper.spi.PropertyInfo; 9 | import org.modelmapper.spi.PropertyMapping; 10 | 11 | import java.lang.reflect.ParameterizedType; 12 | import java.util.Optional; 13 | 14 | /** 15 | * Converts {@link Optional} to {@link Optional} 16 | */ 17 | public class FromOptionalToOptionalConverter implements ConditionalConverter, Optional> { 18 | @Override 19 | public MatchResult match(Class sourceType, Class destinationType) { 20 | return (Optional.class.equals(sourceType) && Optional.class.equals(destinationType)) 21 | ? MatchResult.FULL 22 | : MatchResult.NONE; 23 | } 24 | 25 | @Override 26 | @SuppressWarnings("all") 27 | public Optional convert(MappingContext, Optional> mappingContext) { 28 | Class optionalType = getElementType(mappingContext); 29 | Optional source = mappingContext.getSource(); 30 | if (source == null) { 31 | return null; 32 | } else if (source.isPresent()) { 33 | MappingContext optionalContext = mappingContext.create(source.get(), optionalType); 34 | return Optional.ofNullable(mappingContext.getMappingEngine().map(optionalContext)); 35 | } else { 36 | return Optional.empty(); 37 | } 38 | } 39 | 40 | 41 | private Class getElementType(MappingContext, Optional> mappingContext) { 42 | Mapping mapping = mappingContext.getMapping(); 43 | if (mapping instanceof PropertyMapping) { 44 | PropertyInfo destInfo = mapping.getLastDestinationProperty(); 45 | Class elementType = TypeResolver.resolveRawArgument(destInfo.getGenericType(), 46 | destInfo.getInitialType()); 47 | return elementType == TypeResolver.Unknown.class ? Object.class : elementType; 48 | } else if (mappingContext.getGenericDestinationType() instanceof ParameterizedType) { 49 | return Types.rawTypeFor(((ParameterizedType) mappingContext.getGenericDestinationType()).getActualTypeArguments()[0]); 50 | } 51 | 52 | return Object.class; 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /datatypes/src/main/java/org/modelmapper/module/jdk8/Jdk8Module.java: -------------------------------------------------------------------------------- 1 | package org.modelmapper.module.jdk8; 2 | 3 | import org.modelmapper.ModelMapper; 4 | import org.modelmapper.Module; 5 | 6 | /** 7 | * Supports the JDK8 data types with ModelMapper 8 | * 9 | * @author Chun Han Hsiao 10 | */ 11 | public class Jdk8Module implements Module { 12 | @Override 13 | public void setupModule(ModelMapper modelMapper) { 14 | modelMapper.getConfiguration().getConverters().add(0, new FromOptionalConverter()); 15 | modelMapper.getConfiguration().getConverters().add(0, new ToOptionalConverter()); 16 | modelMapper.getConfiguration().getConverters().add(0, new FromOptionalToOptionalConverter()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /datatypes/src/main/java/org/modelmapper/module/jdk8/ToOptionalConverter.java: -------------------------------------------------------------------------------- 1 | package org.modelmapper.module.jdk8; 2 | 3 | import java.util.Optional; 4 | import org.modelmapper.internal.util.MappingContextHelper; 5 | import org.modelmapper.spi.ConditionalConverter; 6 | import org.modelmapper.spi.MappingContext; 7 | 8 | /** 9 | * Converts {@link Object} to {@link Optional} 10 | * 11 | * @author Chun Han Hsiao 12 | */ 13 | public class ToOptionalConverter implements ConditionalConverter> { 14 | @Override 15 | public MatchResult match(Class sourceType, Class destinationType) { 16 | return (!Optional.class.equals(sourceType) && Optional.class.equals(destinationType)) 17 | ? MatchResult.FULL 18 | : MatchResult.NONE; 19 | } 20 | 21 | @Override 22 | public Optional convert(MappingContext> mappingContext) { 23 | if (mappingContext.getSource() == null) { 24 | return Optional.empty(); 25 | } 26 | 27 | MappingContext propertyContext = mappingContext.create( 28 | mappingContext.getSource(), MappingContextHelper.resolveDestinationGenericType(mappingContext)); 29 | Object destination = mappingContext.getMappingEngine().map(propertyContext); 30 | return Optional.ofNullable(destination); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /datatypes/src/test/java/org/modelmapper/module/jdk8/FromOptionalConverterTest.java: -------------------------------------------------------------------------------- 1 | package org.modelmapper.module.jdk8; 2 | 3 | import static org.testng.Assert.assertEquals; 4 | import static org.testng.Assert.assertNull; 5 | 6 | import java.util.Optional; 7 | import lombok.AllArgsConstructor; 8 | import lombok.Data; 9 | import org.modelmapper.Converter; 10 | import org.modelmapper.ModelMapper; 11 | import org.testng.annotations.BeforeMethod; 12 | import org.testng.annotations.Test; 13 | 14 | @Test 15 | public class FromOptionalConverterTest { 16 | private ModelMapper modelMapper; 17 | 18 | @Data 19 | @AllArgsConstructor 20 | static class Field { 21 | private String value; 22 | } 23 | 24 | @Data 25 | static class FieldDto { 26 | private String value; 27 | } 28 | 29 | @Data 30 | @AllArgsConstructor 31 | @SuppressWarnings("all") 32 | static class Source { 33 | Optional field; 34 | } 35 | 36 | @Data 37 | static class Destination { 38 | FieldDto field; 39 | } 40 | 41 | @BeforeMethod 42 | public void setUp() { 43 | modelMapper = new ModelMapper(); 44 | modelMapper.registerModule(new Jdk8Module()); 45 | 46 | Converter upperCase = ctx -> ctx.getSource().toUpperCase(); 47 | modelMapper.emptyTypeMap(Field.class, FieldDto.class).addMappings( 48 | mapper -> mapper.using(upperCase).map(Field::getValue, FieldDto::setValue)); 49 | } 50 | 51 | 52 | public void shouldMapOptionalStringToString() { 53 | assertEquals(modelMapper.map(Optional.of("foo"), String.class), "foo"); 54 | assertNull(modelMapper.map(Optional.empty(), String.class)); 55 | } 56 | 57 | public void shouldMapOptionalStringToInteger() { 58 | assertEquals((int) modelMapper.map(Optional.of("100"), Integer.class), 100); 59 | } 60 | 61 | public void shouldMapOptionalProperty() { 62 | Destination destination = modelMapper.map(new Source(Optional.of(new Field("foo"))), Destination.class); 63 | assertEquals(destination.getField().getValue(), "FOO"); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /datatypes/src/test/java/org/modelmapper/module/jdk8/FromOptionalToOptionalConverterTest.java: -------------------------------------------------------------------------------- 1 | package org.modelmapper.module.jdk8; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import org.modelmapper.Converter; 6 | import org.modelmapper.ModelMapper; 7 | import org.modelmapper.TypeToken; 8 | import org.testng.annotations.BeforeMethod; 9 | import org.testng.annotations.Test; 10 | 11 | import java.lang.reflect.Type; 12 | import java.util.Optional; 13 | 14 | import static org.testng.Assert.assertEquals; 15 | import static org.testng.Assert.assertNull; 16 | 17 | @Test 18 | public class FromOptionalToOptionalConverterTest { 19 | private ModelMapper modelMapper; 20 | 21 | @Data 22 | @AllArgsConstructor 23 | static class Field { 24 | private String value; 25 | } 26 | 27 | @Data 28 | static class FieldDto { 29 | private String value; 30 | } 31 | 32 | @Data 33 | @AllArgsConstructor 34 | @SuppressWarnings("all") 35 | static class Source { 36 | private Optional field; 37 | } 38 | 39 | @Data 40 | @SuppressWarnings("all") 41 | static class Destination { 42 | private Optional field; 43 | } 44 | 45 | @BeforeMethod 46 | public void setUp() { 47 | modelMapper = new ModelMapper(); 48 | modelMapper.registerModule(new Jdk8Module()); 49 | 50 | Converter upperCase = ctx -> ctx.getSource().toUpperCase(); 51 | modelMapper.emptyTypeMap(Field.class, FieldDto.class).addMappings( 52 | mapper -> mapper.using(upperCase).map(Field::getValue, FieldDto::setValue)); 53 | } 54 | 55 | 56 | public void shouldMapOptionalStringToOptionalString() { 57 | assertEquals(modelMapper.map(Optional.of("foo"), Optional.class), Optional.of("foo")); 58 | assertEquals(modelMapper.map(Optional.empty(), Optional.class), Optional.empty()); 59 | } 60 | 61 | public void shouldMapOptionalStringToOptionalInteger() { 62 | Type type = new TypeToken>() {}.getType(); 63 | assertEquals(modelMapper.map(Optional.of("100"), type), Optional.of(100)); 64 | } 65 | 66 | @SuppressWarnings("all") 67 | public void shouldMapOptionalPropertyToOtherOptionalProperty() { 68 | Destination destination = modelMapper.map(new Source(Optional.of(new Field("foo"))), Destination.class); 69 | assertEquals(destination.getField().get().getValue(), "FOO"); 70 | } 71 | 72 | public void shouldMapNullToNull() { 73 | Destination destination = modelMapper.map(new Source(null), Destination.class); 74 | assertNull(destination.getField()); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /datatypes/src/test/java/org/modelmapper/module/jdk8/ToOptionalConverterTest.java: -------------------------------------------------------------------------------- 1 | package org.modelmapper.module.jdk8; 2 | 3 | import static org.testng.Assert.assertEquals; 4 | import static org.testng.Assert.assertFalse; 5 | import static org.testng.Assert.assertNull; 6 | import static org.testng.Assert.assertTrue; 7 | 8 | import java.util.Optional; 9 | import lombok.AllArgsConstructor; 10 | import lombok.Data; 11 | import org.modelmapper.Converter; 12 | import org.modelmapper.ModelMapper; 13 | import org.modelmapper.TypeToken; 14 | import org.testng.annotations.BeforeMethod; 15 | import org.testng.annotations.Test; 16 | 17 | @Test 18 | public class ToOptionalConverterTest { 19 | private ModelMapper modelMapper; 20 | 21 | @Data 22 | @AllArgsConstructor 23 | static class Field { 24 | private String value; 25 | } 26 | 27 | @Data 28 | static class FieldDto { 29 | private String value; 30 | } 31 | 32 | @Data 33 | @AllArgsConstructor 34 | static class Source { 35 | Field field; 36 | } 37 | 38 | @Data 39 | @SuppressWarnings("all") 40 | static class Destination { 41 | Optional field; 42 | } 43 | 44 | @BeforeMethod 45 | public void setUp() { 46 | modelMapper = new ModelMapper(); 47 | modelMapper.registerModule(new Jdk8Module()); 48 | 49 | Converter upperCase = ctx -> ctx.getSource().toUpperCase(); 50 | modelMapper.emptyTypeMap(Field.class, FieldDto.class).addMappings( 51 | mapper -> mapper.using(upperCase).map(Field::getValue, FieldDto::setValue)); 52 | } 53 | 54 | 55 | @SuppressWarnings("all") 56 | public void shouldMapStringToOptional() { 57 | assertEquals(modelMapper.map("foo", Optional.class).get(), "foo"); 58 | } 59 | 60 | public void shouldMapStringToOptionalInteger() { 61 | assertEquals(modelMapper.map("100", new TypeToken>() {}.getType()), Optional.of(100)); 62 | } 63 | 64 | @SuppressWarnings("all") 65 | public void shouldMapToOptionalProperty() { 66 | Destination destination = modelMapper.map(new Source(new Field("foo")), Destination.class); 67 | assertEquals(destination.getField().get().getValue(), "FOO"); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /datetime/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | org.modelmapper 5 | modelmapper-module-java8 6 | 1.2.4-SNAPSHOT 7 | 8 | jar 9 | 4.0.0 10 | modelmapper-module-jsr310 11 | ModelMapper Module JSR310 12 | ModelMapper Module for JSR310 13 | 14 | 15 | org.modelmapper 16 | modelmapper 17 | 18 | 19 | org.projectlombok 20 | lombok 21 | true 22 | 23 | 24 | -------------------------------------------------------------------------------- /datetime/src/main/java/org/modelmapper/module/jsr310/FromTemporalConverter.java: -------------------------------------------------------------------------------- 1 | package org.modelmapper.module.jsr310; 2 | 3 | import java.math.BigDecimal; 4 | import java.math.BigInteger; 5 | import java.time.*; 6 | import java.time.temporal.Temporal; 7 | import java.util.Calendar; 8 | import java.util.Date; 9 | import org.modelmapper.Converter; 10 | import org.modelmapper.internal.Errors; 11 | import org.modelmapper.spi.ConditionalConverter; 12 | import org.modelmapper.spi.MappingContext; 13 | 14 | /** 15 | * Converts {@link Temporal} to {@link Object} 16 | * 17 | * @author Chun Han Hsiao 18 | */ 19 | public class FromTemporalConverter implements ConditionalConverter { 20 | private Jsr310ModuleConfig config; 21 | private final LocalDateTimeConverter localDateTimeConverter = new LocalDateTimeConverter(); 22 | private final ZonedDateTimeConverter zonedDateTimeConverter = new ZonedDateTimeConverter(); 23 | private final LocalDateConverter localDateConverter = new LocalDateConverter(); 24 | private final OffsetDateTimeConverter offsetDateTimeConverter = new OffsetDateTimeConverter(); 25 | private final InstantConverter instantConverter = new InstantConverter(); 26 | 27 | public FromTemporalConverter(Jsr310ModuleConfig config) { 28 | this.config = config; 29 | } 30 | 31 | @Override 32 | public MatchResult match(Class sourceType, Class destinationType) { 33 | return Temporal.class.isAssignableFrom(sourceType) 34 | ? MatchResult.FULL : MatchResult.NONE; 35 | } 36 | 37 | @Override 38 | public Object convert(MappingContext mappingContext) { 39 | if (mappingContext.getSource() == null) 40 | return null; 41 | 42 | Class sourceType = mappingContext.getSourceType(); 43 | if (LocalDateTime.class.equals(sourceType)) 44 | return localDateTimeConverter.convert(mappingContext); 45 | else if (LocalDate.class.equals(sourceType)) 46 | return localDateConverter.convert(mappingContext); 47 | else if (OffsetDateTime.class.equals(sourceType)) 48 | return offsetDateTimeConverter.convert(mappingContext); 49 | else if (Instant.class.equals(sourceType)) 50 | return instantConverter.convert(mappingContext); 51 | else if (ZonedDateTime.class.equals(sourceType)) 52 | return zonedDateTimeConverter.convert(mappingContext); 53 | else 54 | throw new Errors().addMessage("Unsupported mapping types[%s->%s]", 55 | LocalDateTime.class.getName(), mappingContext.getDestinationType().getName()) 56 | .toMappingException(); 57 | } 58 | 59 | private class LocalDateTimeConverter implements Converter { 60 | @Override 61 | public Object convert(MappingContext mappingContext) { 62 | LocalDateTime source = (LocalDateTime) mappingContext.getSource(); 63 | return convertLocalDateTime(source, mappingContext); 64 | } 65 | } 66 | 67 | private class ZonedDateTimeConverter implements Converter { 68 | @Override 69 | public Object convert(MappingContext mappingContext) { 70 | ZonedDateTime source = (ZonedDateTime) mappingContext.getSource(); 71 | return convertZonedDateTime(source, mappingContext); 72 | } 73 | } 74 | 75 | private class LocalDateConverter implements Converter { 76 | @Override 77 | public Object convert(MappingContext mappingContext) { 78 | LocalDate source = (LocalDate) mappingContext.getSource(); 79 | Class destinationType = mappingContext.getDestinationType(); 80 | if (destinationType.equals(String.class)) 81 | return config.getDateFormatter() 82 | .format(source); 83 | 84 | LocalDateTime localDateTime = source.atStartOfDay(); 85 | return convertLocalDateTime(localDateTime, mappingContext); 86 | } 87 | } 88 | 89 | private class OffsetDateTimeConverter implements Converter { 90 | @Override 91 | public Object convert(MappingContext mappingContext) { 92 | OffsetDateTime source = (OffsetDateTime) mappingContext.getSource(); 93 | return convertOffsetDateTime(source, mappingContext); 94 | } 95 | } 96 | 97 | private class InstantConverter implements Converter { 98 | @Override 99 | public Object convert(MappingContext mappingContext) { 100 | Instant source = (Instant) mappingContext.getSource(); 101 | return convertInstant(source, mappingContext); 102 | } 103 | } 104 | 105 | private Object convertLocalDateTime(LocalDateTime source, MappingContext mappingContext) { 106 | Class destinationType = mappingContext.getDestinationType(); 107 | if (destinationType.equals(String.class)) 108 | return config.getDateTimeFormatter() 109 | .format(source); 110 | 111 | Instant instant = source.atZone(config.getZoneId()).toInstant(); 112 | return convertInstant(instant, mappingContext); 113 | } 114 | 115 | private Object convertZonedDateTime(ZonedDateTime source, MappingContext mappingContext) { 116 | Class destinationType = mappingContext.getDestinationType(); 117 | if (destinationType.equals(String.class)) 118 | return config.getDateTimeOffsetFormatter() 119 | .format(source); 120 | 121 | Instant instant = source.toInstant(); 122 | return convertInstant(instant, mappingContext); 123 | } 124 | 125 | 126 | private Object convertOffsetDateTime(OffsetDateTime source, MappingContext mappingContext) { 127 | Class destinationType = mappingContext.getDestinationType(); 128 | if (destinationType.equals(String.class)) 129 | return config.getDateTimeOffsetFormatter() 130 | .format(source); 131 | 132 | Instant instant = source.toInstant(); 133 | return convertInstant(instant, mappingContext); 134 | } 135 | 136 | private Object convertInstant(Instant source, MappingContext mappingContext) { 137 | Class destinationType = mappingContext.getDestinationType(); 138 | if (destinationType.equals(String.class)) 139 | return config.getDateTimeFormatter() 140 | .withZone(config.getZoneId()) 141 | .format(source); 142 | else if (Date.class.isAssignableFrom(destinationType)) 143 | return new Date(epochMilliOf(source)); 144 | else if (Calendar.class.isAssignableFrom(destinationType)) 145 | return calendarOf(source); 146 | else if (Long.class.equals(destinationType) || Long.TYPE.equals(destinationType)) 147 | return epochMilliOf(source); 148 | else if (BigDecimal.class.equals(destinationType)) 149 | return new BigDecimal(epochMilliOf(source)); 150 | else if (BigInteger.class.equals(destinationType)) 151 | return BigInteger.valueOf(epochMilliOf(source)); 152 | else 153 | throw new Errors().addMessage("Unsupported mapping types[%s->%s]", 154 | mappingContext.getSourceType().getName(), destinationType.getName()) 155 | .toMappingException(); 156 | } 157 | 158 | private long epochMilliOf(Instant instant) { 159 | return instant.toEpochMilli(); 160 | } 161 | 162 | private Calendar calendarOf(Instant instant) { 163 | Calendar calendar = Calendar.getInstance(); 164 | calendar.setTimeInMillis(epochMilliOf(instant)); 165 | return calendar; 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /datetime/src/main/java/org/modelmapper/module/jsr310/Jsr310Module.java: -------------------------------------------------------------------------------- 1 | package org.modelmapper.module.jsr310; 2 | 3 | import org.modelmapper.ModelMapper; 4 | import org.modelmapper.Module; 5 | 6 | /** 7 | * Supports the JSR310 {@code java.time} objects with ModelMapper 8 | * 9 | * @author Chun Han Hsiao 10 | */ 11 | public class Jsr310Module implements Module { 12 | private Jsr310ModuleConfig config; 13 | 14 | public Jsr310Module() { 15 | this(Jsr310ModuleConfig.builder().build()); 16 | } 17 | 18 | public Jsr310Module(Jsr310ModuleConfig config) { 19 | this.config = config; 20 | } 21 | 22 | @Override 23 | public void setupModule(ModelMapper modelMapper) { 24 | modelMapper.getConfiguration().getConverters().add(0, new FromTemporalConverter(config)); 25 | modelMapper.getConfiguration().getConverters().add(0, new ToTemporalConverter(config)); 26 | modelMapper.getConfiguration().getConverters().add(0, new TemporalToTemporalConverter()); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /datetime/src/main/java/org/modelmapper/module/jsr310/Jsr310ModuleConfig.java: -------------------------------------------------------------------------------- 1 | package org.modelmapper.module.jsr310; 2 | 3 | import java.time.ZoneId; 4 | import java.time.format.DateTimeFormatter; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | /** 10 | * Config for {@link Jsr310Module} 11 | * 12 | * @author Chun Han Hsiao 13 | */ 14 | @Data 15 | @NoArgsConstructor 16 | @AllArgsConstructor 17 | public class Jsr310ModuleConfig { 18 | private static final String DEFAULT_DATE_PATTERN = "yyyy-MM-dd"; 19 | private static final String DEFAULT_DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss"; 20 | private static final String DEFAULT_DATE_TIME_OFFSET_PATTERN = "yyyy-MM-dd HH:mm:ssX"; 21 | private static final String DEFAULT_TIME_PATTERN = "HH:mm:ss"; 22 | 23 | private DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(DEFAULT_DATE_PATTERN); 24 | private DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_PATTERN); 25 | private DateTimeFormatter dateTimeOffsetFormatter = DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_OFFSET_PATTERN); 26 | private DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern(DEFAULT_TIME_PATTERN); 27 | private ZoneId zoneId = ZoneId.systemDefault(); 28 | 29 | public void setDatePattern(String datePattern) { 30 | this.setDateFormatter(DateTimeFormatter.ofPattern(datePattern)); 31 | } 32 | 33 | public void setDateTimePattern(String dateTimePattern) { 34 | this.setDateTimeFormatter(DateTimeFormatter.ofPattern(dateTimePattern)); 35 | } 36 | 37 | public void setDateTimeOffsetPattern(String dateTimeOffsetPattern) { 38 | this.setDateTimeOffsetFormatter(DateTimeFormatter.ofPattern(dateTimeOffsetPattern)); 39 | } 40 | 41 | public void setTimePattern(String timePattern) { 42 | this.setTimeFormatter(DateTimeFormatter.ofPattern(timePattern)); 43 | } 44 | 45 | public static Jsr310ModuleConfigBuilder builder() { 46 | return new Jsr310ModuleConfigBuilder(); 47 | } 48 | 49 | public static class Jsr310ModuleConfigBuilder { 50 | 51 | private DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(DEFAULT_DATE_PATTERN); 52 | private DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_PATTERN); 53 | private DateTimeFormatter dateTimeOffsetFormatter = DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_OFFSET_PATTERN); 54 | private DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern(DEFAULT_TIME_PATTERN); 55 | private ZoneId zoneId = ZoneId.systemDefault(); 56 | 57 | public Jsr310ModuleConfigBuilder datePattern(String datePattern) { 58 | return this.dateFormatter(DateTimeFormatter.ofPattern(datePattern)); 59 | } 60 | 61 | public Jsr310ModuleConfigBuilder dateFormatter(DateTimeFormatter dateFormatter) { 62 | this.dateFormatter = dateFormatter; 63 | return this; 64 | } 65 | 66 | public Jsr310ModuleConfigBuilder dateTimePattern(String dateTimePattern) { 67 | return this.dateTimeFormatter(DateTimeFormatter.ofPattern(dateTimePattern)); 68 | } 69 | 70 | public Jsr310ModuleConfigBuilder dateTimeFormatter(DateTimeFormatter dateTimeFormatter) { 71 | this.dateTimeFormatter = dateTimeFormatter; 72 | return this; 73 | } 74 | 75 | public Jsr310ModuleConfigBuilder dateTimeOffsetPattern(String dateTimeOffsetPattern) { 76 | return this.dateTimeOffsetFormatter(DateTimeFormatter.ofPattern(dateTimeOffsetPattern)); 77 | } 78 | 79 | public Jsr310ModuleConfigBuilder dateTimeOffsetFormatter(DateTimeFormatter dateTimeOffsetFormatter) { 80 | this.dateTimeOffsetFormatter = dateTimeOffsetFormatter; 81 | return this; 82 | } 83 | 84 | public Jsr310ModuleConfigBuilder timePattern(String timePattern) { 85 | return this.timeFormatter(DateTimeFormatter.ofPattern(timePattern)); 86 | } 87 | 88 | public Jsr310ModuleConfigBuilder timeFormatter(DateTimeFormatter timeFormatter) { 89 | this.timeFormatter = timeFormatter; 90 | return this; 91 | } 92 | 93 | public Jsr310ModuleConfigBuilder zoneId(ZoneId zoneId) { 94 | this.zoneId = zoneId; 95 | return this; 96 | } 97 | 98 | public Jsr310ModuleConfig build() { 99 | return new Jsr310ModuleConfig(dateFormatter, dateTimeFormatter, dateTimeOffsetFormatter, timeFormatter, zoneId); 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /datetime/src/main/java/org/modelmapper/module/jsr310/TemporalToTemporalConverter.java: -------------------------------------------------------------------------------- 1 | package org.modelmapper.module.jsr310; 2 | 3 | import java.time.temporal.Temporal; 4 | import org.modelmapper.internal.Errors; 5 | import org.modelmapper.spi.ConditionalConverter; 6 | import org.modelmapper.spi.MappingContext; 7 | 8 | /** 9 | * Converts {@link Temporal} to {@link Temporal} 10 | * 11 | * @author Chun Han Hsiao 12 | */ 13 | public class TemporalToTemporalConverter implements ConditionalConverter { 14 | @Override 15 | public MatchResult match(Class sourceType, Class destinationType) { 16 | return Temporal.class.isAssignableFrom(sourceType) 17 | && Temporal.class.isAssignableFrom(destinationType) 18 | ? MatchResult.FULL : MatchResult.NONE; 19 | } 20 | 21 | @Override 22 | public Temporal convert(MappingContext mappingContext) { 23 | if (mappingContext.getSource() == null) 24 | return null; 25 | else if (mappingContext.getSourceType().equals(mappingContext.getDestinationType())) 26 | return mappingContext.getSource(); 27 | else 28 | throw new Errors().addMessage("Unsupported mapping types[%s->%s]", 29 | mappingContext.getSourceType().getName(), mappingContext.getDestinationType()) 30 | .toMappingException(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /datetime/src/main/java/org/modelmapper/module/jsr310/ToTemporalConverter.java: -------------------------------------------------------------------------------- 1 | package org.modelmapper.module.jsr310; 2 | 3 | import java.time.*; 4 | import java.time.temporal.Temporal; 5 | import java.util.Calendar; 6 | import java.util.Date; 7 | import org.modelmapper.Converter; 8 | import org.modelmapper.internal.Errors; 9 | import org.modelmapper.spi.ConditionalConverter; 10 | import org.modelmapper.spi.MappingContext; 11 | 12 | /** 13 | * Converts {@link Object} to {@link Temporal} 14 | * 15 | * @author Chun Han Hsiao 16 | */ 17 | public class ToTemporalConverter implements ConditionalConverter { 18 | private Jsr310ModuleConfig config; 19 | private final LocalDateTimeConverter localDateTimeConverter = new LocalDateTimeConverter(); 20 | private final ZonedDateTimeConverter zonedDateTimeConverter = new ZonedDateTimeConverter(); 21 | private final LocalDateConverter localDateConverter = new LocalDateConverter(); 22 | private final OffsetDateTimeConverter offsetDateTimeConverter = new OffsetDateTimeConverter(); 23 | private final InstantConverter instantConverter = new InstantConverter(); 24 | 25 | public ToTemporalConverter(Jsr310ModuleConfig config) { 26 | this.config = config; 27 | } 28 | 29 | @Override 30 | public MatchResult match(Class sourceType, Class destinationType) { 31 | return Temporal.class.isAssignableFrom(destinationType) 32 | ? MatchResult.FULL : MatchResult.NONE; 33 | } 34 | 35 | @Override 36 | public Temporal convert(MappingContext mappingContext) { 37 | if (mappingContext.getSource() == null) 38 | return null; 39 | 40 | Class destinationType = mappingContext.getDestinationType(); 41 | if (LocalDateTime.class.equals(destinationType)) 42 | return localDateTimeConverter.convert(mappingContext); 43 | else if (LocalDate.class.equals(destinationType)) 44 | return localDateConverter.convert(mappingContext); 45 | else if (OffsetDateTime.class.equals(destinationType)) 46 | return offsetDateTimeConverter.convert(mappingContext); 47 | else if (Instant.class.equals(destinationType)) 48 | return instantConverter.convert(mappingContext); 49 | else if (ZonedDateTime.class.equals(destinationType)) 50 | return zonedDateTimeConverter.convert(mappingContext); 51 | else 52 | throw new Errors().addMessage("Unsupported mapping types[%s->%s]", 53 | mappingContext.getSourceType().getName(), destinationType.getName()) 54 | .toMappingException(); 55 | } 56 | 57 | private class LocalDateTimeConverter implements Converter { 58 | @Override 59 | public Temporal convert(MappingContext mappingContext) { 60 | return convertLocalDateTime(mappingContext); 61 | } 62 | } 63 | 64 | private class ZonedDateTimeConverter implements Converter { 65 | @Override 66 | public Temporal convert(MappingContext mappingContext) { 67 | return convertZonedDateTime(mappingContext); 68 | } 69 | } 70 | 71 | private class LocalDateConverter implements Converter { 72 | @Override 73 | public Temporal convert(MappingContext mappingContext) { 74 | return convertLocalDate(mappingContext); 75 | } 76 | } 77 | 78 | private class OffsetDateTimeConverter implements Converter { 79 | @Override 80 | public Temporal convert(MappingContext mappingContext) { 81 | return convertOffsetDateTime(mappingContext); 82 | } 83 | } 84 | 85 | private class InstantConverter implements Converter { 86 | @Override 87 | public Temporal convert(MappingContext mappingContext) { 88 | return convertInstant(mappingContext); 89 | } 90 | } 91 | 92 | private LocalDate convertLocalDate(MappingContext mappingContext) { 93 | Object source = mappingContext.getSource(); 94 | Class sourceType = source.getClass(); 95 | if (sourceType.equals(String.class)) 96 | return LocalDate.parse((String) source, 97 | config.getDateFormatter()); 98 | return convertInstant(mappingContext).atZone(config.getZoneId()).toLocalDate(); 99 | } 100 | 101 | private LocalDateTime convertLocalDateTime(MappingContext mappingContext) { 102 | Object source = mappingContext.getSource(); 103 | Class sourceType = source.getClass(); 104 | if (sourceType.equals(String.class)) 105 | return LocalDateTime.parse((String) source, 106 | config.getDateTimeFormatter()); 107 | return convertInstant(mappingContext).atZone(config.getZoneId()).toLocalDateTime(); 108 | } 109 | 110 | private ZonedDateTime convertZonedDateTime(MappingContext mappingContext) { 111 | Object source = mappingContext.getSource(); 112 | Class sourceType = source.getClass(); 113 | if (sourceType.equals(String.class)) 114 | return ZonedDateTime.parse((String) source, 115 | config.getDateTimeOffsetFormatter()); 116 | return convertInstant(mappingContext).atZone(config.getZoneId()); 117 | } 118 | 119 | private OffsetDateTime convertOffsetDateTime(MappingContext mappingContext) { 120 | Object source = mappingContext.getSource(); 121 | Class sourceType = source.getClass(); 122 | if (sourceType.equals(String.class)) 123 | return OffsetDateTime.parse((String) source, 124 | config.getDateTimeOffsetFormatter()); 125 | return convertInstant(mappingContext).atZone(config.getZoneId()).toOffsetDateTime(); 126 | } 127 | 128 | private Instant convertInstant(MappingContext mappingContext) { 129 | Object source = mappingContext.getSource(); 130 | Class sourceType = source.getClass(); 131 | if (sourceType.equals(String.class)) 132 | return LocalDateTime.parse((String) source, 133 | config.getDateTimeFormatter()) 134 | .atZone(config.getZoneId()).toInstant(); 135 | else if (Date.class.isAssignableFrom(sourceType)) 136 | return Instant.ofEpochMilli(((Date) source).getTime()); 137 | else if (Calendar.class.isAssignableFrom(sourceType)) 138 | return Instant.ofEpochMilli(((Calendar) source).getTime().getTime()); 139 | else if (Number.class.isAssignableFrom(sourceType)) 140 | return Instant.ofEpochMilli(((Number) source).longValue()); 141 | else 142 | throw new Errors().addMessage("Unsupported mapping types[%s->%s]", 143 | sourceType.getName(), mappingContext.getDestinationType().getName()) 144 | .toMappingException(); 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /datetime/src/test/java/org/modelmapper/module/jsr310/FromInstantConverterTest.java: -------------------------------------------------------------------------------- 1 | package org.modelmapper.module.jsr310; 2 | 3 | import static org.testng.Assert.assertEquals; 4 | import static org.testng.Assert.assertNull; 5 | 6 | import java.math.BigDecimal; 7 | import java.math.BigInteger; 8 | import java.time.Instant; 9 | import java.time.ZoneOffset; 10 | import java.util.Calendar; 11 | import java.util.Date; 12 | import org.modelmapper.spi.ConditionalConverter; 13 | import org.testng.annotations.BeforeMethod; 14 | import org.testng.annotations.Test; 15 | 16 | @Test 17 | public class FromInstantConverterTest { 18 | 19 | private Jsr310ModuleConfig config; 20 | private ConditionalConverter converter; 21 | 22 | @BeforeMethod 23 | public void setUp() { 24 | config = Jsr310ModuleConfig.builder() 25 | .zoneId(ZoneOffset.UTC) 26 | .build(); 27 | converter = TestHelper.unsafe(new FromTemporalConverter(config)); 28 | } 29 | 30 | public void shouldConvertToDefaultString() { 31 | Instant source = TestHelper.instantOf(2018, 1, 1); 32 | String dateText = (String) converter.convert(TestHelper.unsafeMappingContext(source, Instant.class, String.class)); 33 | assertEquals(dateText, "2018-01-01 00:00:00"); 34 | } 35 | 36 | public void shouldConvertToStringWithPattern() { 37 | config.setDateTimePattern("yyyy-MM-dd HH:mm:ss.SSS"); 38 | Instant source = TestHelper.instantOf(2018, 1, 1); 39 | String dateText = (String) converter.convert(TestHelper.unsafeMappingContext(source, Instant.class, String.class)); 40 | assertEquals(dateText, "2018-01-01 00:00:00.000"); 41 | } 42 | 43 | public void shouldConvertToLong() { 44 | Instant source = TestHelper.instantOf(2018, 1, 1); 45 | long timestamp = (Long) converter.convert(TestHelper.unsafeMappingContext(source, Instant.class, Long.class)); 46 | assertEquals(timestamp, 1514764800000L); 47 | } 48 | 49 | public void shouldConvertToBigDecimal() { 50 | Instant source = TestHelper.instantOf(2018, 1, 1); 51 | BigDecimal timestamp = (BigDecimal) converter.convert(TestHelper.unsafeMappingContext(source, Instant.class, BigDecimal.class)); 52 | assertEquals(timestamp.longValue(), 1514764800000L); 53 | } 54 | 55 | public void shouldConvertToBigInteger() { 56 | Instant source = TestHelper.instantOf(2018, 1, 1); 57 | BigInteger timestamp = (BigInteger) converter.convert(TestHelper.unsafeMappingContext(source, Instant.class, BigInteger.class)); 58 | assertEquals(timestamp.longValue(), 1514764800000L); 59 | } 60 | 61 | public void shouldConvertToDate() { 62 | Instant source = TestHelper.instantOf(2018, 1, 1); 63 | Date timestamp = (Date) converter.convert(TestHelper.unsafeMappingContext(source, Instant.class, Date.class)); 64 | assertEquals(timestamp.getTime(), 1514764800000L); 65 | } 66 | 67 | public void shouldConvertToCalendar() { 68 | Instant source = TestHelper.instantOf(2018, 1, 1); 69 | Calendar timestamp = (Calendar) converter.convert(TestHelper.unsafeMappingContext(source, Instant.class, Calendar.class)); 70 | assertEquals(timestamp.getTime().getTime(), 1514764800000L); 71 | } 72 | 73 | public void shouldConvertNull() { 74 | Calendar timestamp = (Calendar) converter.convert(TestHelper.unsafeMappingContext(null, Instant.class, Calendar.class)); 75 | assertNull(timestamp); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /datetime/src/test/java/org/modelmapper/module/jsr310/FromLocalDateConverterTest.java: -------------------------------------------------------------------------------- 1 | package org.modelmapper.module.jsr310; 2 | 3 | import static org.testng.Assert.assertEquals; 4 | import static org.testng.Assert.assertNull; 5 | 6 | import java.math.BigDecimal; 7 | import java.math.BigInteger; 8 | import java.time.LocalDate; 9 | import java.time.ZoneOffset; 10 | import java.util.Calendar; 11 | import java.util.Date; 12 | import org.modelmapper.spi.ConditionalConverter; 13 | import org.testng.annotations.BeforeMethod; 14 | import org.testng.annotations.Test; 15 | 16 | @Test 17 | public class FromLocalDateConverterTest { 18 | 19 | private Jsr310ModuleConfig config; 20 | private ConditionalConverter converter; 21 | 22 | @BeforeMethod 23 | public void setUp() { 24 | config = Jsr310ModuleConfig.builder() 25 | .zoneId(ZoneOffset.UTC) 26 | .build(); 27 | converter = TestHelper.unsafe(new FromTemporalConverter(config)); 28 | } 29 | 30 | public void shouldConvertToDefaultString() { 31 | LocalDate source = TestHelper.instantOf(2018, 1, 1) 32 | .atZone(ZoneOffset.UTC) 33 | .toLocalDate(); 34 | String dateText = (String) converter.convert(TestHelper.unsafeMappingContext(source, LocalDate.class, String.class)); 35 | assertEquals(dateText, "2018-01-01"); 36 | } 37 | 38 | public void shouldConvertToStringWithPattern() { 39 | config.setDatePattern("yyyy/MM/dd"); 40 | LocalDate source = TestHelper.instantOf(2018, 1, 1) 41 | .atZone(ZoneOffset.UTC) 42 | .toLocalDate(); 43 | String dateText = (String) converter.convert(TestHelper.unsafeMappingContext(source, LocalDate.class, String.class)); 44 | assertEquals(dateText, "2018/01/01"); 45 | } 46 | 47 | public void shouldConvertToLong() { 48 | LocalDate source = TestHelper.instantOf(2018, 1, 1) 49 | .atZone(ZoneOffset.UTC) 50 | .toLocalDate(); 51 | long timestamp = (Long) converter.convert(TestHelper.unsafeMappingContext(source, LocalDate.class, Long.class)); 52 | assertEquals(timestamp, 1514764800000L); 53 | } 54 | 55 | public void shouldConvertToBigDecimal() { 56 | LocalDate source = TestHelper.instantOf(2018, 1, 1) 57 | .atZone(ZoneOffset.UTC) 58 | .toLocalDate(); 59 | BigDecimal timestamp = (BigDecimal) converter.convert(TestHelper.unsafeMappingContext(source, LocalDate.class, BigDecimal.class)); 60 | assertEquals(timestamp.longValue(), 1514764800000L); 61 | } 62 | 63 | public void shouldConvertToBigInteger() { 64 | LocalDate source = TestHelper.instantOf(2018, 1, 1) 65 | .atZone(ZoneOffset.UTC) 66 | .toLocalDate(); 67 | BigInteger timestamp = (BigInteger) converter.convert(TestHelper.unsafeMappingContext(source, LocalDate.class, BigInteger.class)); 68 | assertEquals(timestamp.longValue(), 1514764800000L); 69 | } 70 | 71 | public void shouldConvertToDate() { 72 | LocalDate source = TestHelper.instantOf(2018, 1, 1) 73 | .atZone(ZoneOffset.UTC) 74 | .toLocalDate(); 75 | Date timestamp = (Date) converter.convert(TestHelper.unsafeMappingContext(source, LocalDate.class, Date.class)); 76 | assertEquals(timestamp.getTime(), 1514764800000L); 77 | } 78 | 79 | public void shouldConvertToCalendar() { 80 | LocalDate source = TestHelper.instantOf(2018, 1, 1) 81 | .atZone(ZoneOffset.UTC) 82 | .toLocalDate(); 83 | Calendar timestamp = (Calendar) converter.convert(TestHelper.unsafeMappingContext(source, LocalDate.class, Calendar.class)); 84 | assertEquals(timestamp.getTime().getTime(), 1514764800000L); 85 | } 86 | 87 | public void shouldConvertNull() { 88 | Calendar timestamp = (Calendar) converter.convert(TestHelper.unsafeMappingContext(null, LocalDate.class, Calendar.class)); 89 | assertNull(timestamp); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /datetime/src/test/java/org/modelmapper/module/jsr310/FromLocalDateTimeConverterTest.java: -------------------------------------------------------------------------------- 1 | package org.modelmapper.module.jsr310; 2 | 3 | import static org.testng.Assert.assertEquals; 4 | import static org.testng.Assert.assertNull; 5 | 6 | import java.math.BigDecimal; 7 | import java.math.BigInteger; 8 | import java.time.LocalDateTime; 9 | import java.time.ZoneOffset; 10 | import java.util.Calendar; 11 | import java.util.Date; 12 | import org.modelmapper.spi.ConditionalConverter; 13 | import org.testng.annotations.BeforeMethod; 14 | import org.testng.annotations.Test; 15 | 16 | @Test 17 | public class FromLocalDateTimeConverterTest { 18 | 19 | private Jsr310ModuleConfig config; 20 | private ConditionalConverter converter; 21 | 22 | @BeforeMethod 23 | public void setUp() { 24 | config = Jsr310ModuleConfig.builder() 25 | .zoneId(ZoneOffset.UTC) 26 | .build(); 27 | converter = TestHelper.unsafe(new FromTemporalConverter(config)); 28 | } 29 | 30 | public void shouldConvertToDefaultString() { 31 | LocalDateTime source = TestHelper.instantOf(2018, 1, 1) 32 | .atZone(ZoneOffset.UTC) 33 | .toLocalDateTime(); 34 | String dateText = (String) converter.convert(TestHelper.unsafeMappingContext(source, LocalDateTime.class, String.class)); 35 | assertEquals(dateText, "2018-01-01 00:00:00"); 36 | } 37 | 38 | public void shouldConvertToStringWithPattern() { 39 | config.setDateTimePattern("yyyy-MM-dd HH:mm:ss.SSS"); 40 | LocalDateTime source = TestHelper.instantOf(2018, 1, 1) 41 | .atZone(ZoneOffset.UTC) 42 | .toLocalDateTime(); 43 | String dateText = (String) converter.convert(TestHelper.unsafeMappingContext(source, LocalDateTime.class, String.class)); 44 | assertEquals(dateText, "2018-01-01 00:00:00.000"); 45 | } 46 | 47 | public void shouldConvertToLong() { 48 | LocalDateTime source = TestHelper.instantOf(2018, 1, 1) 49 | .atZone(ZoneOffset.UTC) 50 | .toLocalDateTime(); 51 | long timestamp = (Long) converter.convert(TestHelper.unsafeMappingContext(source, LocalDateTime.class, Long.class)); 52 | assertEquals(timestamp, 1514764800000L); 53 | } 54 | 55 | public void shouldConvertToBigDecimal() { 56 | LocalDateTime source = TestHelper.instantOf(2018, 1, 1) 57 | .atZone(ZoneOffset.UTC) 58 | .toLocalDateTime(); 59 | BigDecimal timestamp = (BigDecimal) converter.convert(TestHelper.unsafeMappingContext(source, LocalDateTime.class, BigDecimal.class)); 60 | assertEquals(timestamp.longValue(), 1514764800000L); 61 | } 62 | 63 | public void shouldConvertToBigInteger() { 64 | LocalDateTime source = TestHelper.instantOf(2018, 1, 1) 65 | .atZone(ZoneOffset.UTC) 66 | .toLocalDateTime(); 67 | BigInteger timestamp = (BigInteger) converter.convert(TestHelper.unsafeMappingContext(source, LocalDateTime.class, BigInteger.class)); 68 | assertEquals(timestamp.longValue(), 1514764800000L); 69 | } 70 | 71 | public void shouldConvertToDate() { 72 | LocalDateTime source = TestHelper.instantOf(2018, 1, 1) 73 | .atZone(ZoneOffset.UTC) 74 | .toLocalDateTime(); 75 | Date timestamp = (Date) converter.convert(TestHelper.unsafeMappingContext(source, LocalDateTime.class, Date.class)); 76 | assertEquals(timestamp.getTime(), 1514764800000L); 77 | } 78 | 79 | public void shouldConvertToCalendar() { 80 | LocalDateTime source = TestHelper.instantOf(2018, 1, 1) 81 | .atZone(ZoneOffset.UTC) 82 | .toLocalDateTime(); 83 | Calendar timestamp = (Calendar) converter.convert(TestHelper.unsafeMappingContext(source, LocalDateTime.class, Calendar.class)); 84 | assertEquals(timestamp.getTime().getTime(), 1514764800000L); 85 | } 86 | 87 | public void shouldConvertNull() { 88 | Calendar timestamp = (Calendar) converter.convert(TestHelper.unsafeMappingContext(null, LocalDateTime.class, Calendar.class)); 89 | assertNull(timestamp); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /datetime/src/test/java/org/modelmapper/module/jsr310/FromOffsetDateTimeConverterTest.java: -------------------------------------------------------------------------------- 1 | package org.modelmapper.module.jsr310; 2 | 3 | import org.modelmapper.spi.ConditionalConverter; 4 | import org.testng.annotations.BeforeMethod; 5 | import org.testng.annotations.Test; 6 | 7 | import java.math.BigDecimal; 8 | import java.math.BigInteger; 9 | import java.time.LocalDateTime; 10 | import java.time.OffsetDateTime; 11 | import java.time.ZoneId; 12 | import java.time.ZoneOffset; 13 | import java.util.Calendar; 14 | import java.util.Date; 15 | 16 | import static org.testng.Assert.assertEquals; 17 | import static org.testng.Assert.assertNull; 18 | 19 | @Test 20 | public class FromOffsetDateTimeConverterTest { 21 | 22 | private Jsr310ModuleConfig config; 23 | private ConditionalConverter converter; 24 | 25 | @BeforeMethod 26 | public void setUp() { 27 | config = Jsr310ModuleConfig.builder() 28 | .zoneId(ZoneOffset.UTC) 29 | .build(); 30 | converter = TestHelper.unsafe(new FromTemporalConverter(config)); 31 | } 32 | 33 | public void shouldConvertToDefaultString() { 34 | OffsetDateTime source = TestHelper.instantOf(2018, 1, 1) 35 | .atZone(ZoneOffset.UTC) 36 | .toOffsetDateTime(); 37 | String dateText = (String) converter.convert(TestHelper.unsafeMappingContext(source, OffsetDateTime.class, String.class)); 38 | assertEquals(dateText, "2018-01-01 00:00:00Z"); 39 | } 40 | 41 | public void shouldConvertZonedTimeToDefaultString() { 42 | OffsetDateTime source = TestHelper.instantOf(2018, 1, 1) 43 | .atZone(ZoneId.of("-05:00")) 44 | .toOffsetDateTime(); 45 | String dateText = (String) converter.convert(TestHelper.unsafeMappingContext(source, OffsetDateTime.class, String.class)); 46 | assertEquals(dateText, "2017-12-31 19:00:00-05"); 47 | } 48 | 49 | public void shouldConvertToLong() { 50 | OffsetDateTime source = TestHelper.instantOf(2018, 1, 1) 51 | .atZone(ZoneOffset.UTC) 52 | .toOffsetDateTime(); 53 | long timestamp = (Long) converter.convert(TestHelper.unsafeMappingContext(source, OffsetDateTime.class, Long.class)); 54 | assertEquals(timestamp, 1514764800000L); 55 | } 56 | 57 | public void shouldConvertToBigDecimal() { 58 | OffsetDateTime source = TestHelper.instantOf(2018, 1, 1) 59 | .atZone(ZoneOffset.UTC) 60 | .toOffsetDateTime(); 61 | BigDecimal timestamp = (BigDecimal) converter.convert(TestHelper.unsafeMappingContext(source, OffsetDateTime.class, BigDecimal.class)); 62 | assertEquals(timestamp.longValue(), 1514764800000L); 63 | } 64 | 65 | public void shouldConvertToBigInteger() { 66 | OffsetDateTime source = TestHelper.instantOf(2018, 1, 1) 67 | .atZone(ZoneOffset.UTC) 68 | .toOffsetDateTime(); 69 | BigInteger timestamp = (BigInteger) converter.convert(TestHelper.unsafeMappingContext(source, OffsetDateTime.class, BigInteger.class)); 70 | assertEquals(timestamp.longValue(), 1514764800000L); 71 | } 72 | 73 | public void shouldConvertToDate() { 74 | OffsetDateTime source = TestHelper.instantOf(2018, 1, 1) 75 | .atZone(ZoneOffset.UTC) 76 | .toOffsetDateTime(); 77 | Date timestamp = (Date) converter.convert(TestHelper.unsafeMappingContext(source, OffsetDateTime.class, Date.class)); 78 | assertEquals(timestamp.getTime(), 1514764800000L); 79 | } 80 | 81 | public void shouldConvertToCalendar() { 82 | OffsetDateTime source = TestHelper.instantOf(2018, 1, 1) 83 | .atZone(ZoneOffset.UTC) 84 | .toOffsetDateTime(); 85 | Calendar timestamp = (Calendar) converter.convert(TestHelper.unsafeMappingContext(source, OffsetDateTime.class, Calendar.class)); 86 | assertEquals(timestamp.getTime().getTime(), 1514764800000L); 87 | } 88 | 89 | public void shouldConvertNull() { 90 | Calendar timestamp = (Calendar) converter.convert(TestHelper.unsafeMappingContext(null, OffsetDateTime.class, Calendar.class)); 91 | assertNull(timestamp); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /datetime/src/test/java/org/modelmapper/module/jsr310/FromZonedDateTimeConverterTest.java: -------------------------------------------------------------------------------- 1 | package org.modelmapper.module.jsr310; 2 | 3 | import org.modelmapper.spi.ConditionalConverter; 4 | import org.testng.annotations.BeforeMethod; 5 | import org.testng.annotations.Test; 6 | 7 | import java.math.BigDecimal; 8 | import java.math.BigInteger; 9 | import java.time.ZoneId; 10 | import java.time.ZoneOffset; 11 | import java.time.ZonedDateTime; 12 | import java.util.Calendar; 13 | import java.util.Date; 14 | 15 | import static org.testng.Assert.assertEquals; 16 | import static org.testng.Assert.assertNull; 17 | 18 | @Test 19 | public class FromZonedDateTimeConverterTest { 20 | 21 | private Jsr310ModuleConfig config; 22 | private ConditionalConverter converter; 23 | 24 | @BeforeMethod 25 | public void setUp() { 26 | config = Jsr310ModuleConfig.builder() 27 | .zoneId(ZoneId.of("-05:00")) 28 | .build(); 29 | converter = TestHelper.unsafe(new FromTemporalConverter(config)); 30 | } 31 | 32 | public void shouldConvertToDefaultString() { 33 | ZonedDateTime source = TestHelper.instantOf(2018, 1, 1).atZone(ZoneOffset.UTC); 34 | String dateText = (String) converter.convert(TestHelper.unsafeMappingContext(source, ZonedDateTime.class, String.class)); 35 | assertEquals(dateText, "2018-01-01 00:00:00Z"); 36 | } 37 | 38 | public void shouldConvertToStringWithPattern() { 39 | config.setDateTimeOffsetPattern("yyyy-MM-dd HH:mm:ss.SSSX"); 40 | ZonedDateTime source = TestHelper.instantOf(2018, 1, 1).atZone(ZoneOffset.UTC); 41 | String dateText = (String) converter.convert(TestHelper.unsafeMappingContext(source, ZonedDateTime.class, String.class)); 42 | assertEquals(dateText, "2018-01-01 00:00:00.000Z"); 43 | } 44 | 45 | public void shouldConvertToLong() { 46 | ZonedDateTime source = TestHelper.instantOf(2018, 1, 1).atZone(ZoneOffset.UTC); 47 | long timestamp = (Long) converter.convert(TestHelper.unsafeMappingContext(source, ZonedDateTime.class, Long.class)); 48 | assertEquals(timestamp, 1514764800000L); 49 | } 50 | 51 | public void shouldConvertToBigDecimal() { 52 | ZonedDateTime source = TestHelper.instantOf(2018, 1, 1).atZone(ZoneOffset.UTC); 53 | BigDecimal timestamp = (BigDecimal) converter.convert(TestHelper.unsafeMappingContext(source, ZonedDateTime.class, BigDecimal.class)); 54 | assertEquals(timestamp.longValue(), 1514764800000L); 55 | } 56 | 57 | public void shouldConvertToBigInteger() { 58 | ZonedDateTime source = TestHelper.instantOf(2018, 1, 1).atZone(ZoneOffset.UTC); 59 | BigInteger timestamp = (BigInteger) converter.convert(TestHelper.unsafeMappingContext(source, ZonedDateTime.class, BigInteger.class)); 60 | assertEquals(timestamp.longValue(), 1514764800000L); 61 | } 62 | 63 | public void shouldConvertToDate() { 64 | ZonedDateTime source = TestHelper.instantOf(2018, 1, 1).atZone(ZoneOffset.UTC); 65 | Date timestamp = (Date) converter.convert(TestHelper.unsafeMappingContext(source, ZonedDateTime.class, Date.class)); 66 | assertEquals(timestamp.getTime(), 1514764800000L); 67 | } 68 | 69 | public void shouldConvertToCalendar() { 70 | ZonedDateTime source = TestHelper.instantOf(2018, 1, 1).atZone(ZoneOffset.UTC); 71 | Calendar timestamp = (Calendar) converter.convert(TestHelper.unsafeMappingContext(source, ZonedDateTime.class, Calendar.class)); 72 | assertEquals(timestamp.getTime().getTime(), 1514764800000L); 73 | } 74 | 75 | public void shouldConvertNull() { 76 | Calendar timestamp = (Calendar) converter.convert(TestHelper.unsafeMappingContext(null, ZonedDateTime.class, Calendar.class)); 77 | assertNull(timestamp); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /datetime/src/test/java/org/modelmapper/module/jsr310/Jsr310ModuleTest.java: -------------------------------------------------------------------------------- 1 | package org.modelmapper.module.jsr310; 2 | 3 | import java.time.Instant; 4 | import java.time.ZoneOffset; 5 | import lombok.Data; 6 | import org.modelmapper.ModelMapper; 7 | import org.testng.annotations.BeforeMethod; 8 | import org.testng.annotations.Test; 9 | 10 | import static org.testng.Assert.assertEquals; 11 | 12 | @Test 13 | public class Jsr310ModuleTest { 14 | 15 | @Data 16 | private static class StringWrapper { 17 | private String date; 18 | } 19 | 20 | @Data 21 | private static class InstantWrapper { 22 | private Instant date; 23 | } 24 | 25 | private ModelMapper modelMapper; 26 | 27 | @BeforeMethod 28 | public void setUp() { 29 | Jsr310ModuleConfig config = Jsr310ModuleConfig.builder() 30 | .zoneId(ZoneOffset.UTC) 31 | .build(); 32 | modelMapper = new ModelMapper() 33 | .registerModule(new Jsr310Module(config)); 34 | } 35 | 36 | public void shouldMapStringToInstant() { 37 | StringWrapper source = new StringWrapper(); 38 | source.setDate("2018-01-01 00:00:00"); 39 | InstantWrapper destination = modelMapper.map(source, InstantWrapper.class); 40 | assertEquals(destination.getDate().toEpochMilli(), 1514764800000L); 41 | } 42 | 43 | public void shouldMapInstantToString() { 44 | InstantWrapper source = new InstantWrapper(); 45 | source.setDate(TestHelper.instantOf(2018, 1, 1)); 46 | StringWrapper destination = modelMapper.map(source, StringWrapper.class); 47 | assertEquals(destination.getDate(), "2018-01-01 00:00:00"); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /datetime/src/test/java/org/modelmapper/module/jsr310/TestHelper.java: -------------------------------------------------------------------------------- 1 | package org.modelmapper.module.jsr310; 2 | 3 | import java.time.Instant; 4 | import org.modelmapper.internal.MappingContextImpl; 5 | import org.modelmapper.spi.ConditionalConverter; 6 | import org.modelmapper.spi.MappingContext; 7 | 8 | public class TestHelper { 9 | public static MappingContext mappingContext(S source, Class sourceType, Class destinationType) { 10 | return new MappingContextImpl<>(source ,sourceType, null, 11 | destinationType,null, "", null); 12 | } 13 | public static MappingContext unsafeMappingContext(S source, Class sourceType, Class destinationType) { 14 | MappingContext mappingContext = mappingContext(source ,sourceType, destinationType); 15 | return unsafe(mappingContext); 16 | } 17 | 18 | @SuppressWarnings("unchecked") 19 | public static MappingContext unsafe(MappingContext mappingContext) { 20 | return (MappingContext) mappingContext; 21 | } 22 | 23 | @SuppressWarnings("unchecked") 24 | public static ConditionalConverter unsafe(ConditionalConverter converter) { 25 | return (ConditionalConverter) converter; 26 | } 27 | 28 | public static Instant instantOf(int year, int month, int day) { 29 | return Instant.parse(String.format("%04d-%02d-%02dT00:00:00Z", year, month, day)); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /datetime/src/test/java/org/modelmapper/module/jsr310/ToInstantConverterTest.java: -------------------------------------------------------------------------------- 1 | package org.modelmapper.module.jsr310; 2 | 3 | import java.math.BigDecimal; 4 | import java.math.BigInteger; 5 | import java.time.Instant; 6 | import java.time.ZoneOffset; 7 | import java.util.Calendar; 8 | import java.util.Date; 9 | import org.modelmapper.spi.ConditionalConverter; 10 | import org.testng.annotations.BeforeMethod; 11 | import org.testng.annotations.Test; 12 | 13 | import static org.testng.Assert.assertEquals; 14 | import static org.testng.Assert.assertNull; 15 | 16 | @Test 17 | public class ToInstantConverterTest { 18 | 19 | private Jsr310ModuleConfig config; 20 | private ConditionalConverter converter; 21 | 22 | @BeforeMethod 23 | public void setUp() { 24 | config = Jsr310ModuleConfig.builder() 25 | .zoneId(ZoneOffset.UTC) 26 | .build(); 27 | converter = TestHelper.unsafe(new ToTemporalConverter(config)); 28 | } 29 | 30 | public void shouldConvertStringWithDefaultPattern() { 31 | Instant instant = (Instant) converter.convert(TestHelper.unsafeMappingContext( 32 | "2018-01-01 00:00:00", String.class, Instant.class)); 33 | assertEquals(instant.toEpochMilli(), 1514764800000L); 34 | } 35 | 36 | public void shouldConvertStringWithCustomPattern() { 37 | config.setDateTimePattern("yyyy-MM-dd HH:mm:ss.SSS"); 38 | Instant instant = (Instant) converter.convert(TestHelper.unsafeMappingContext( 39 | "2018-01-01 00:00:00.000", String.class, Instant.class)); 40 | assertEquals(instant.toEpochMilli(), 1514764800000L); 41 | } 42 | 43 | public void shouldConvertLong() { 44 | Instant instant = (Instant) converter.convert(TestHelper.unsafeMappingContext( 45 | 1514764800000L, Long.class, Instant.class)); 46 | assertEquals(instant.toEpochMilli(), 1514764800000L); 47 | } 48 | 49 | public void shouldConvertPrimitiveLong() { 50 | Instant instant = (Instant) converter.convert(TestHelper.unsafeMappingContext( 51 | 1514764800000L, Long.TYPE, Instant.class)); 52 | assertEquals(instant.toEpochMilli(), 1514764800000L); 53 | } 54 | 55 | public void shouldConvertBigDecimal() { 56 | Instant instant = (Instant) converter.convert(TestHelper.unsafeMappingContext( 57 | new BigDecimal("1514764800000"), BigDecimal.class, Instant.class)); 58 | assertEquals(instant.toEpochMilli(), 1514764800000L); 59 | } 60 | 61 | public void shouldConvertBigInteger() { 62 | Instant instant = (Instant) converter.convert(TestHelper.unsafeMappingContext( 63 | new BigInteger("1514764800000"), BigInteger.class, Instant.class)); 64 | assertEquals(instant.toEpochMilli(), 1514764800000L); 65 | } 66 | 67 | public void shouldConvertDate() { 68 | Instant instant = (Instant) converter.convert(TestHelper.unsafeMappingContext( 69 | new Date(1514764800000L), Date.class, Instant.class)); 70 | assertEquals(instant.toEpochMilli(), 1514764800000L); 71 | } 72 | 73 | public void shouldConvertCalendar() { 74 | Calendar calendar = Calendar.getInstance(); 75 | calendar.setTimeInMillis(1514764800000L); 76 | Instant instant = (Instant) converter.convert(TestHelper.unsafeMappingContext( 77 | calendar, Calendar.class, Instant.class)); 78 | assertEquals(instant.toEpochMilli(), 1514764800000L); 79 | } 80 | 81 | public void shouldConvertNull() { 82 | Instant timestamp = (Instant) converter.convert(TestHelper.unsafeMappingContext( 83 | null, Date.class, Instant.class)); 84 | assertNull(timestamp); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /datetime/src/test/java/org/modelmapper/module/jsr310/ToLocalDateConverterTest.java: -------------------------------------------------------------------------------- 1 | package org.modelmapper.module.jsr310; 2 | 3 | import static org.testng.Assert.assertEquals; 4 | import static org.testng.Assert.assertNull; 5 | 6 | import java.math.BigDecimal; 7 | import java.math.BigInteger; 8 | import java.time.LocalDate; 9 | import java.time.ZoneOffset; 10 | import java.util.Calendar; 11 | import java.util.Date; 12 | import org.modelmapper.spi.ConditionalConverter; 13 | import org.testng.annotations.BeforeMethod; 14 | import org.testng.annotations.Test; 15 | 16 | @Test 17 | public class ToLocalDateConverterTest { 18 | 19 | private Jsr310ModuleConfig config; 20 | private ConditionalConverter converter; 21 | 22 | @BeforeMethod 23 | public void setUp() { 24 | config = Jsr310ModuleConfig.builder() 25 | .zoneId(ZoneOffset.UTC) 26 | .build(); 27 | converter = TestHelper.unsafe(new ToTemporalConverter(config)); 28 | } 29 | 30 | public void shouldConvertStringWithDefaultPattern() { 31 | LocalDate localDate = (LocalDate) converter.convert(TestHelper.unsafeMappingContext( 32 | "2018-01-01", String.class, LocalDate.class)); 33 | assertEquals(localDate.atStartOfDay().toInstant(ZoneOffset.UTC).toEpochMilli(), 1514764800000L); 34 | } 35 | 36 | public void shouldConvertStringWithCustomPattern() { 37 | config.setDatePattern("yyyy/MM/dd"); 38 | LocalDate localDate = (LocalDate) converter.convert(TestHelper.unsafeMappingContext( 39 | "2018/01/01", String.class, LocalDate.class)); 40 | assertEquals(localDate.atStartOfDay().toInstant(ZoneOffset.UTC).toEpochMilli(), 1514764800000L); 41 | } 42 | 43 | public void shouldConvertLong() { 44 | LocalDate localDate = (LocalDate) converter.convert(TestHelper.unsafeMappingContext( 45 | 1514764800000L, Long.class, LocalDate.class)); 46 | assertEquals(localDate.atStartOfDay().toInstant(ZoneOffset.UTC).toEpochMilli(), 1514764800000L); 47 | } 48 | 49 | public void shouldConvertPrimitiveLong() { 50 | LocalDate localDate = (LocalDate) converter.convert(TestHelper.unsafeMappingContext( 51 | 1514764800000L, Long.TYPE, LocalDate.class)); 52 | assertEquals(localDate.atStartOfDay().toInstant(ZoneOffset.UTC).toEpochMilli(), 1514764800000L); 53 | } 54 | 55 | public void shouldConvertBigDecimal() { 56 | LocalDate localDate = (LocalDate) converter.convert(TestHelper.unsafeMappingContext( 57 | new BigDecimal("1514764800000"), BigDecimal.class, LocalDate.class)); 58 | assertEquals(localDate.atStartOfDay().toInstant(ZoneOffset.UTC).toEpochMilli(), 1514764800000L); 59 | } 60 | 61 | public void shouldConvertBigInteger() { 62 | LocalDate localDate = (LocalDate) converter.convert(TestHelper.unsafeMappingContext( 63 | new BigInteger("1514764800000"), BigInteger.class, LocalDate.class)); 64 | assertEquals(localDate.atStartOfDay().toInstant(ZoneOffset.UTC).toEpochMilli(), 1514764800000L); 65 | } 66 | 67 | public void shouldConvertDate() { 68 | LocalDate localDate = (LocalDate) converter.convert(TestHelper.unsafeMappingContext( 69 | new Date(1514764800000L), Date.class, LocalDate.class)); 70 | assertEquals(localDate.atStartOfDay().toInstant(ZoneOffset.UTC).toEpochMilli(), 1514764800000L); 71 | } 72 | 73 | public void shouldConvertCalendar() { 74 | Calendar calendar = Calendar.getInstance(); 75 | calendar.setTimeInMillis(1514764800000L); 76 | LocalDate localDate = (LocalDate) converter.convert(TestHelper.unsafeMappingContext( 77 | calendar, Calendar.class, LocalDate.class)); 78 | assertEquals(localDate.atStartOfDay().toInstant(ZoneOffset.UTC).toEpochMilli(), 1514764800000L); 79 | } 80 | 81 | public void shouldConvertNull() { 82 | LocalDate timestamp = (LocalDate) converter.convert(TestHelper.unsafeMappingContext( 83 | null, Date.class, LocalDate.class)); 84 | assertNull(timestamp); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /datetime/src/test/java/org/modelmapper/module/jsr310/ToLocalDateTimeConverterTest.java: -------------------------------------------------------------------------------- 1 | package org.modelmapper.module.jsr310; 2 | 3 | import static org.testng.Assert.assertEquals; 4 | import static org.testng.Assert.assertNull; 5 | 6 | import java.math.BigDecimal; 7 | import java.math.BigInteger; 8 | import java.time.LocalDateTime; 9 | import java.time.ZoneOffset; 10 | import java.util.Calendar; 11 | import java.util.Date; 12 | import org.modelmapper.spi.ConditionalConverter; 13 | import org.testng.annotations.BeforeMethod; 14 | import org.testng.annotations.Test; 15 | 16 | @Test 17 | public class ToLocalDateTimeConverterTest { 18 | 19 | private Jsr310ModuleConfig config; 20 | private ConditionalConverter converter; 21 | 22 | @BeforeMethod 23 | public void setUp() { 24 | config = Jsr310ModuleConfig.builder() 25 | .zoneId(ZoneOffset.UTC) 26 | .build(); 27 | converter = TestHelper.unsafe(new ToTemporalConverter(config)); 28 | } 29 | 30 | public void shouldConvertStringWithDefaultPattern() { 31 | LocalDateTime localDateTime = (LocalDateTime) converter.convert(TestHelper.unsafeMappingContext( 32 | "2018-01-01 00:00:00", String.class, LocalDateTime.class)); 33 | assertEquals(localDateTime.toInstant(ZoneOffset.UTC).toEpochMilli(), 1514764800000L); 34 | } 35 | 36 | public void shouldConvertStringWithCustomPattern() { 37 | config.setDateTimePattern("yyyy-MM-dd HH:mm:ss.SSS"); 38 | LocalDateTime localDateTime = (LocalDateTime) converter.convert(TestHelper.unsafeMappingContext( 39 | "2018-01-01 00:00:00.000", String.class, LocalDateTime.class)); 40 | assertEquals(localDateTime.toInstant(ZoneOffset.UTC).toEpochMilli(), 1514764800000L); 41 | } 42 | 43 | public void shouldConvertLong() { 44 | LocalDateTime localDateTime = (LocalDateTime) converter.convert(TestHelper.unsafeMappingContext( 45 | 1514764800000L, Long.class, LocalDateTime.class)); 46 | assertEquals(localDateTime.toInstant(ZoneOffset.UTC).toEpochMilli(), 1514764800000L); 47 | } 48 | 49 | public void shouldConvertPrimitiveLong() { 50 | LocalDateTime localDateTime = (LocalDateTime) converter.convert(TestHelper.unsafeMappingContext( 51 | 1514764800000L, Long.TYPE, LocalDateTime.class)); 52 | assertEquals(localDateTime.toInstant(ZoneOffset.UTC).toEpochMilli(), 1514764800000L); 53 | } 54 | 55 | public void shouldConvertBigDecimal() { 56 | LocalDateTime localDateTime = (LocalDateTime) converter.convert(TestHelper.unsafeMappingContext( 57 | new BigDecimal("1514764800000"), BigDecimal.class, LocalDateTime.class)); 58 | assertEquals(localDateTime.toInstant(ZoneOffset.UTC).toEpochMilli(), 1514764800000L); 59 | } 60 | 61 | public void shouldConvertBigInteger() { 62 | LocalDateTime localDateTime = (LocalDateTime) converter.convert(TestHelper.unsafeMappingContext( 63 | new BigInteger("1514764800000"), BigInteger.class, LocalDateTime.class)); 64 | assertEquals(localDateTime.toInstant(ZoneOffset.UTC).toEpochMilli(), 1514764800000L); 65 | } 66 | 67 | public void shouldConvertDate() { 68 | LocalDateTime localDateTime = (LocalDateTime) converter.convert(TestHelper.unsafeMappingContext( 69 | new Date(1514764800000L), Date.class, LocalDateTime.class)); 70 | assertEquals(localDateTime.toInstant(ZoneOffset.UTC).toEpochMilli(), 1514764800000L); 71 | } 72 | 73 | public void shouldConvertCalendar() { 74 | Calendar calendar = Calendar.getInstance(); 75 | calendar.setTimeInMillis(1514764800000L); 76 | LocalDateTime localDateTime = (LocalDateTime) converter.convert(TestHelper.unsafeMappingContext( 77 | calendar, Calendar.class, LocalDateTime.class)); 78 | assertEquals(localDateTime.toInstant(ZoneOffset.UTC).toEpochMilli(), 1514764800000L); 79 | } 80 | 81 | public void shouldConvertNull() { 82 | LocalDateTime timestamp = (LocalDateTime) converter.convert(TestHelper.unsafeMappingContext( 83 | null, Date.class, LocalDateTime.class)); 84 | assertNull(timestamp); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /datetime/src/test/java/org/modelmapper/module/jsr310/ToOffsetDateTimeConverterTest.java: -------------------------------------------------------------------------------- 1 | package org.modelmapper.module.jsr310; 2 | 3 | import org.modelmapper.spi.ConditionalConverter; 4 | import org.testng.annotations.BeforeMethod; 5 | import org.testng.annotations.Test; 6 | 7 | import java.math.BigDecimal; 8 | import java.math.BigInteger; 9 | import java.time.OffsetDateTime; 10 | import java.time.ZoneOffset; 11 | import java.util.Calendar; 12 | import java.util.Date; 13 | 14 | import static org.testng.Assert.assertEquals; 15 | import static org.testng.Assert.assertNull; 16 | 17 | @Test 18 | public class ToOffsetDateTimeConverterTest { 19 | 20 | private Jsr310ModuleConfig config; 21 | private ConditionalConverter converter; 22 | 23 | @BeforeMethod 24 | public void setUp() { 25 | config = Jsr310ModuleConfig.builder() 26 | .zoneId(ZoneOffset.UTC) 27 | .build(); 28 | converter = TestHelper.unsafe(new ToTemporalConverter(config)); 29 | } 30 | 31 | public void shouldConvertStringWithDefaultPattern() { 32 | OffsetDateTime offsetDateTime = (OffsetDateTime) converter.convert(TestHelper.unsafeMappingContext( 33 | "2018-01-01 00:00:00Z", String.class, OffsetDateTime.class)); 34 | assertEquals(offsetDateTime.toInstant().toEpochMilli(), 1514764800000L); 35 | } 36 | 37 | public void shouldConvertZonedTimeStringWithDefaultPattern() { 38 | OffsetDateTime offsetDateTime = (OffsetDateTime) converter.convert(TestHelper.unsafeMappingContext( 39 | "2017-12-31 19:00:00-05", String.class, OffsetDateTime.class)); 40 | assertEquals(offsetDateTime.toInstant().toEpochMilli(), 1514764800000L); 41 | } 42 | 43 | public void shouldConvertLong() { 44 | OffsetDateTime offsetDateTime = (OffsetDateTime) converter.convert(TestHelper.unsafeMappingContext( 45 | 1514764800000L, Long.class, OffsetDateTime.class)); 46 | assertEquals(offsetDateTime.toInstant().toEpochMilli(), 1514764800000L); 47 | } 48 | 49 | public void shouldConvertPrimitiveLong() { 50 | OffsetDateTime offsetDateTime = (OffsetDateTime) converter.convert(TestHelper.unsafeMappingContext( 51 | 1514764800000L, Long.TYPE, OffsetDateTime.class)); 52 | assertEquals(offsetDateTime.toInstant().toEpochMilli(), 1514764800000L); 53 | } 54 | 55 | public void shouldConvertBigDecimal() { 56 | OffsetDateTime offsetDateTime = (OffsetDateTime) converter.convert(TestHelper.unsafeMappingContext( 57 | new BigDecimal("1514764800000"), BigDecimal.class, OffsetDateTime.class)); 58 | assertEquals(offsetDateTime.toInstant().toEpochMilli(), 1514764800000L); 59 | } 60 | 61 | public void shouldConvertBigInteger() { 62 | OffsetDateTime offsetDateTime = (OffsetDateTime) converter.convert(TestHelper.unsafeMappingContext( 63 | new BigInteger("1514764800000"), BigInteger.class, OffsetDateTime.class)); 64 | assertEquals(offsetDateTime.toInstant().toEpochMilli(), 1514764800000L); 65 | } 66 | 67 | public void shouldConvertDate() { 68 | OffsetDateTime offsetDateTime = (OffsetDateTime) converter.convert(TestHelper.unsafeMappingContext( 69 | new Date(1514764800000L), Date.class, OffsetDateTime.class)); 70 | assertEquals(offsetDateTime.toInstant().toEpochMilli(), 1514764800000L); 71 | } 72 | 73 | public void shouldConvertCalendar() { 74 | Calendar calendar = Calendar.getInstance(); 75 | calendar.setTimeInMillis(1514764800000L); 76 | OffsetDateTime offsetDateTime = (OffsetDateTime) converter.convert(TestHelper.unsafeMappingContext( 77 | calendar, Calendar.class, OffsetDateTime.class)); 78 | assertEquals(offsetDateTime.toInstant().toEpochMilli(), 1514764800000L); 79 | } 80 | 81 | public void shouldConvertNull() { 82 | OffsetDateTime timestamp = (OffsetDateTime) converter.convert(TestHelper.unsafeMappingContext( 83 | null, Date.class, OffsetDateTime.class)); 84 | assertNull(timestamp); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /datetime/src/test/java/org/modelmapper/module/jsr310/ToZonedDateTimeConverterTest.java: -------------------------------------------------------------------------------- 1 | package org.modelmapper.module.jsr310; 2 | 3 | import org.modelmapper.spi.ConditionalConverter; 4 | import org.testng.annotations.BeforeMethod; 5 | import org.testng.annotations.Test; 6 | 7 | import java.math.BigDecimal; 8 | import java.math.BigInteger; 9 | import java.time.ZoneId; 10 | import java.time.ZoneOffset; 11 | import java.time.ZonedDateTime; 12 | import java.util.Calendar; 13 | import java.util.Date; 14 | 15 | import static org.testng.Assert.assertEquals; 16 | 17 | @Test 18 | public class ToZonedDateTimeConverterTest { 19 | 20 | private Jsr310ModuleConfig config; 21 | private ConditionalConverter converter; 22 | 23 | @BeforeMethod 24 | public void setUp() { 25 | config = Jsr310ModuleConfig.builder() 26 | .zoneId(ZoneId.of("-05:00")) 27 | .build(); 28 | converter = TestHelper.unsafe(new ToTemporalConverter(config)); 29 | } 30 | 31 | public void shouldConvertStringWithDefaultPattern() { 32 | ZonedDateTime zonedDateTime = (ZonedDateTime) converter.convert(TestHelper.unsafeMappingContext( 33 | "2018-01-01 00:00:00Z", String.class, ZonedDateTime.class)); 34 | assertEquals(zonedDateTime.toInstant().toEpochMilli(), 1514764800000L); 35 | } 36 | 37 | 38 | public void shouldConvertLong() { 39 | ZonedDateTime zonedDateTime = (ZonedDateTime) converter.convert(TestHelper.unsafeMappingContext( 40 | 1514764800000L, Long.class, ZonedDateTime.class)); 41 | assertEquals(ZoneId.of("-05:00"), zonedDateTime.getZone()); 42 | assertEquals(zonedDateTime.toInstant().toEpochMilli(), 1514764800000L); 43 | } 44 | 45 | public void shouldConvertPrimitiveLong() { 46 | ZonedDateTime zonedDateTime = (ZonedDateTime) converter.convert(TestHelper.unsafeMappingContext( 47 | 1514764800000L, Long.class, ZonedDateTime.class)); 48 | assertEquals(zonedDateTime.toInstant().toEpochMilli(), 1514764800000L); 49 | } 50 | 51 | public void shouldConvertBigDecimal() { 52 | ZonedDateTime zonedDateTime = (ZonedDateTime) converter.convert(TestHelper.unsafeMappingContext( 53 | new BigDecimal("1514764800000"), BigDecimal.class, ZonedDateTime.class)); 54 | assertEquals(zonedDateTime.toInstant().toEpochMilli(), 1514764800000L); 55 | } 56 | 57 | public void shouldConvertBigInteger() { 58 | ZonedDateTime zonedDateTime = (ZonedDateTime) converter.convert(TestHelper.unsafeMappingContext( 59 | new BigInteger("1514764800000"), BigInteger.class, ZonedDateTime.class)); 60 | assertEquals(zonedDateTime.toInstant().toEpochMilli(), 1514764800000L); 61 | } 62 | 63 | public void shouldConvertDate() { 64 | ZonedDateTime zonedDateTime = (ZonedDateTime)converter.convert(TestHelper.unsafeMappingContext( 65 | new Date(1514764800000L), Date.class, ZonedDateTime.class)); 66 | assertEquals(zonedDateTime.toInstant().toEpochMilli(), 1514764800000L); 67 | } 68 | 69 | public void shouldConvertCalendar() { 70 | Calendar calendar = Calendar.getInstance(); 71 | calendar.setTimeInMillis(1514764800000L); 72 | ZonedDateTime zonedDateTime = (ZonedDateTime) converter.convert(TestHelper.unsafeMappingContext( 73 | calendar, Calendar.class, ZonedDateTime.class)); 74 | assertEquals(zonedDateTime.toInstant().toEpochMilli(), 1514764800000L); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | org.sonatype.oss 6 | oss-parent 7 | 7 8 | 9 | org.modelmapper 10 | modelmapper-module-java8 11 | 1.2.4-SNAPSHOT 12 | pom 13 | 14 | datetime 15 | datatypes 16 | 17 | ModelMapper Module Java8 18 | ModelMapper Module for Java8 19 | http://modelmapper.org 20 | 2018 21 | 22 | 1.8 23 | 1.8 24 | 2.1.1 25 | 1.18.2 26 | 6.9.10 27 | 28 | 29 | 30 | Apache License, Version 2.0 31 | http://apache.org/licenses/LICENSE-2.0 32 | repo 33 | 34 | 35 | 36 | 37 | Chun Han Hsiao 38 | chhsiao90@gmail.com 39 | 40 | 41 | 42 | scm:git:git@github.com:chhsiao90/modelmapper-module-java8.git 43 | scm:git:git@github.com:chhsiao90/modelmapper-module-java8.git 44 | http://github.com/chhsiao90/modelmapper-module-java8/ 45 | 46 | 47 | GitHub 48 | http://github.com/chhsiao90/modelmapper-module-java8/issues 49 | 50 | 51 | 52 | ModelMapper List 53 | http://groups.google.com/group/modelmapper/topics 54 | http://groups.google.com/group/modelmapper/subscribe 55 | http://groups.google.com/group/modelmapper/subscribe 56 | http://groups.google.com/group/modelmapper/post 57 | 58 | 59 | 60 | 61 | org.testng 62 | testng 63 | ${testng.version} 64 | test 65 | 66 | 67 | 68 | 69 | 70 | org.modelmapper 71 | modelmapper 72 | ${modelmapper.version} 73 | 74 | 75 | org.projectlombok 76 | lombok 77 | ${lombok.version} 78 | provided 79 | 80 | 81 | 82 | 83 | --------------------------------------------------------------------------------