Skip to content

Commit d73e3c6

Browse files
authored
adding deep cloner (mapstruct#49)
1 parent 8dd8efc commit d73e3c6

File tree

8 files changed

+320
-0
lines changed

8 files changed

+320
-0
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Currently, the following examples exist:
2121
* _mapstruct-jpa-parent-child_: Example on how to use @Context in relation to parent / child relations in JPA)
2222
* _mapstruct-suppress-unmapped_: Shows how mapping to target properties can be ignored without warning by default in a mixed scenario. However bean property mappings that have the same name will still be applied.
2323
* _mapstruct-lookup-entity-with-composed-key_: Shows how an object with composite key can be read from the database in a mapping method.
24+
* _mapstruct-clone_: Shows how an object can be deeply cloned by defining all mapping methods.
2425
* _mapstruct-metadata-annotations_: Demonstrates how to read annotations and use them as mapping instruction.
2526

2627
## License

mapstruct-clone/pom.xml

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
4+
Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/)
5+
and/or other contributors as indicated by the @authors tag. See the
6+
copyright.txt file in the distribution for a full listing of all
7+
contributors.
8+
9+
Licensed under the Apache License, Version 2.0 (the "License");
10+
you may not use this file except in compliance with the License.
11+
You may obtain a copy of the License at
12+
13+
http://www.apache.org/licenses/LICENSE-2.0
14+
15+
Unless required by applicable law or agreed to in writing, software
16+
distributed under the License is distributed on an "AS IS" BASIS,
17+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18+
See the License for the specific language governing permissions and
19+
limitations under the License.
20+
21+
-->
22+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
23+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
24+
<modelVersion>4.0.0</modelVersion>
25+
26+
<groupId>org.mapstruct.examples.clone</groupId>
27+
<artifactId>mapstruct-deep-clone</artifactId>
28+
<version>1.0.0</version>
29+
30+
<properties>
31+
<org.mapstruct.version>1.3.0.Beta2</org.mapstruct.version>
32+
</properties>
33+
34+
<dependencies>
35+
<dependency>
36+
<groupId>org.mapstruct</groupId>
37+
<artifactId>mapstruct-jdk8</artifactId>
38+
<version>${org.mapstruct.version}</version>
39+
</dependency>
40+
41+
<dependency>
42+
<groupId>junit</groupId>
43+
<artifactId>junit</artifactId>
44+
<version>4.12</version>
45+
<scope>test</scope>
46+
</dependency>
47+
48+
<dependency>
49+
<groupId>org.assertj</groupId>
50+
<artifactId>assertj-core</artifactId>
51+
<version>3.6.2</version>
52+
<scope>test</scope>
53+
</dependency>
54+
55+
</dependencies>
56+
57+
<build>
58+
<plugins>
59+
<plugin>
60+
<groupId>org.apache.maven.plugins</groupId>
61+
<artifactId>maven-compiler-plugin</artifactId>
62+
<version>3.6.2</version>
63+
<configuration>
64+
<source>1.8</source>
65+
<target>1.8</target>
66+
<annotationProcessorPaths>
67+
<path>
68+
<groupId>org.mapstruct</groupId>
69+
<artifactId>mapstruct-processor</artifactId>
70+
<version>${org.mapstruct.version}</version>
71+
</path>
72+
</annotationProcessorPaths>
73+
</configuration>
74+
</plugin>
75+
</plugins>
76+
</build>
77+
78+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/**
2+
* Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/)
3+
* and/or other contributors as indicated by the @authors tag. See the
4+
* copyright.txt file in the distribution for a full listing of all
5+
* contributors.
6+
* <p>
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
* <p>
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
* <p>
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
package org.mapstruct.example.dto;
20+
21+
import java.util.List;
22+
import java.util.Map;
23+
24+
/**
25+
* @author Sjaak Derksen
26+
*/
27+
public class CustomerDto {
28+
29+
private Long id;
30+
private String customerName;
31+
private List<OrderItemDto> orders;
32+
private Map<OrderItemKeyDto, OrderItemDto> stock;
33+
34+
35+
public Long getId() {
36+
return id;
37+
}
38+
39+
public void setId(Long id) {
40+
this.id = id;
41+
}
42+
43+
public String getCustomerName() {
44+
return customerName;
45+
}
46+
47+
public void setCustomerName(String customerName) {
48+
this.customerName = customerName;
49+
}
50+
51+
public List<OrderItemDto> getOrders() {
52+
return orders;
53+
}
54+
55+
public void setOrders(List<OrderItemDto> orders) {
56+
this.orders = orders;
57+
}
58+
59+
public Map<OrderItemKeyDto, OrderItemDto> getStock() {
60+
return stock;
61+
}
62+
63+
public void setStock(Map<OrderItemKeyDto, OrderItemDto> stock) {
64+
this.stock = stock;
65+
}
66+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package org.mapstruct.example.dto;
2+
3+
/**
4+
* @author Sjaak Derksen
5+
*/
6+
public class OrderItemDto {
7+
8+
private String name;
9+
private Long quantity;
10+
11+
public String getName() {
12+
return name;
13+
}
14+
15+
public void setName(String name) {
16+
this.name = name;
17+
}
18+
19+
public Long getQuantity() {
20+
return quantity;
21+
}
22+
23+
public void setQuantity(Long quantity) {
24+
this.quantity = quantity;
25+
}
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package org.mapstruct.example.dto;
2+
3+
/**
4+
* @author Sjaak Derksen
5+
*/
6+
public class OrderItemKeyDto {
7+
8+
private long stockNumber;
9+
10+
public long getStockNumber() {
11+
return stockNumber;
12+
}
13+
14+
public void setStockNumber(long stockNumber) {
15+
this.stockNumber = stockNumber;
16+
}
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/**
2+
* Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/)
3+
* and/or other contributors as indicated by the @authors tag. See the
4+
* copyright.txt file in the distribution for a full listing of all
5+
* contributors.
6+
* <p>
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
* <p>
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
* <p>
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
package org.mapstruct.example.mapper;
20+
21+
import java.util.List;
22+
import java.util.Map;
23+
24+
import org.mapstruct.InheritInverseConfiguration;
25+
import org.mapstruct.Mapper;
26+
import org.mapstruct.example.dto.CustomerDto;
27+
import org.mapstruct.example.dto.OrderItemDto;
28+
import org.mapstruct.example.dto.OrderItemKeyDto;
29+
import org.mapstruct.factory.Mappers;
30+
31+
/**
32+
* @author Sjaak Derksen
33+
*
34+
* By defining all methods, we force MapStruct to generate new objects for each mapper in stead of
35+
* taking shortcuts by mapping an object directly.
36+
*/
37+
@Mapper
38+
public interface Cloner {
39+
40+
Cloner MAPPER = Mappers.getMapper( Cloner.class );
41+
42+
CustomerDto clone(CustomerDto customerDto);
43+
44+
List<OrderItemDto> clone(List<OrderItemDto> orders);
45+
46+
OrderItemDto clone(OrderItemDto order);
47+
48+
Map<OrderItemKeyDto, OrderItemDto> clone(Map<OrderItemKeyDto, OrderItemDto> stock);
49+
50+
OrderItemKeyDto clone( OrderItemKeyDto orderItemKeyDto );
51+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/**
2+
* Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/)
3+
* and/or other contributors as indicated by the @authors tag. See the
4+
* copyright.txt file in the distribution for a full listing of all
5+
* contributors.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
package org.mapstruct.example;
20+
21+
import static org.assertj.core.api.Assertions.assertThat;
22+
import static org.assertj.core.api.Assertions.tuple;
23+
24+
import java.util.ArrayList;
25+
import java.util.Collections;
26+
import java.util.HashMap;
27+
import java.util.Map;
28+
29+
import org.junit.Test;
30+
import org.mapstruct.example.dto.CustomerDto;
31+
import org.mapstruct.example.dto.OrderItemDto;
32+
import org.mapstruct.example.dto.OrderItemKeyDto;
33+
import org.mapstruct.example.mapper.Cloner;
34+
35+
/**
36+
*
37+
* @author Sjaak Derksen
38+
*/
39+
public class ClonerTest {
40+
41+
@Test
42+
public void testMapDtoToEntity() {
43+
44+
CustomerDto customerDto = new CustomerDto();
45+
customerDto.setId( 10L );
46+
customerDto.setCustomerName("Jaques" );
47+
OrderItemDto order1 = new OrderItemDto();
48+
order1.setName ("Table" );
49+
order1.setQuantity( 2L );
50+
customerDto.setOrders( new ArrayList<>( Collections.singleton( order1 ) ) );
51+
OrderItemKeyDto key = new OrderItemKeyDto();
52+
key.setStockNumber( 5 );
53+
Map stock = new HashMap( );
54+
stock.put( key, order1 );
55+
customerDto.setStock( stock );
56+
57+
CustomerDto customer = Cloner.MAPPER.clone( customerDto );
58+
59+
// check if cloned
60+
assertThat( customer.getId() ).isEqualTo( 10 );
61+
assertThat( customer.getCustomerName() ).isEqualTo( "Jaques" );
62+
assertThat( customer.getOrders() )
63+
.extracting( "name", "quantity" )
64+
.containsExactly( tuple( "Table", 2L ) );
65+
assertThat( customer.getStock() ).isNotNull();
66+
assertThat( customer.getStock() ).hasSize( 1 );
67+
68+
Map.Entry<OrderItemKeyDto, OrderItemDto> entry = customer.getStock().entrySet().iterator().next();
69+
assertThat( entry.getKey().getStockNumber() ).isEqualTo( 5 );
70+
assertThat( entry.getValue().getName() ).isEqualTo( "Table" );
71+
assertThat( entry.getValue().getQuantity() ).isEqualTo( 2L );
72+
73+
// check mapper really created new objects
74+
assertThat( customer ).isNotSameAs( customerDto );
75+
assertThat( customer.getOrders().get( 0 ) ).isNotEqualTo( order1 );
76+
assertThat( entry.getKey() ).isNotEqualTo( key );
77+
assertThat( entry.getValue() ).isNotEqualTo( order1 );
78+
assertThat( entry.getValue() ).isNotEqualTo( customer.getOrders().get( 0 ) );
79+
}
80+
}

pom.xml

+1
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,6 @@
4343
<module>mapstruct-lookup-entity-with-id</module>
4444
<module>mapstruct-metadata-with-annotations</module>
4545
<module>mapstruct-suppress-unmapped</module>
46+
<module>mapstruct-clone</module>
4647
</modules>
4748
</project>

0 commit comments

Comments
 (0)