Skip to content

Commit 952c207

Browse files
authored
Merge pull request iluwatar#546 from Crossy147/converter
Converter
2 parents 6ba4d7b + a5ab5c7 commit 952c207

File tree

14 files changed

+559
-3
lines changed

14 files changed

+559
-3
lines changed

api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/ImageClientImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
* An adapter to communicate with the Image microservice
3636
*/
3737
@Component
38-
public class ImageClientImpl implements ImageClient{
38+
public class ImageClientImpl implements ImageClient {
3939
/**
4040
* Makes a simple HTTP Get request to the Image microservice
4141
* @return The path to the image

api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/PriceClientImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
* An adapter to communicate with the Price microservice
3636
*/
3737
@Component
38-
public class PriceClientImpl implements PriceClient{
38+
public class PriceClientImpl implements PriceClient {
3939
/**
4040
* Makes a simple HTTP Get request to the Price microservice
4141
* @return The price of the product

converter/README.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
---
2+
layout: pattern
3+
title: Converter
4+
folder: converter
5+
permalink: /patterns/converter/
6+
categories:
7+
tags:
8+
- Java
9+
- Difficulty-Beginner
10+
---
11+
12+
## Intent
13+
The purpose of the Converter Pattern is to provide a generic, common way of bidirectional
14+
conversion between corresponding types, allowing a clean implementation in which the types do not
15+
need to be aware of each other. Moreover, the Converter Pattern introduces bidirectional collection
16+
mapping, reducing a boilerplate code to minimum.
17+
18+
![alt text](./etc/converter.png "Converter Pattern")
19+
20+
## Applicability
21+
Use the Converter Pattern in the following situations:
22+
23+
* When you have types that logically correspond which other and you need to convert entities between them
24+
* When you want to provide different ways of types conversions depending on a context
25+
* Whenever you introduce a DTO (Data transfer object), you will probably need to convert it into the domain equivalence
26+
27+
## Credits
28+
29+
* [Converter](http://www.xsolve.pl/blog/converter-pattern-in-java-8/)

converter/etc/Converter.png

18.9 KB
Loading

converter/etc/Converter.ucls

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<class-diagram version="1.1.14" icons="true" automaticImage="PNG" always-add-relationships="false"
3+
generalizations="true" realizations="true" associations="true" dependencies="false" nesting-relationships="true"
4+
router="FAN">
5+
<class id="1" language="java" name="com.iluwatar.converter.Converter" project="converter"
6+
file="/converter/src/main/java/com/iluwatar/converter/Converter.java" binary="false" corner="BOTTOM_RIGHT">
7+
<position height="189" width="226" x="41" y="37"/>
8+
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
9+
sort-features="false" accessors="true" visibility="true">
10+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
11+
<operations public="true" package="true" protected="true" private="true" static="true"/>
12+
</display>
13+
</class>
14+
<class id="2" language="java" name="com.iluwatar.converter.UserConverter" project="converter"
15+
file="/converter/src/main/java/com/iluwatar/converter/UserConverter.java" binary="false" corner="BOTTOM_RIGHT">
16+
<position height="81" width="107" x="41" y="356"/>
17+
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
18+
sort-features="false" accessors="true" visibility="true">
19+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
20+
<operations public="true" package="true" protected="true" private="true" static="true"/>
21+
</display>
22+
</class>
23+
<class id="3" language="java" name="com.iluwatar.converter.User" project="converter"
24+
file="/converter/src/main/java/com/iluwatar/converter/User.java" binary="false" corner="BOTTOM_RIGHT">
25+
<position height="279" width="188" x="307" y="37"/>
26+
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
27+
sort-features="false" accessors="true" visibility="true">
28+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
29+
<operations public="true" package="true" protected="true" private="true" static="true"/>
30+
</display>
31+
</class>
32+
<class id="4" language="java" name="com.iluwatar.converter.UserDto" project="converter"
33+
file="/converter/src/main/java/com/iluwatar/converter/UserDto.java" binary="false" corner="BOTTOM_RIGHT">
34+
<position height="279" width="204" x="535" y="37"/>
35+
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
36+
sort-features="false" accessors="true" visibility="true">
37+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
38+
<operations public="true" package="true" protected="true" private="true" static="true"/>
39+
</display>
40+
</class>
41+
<generalization id="5">
42+
<end type="SOURCE" refId="2"/>
43+
<end type="TARGET" refId="1"/>
44+
</generalization>
45+
<classifier-display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
46+
sort-features="false" accessors="true" visibility="true">
47+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
48+
<operations public="true" package="true" protected="true" private="true" static="true"/>
49+
</classifier-display>
50+
<association-display labels="true" multiplicity="true"/>
51+
</class-diagram>

converter/pom.xml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<parent>
6+
<artifactId>java-design-patterns</artifactId>
7+
<groupId>com.iluwatar</groupId>
8+
<version>1.15.0-SNAPSHOT</version>
9+
</parent>
10+
<modelVersion>4.0.0</modelVersion>
11+
<dependencies>
12+
<dependency>
13+
<groupId>junit</groupId>
14+
<artifactId>junit</artifactId>
15+
<scope>test</scope>
16+
</dependency>
17+
<dependency>
18+
<groupId>com.google.guava</groupId>
19+
<artifactId>guava</artifactId>
20+
</dependency>
21+
</dependencies>
22+
<artifactId>converter</artifactId>
23+
24+
25+
</project>
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/**
2+
* The MIT License
3+
* Copyright (c) 2014-2016 Ilkka Seppälä
4+
* <p>
5+
* Permission is hereby granted, free of charge, to any person obtaining a copy
6+
* of this software and associated documentation files (the "Software"), to deal
7+
* in the Software without restriction, including without limitation the rights
8+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the Software is
10+
* furnished to do so, subject to the following conditions:
11+
* <p>
12+
* The above copyright notice and this permission notice shall be included in
13+
* all copies or substantial portions of the Software.
14+
* <p>
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
* THE SOFTWARE.
22+
*/
23+
package com.iluwatar.converter;
24+
25+
26+
import com.google.common.collect.Lists;
27+
28+
import java.util.ArrayList;
29+
import java.util.List;
30+
31+
/**
32+
* The Converter pattern is a behavioral design pattern which allows a common way of bidirectional
33+
* conversion between corresponding types (e.g. DTO and domain representations of the logically
34+
* isomorphic types). Moreover, the pattern introduces a common way of converting a collection of
35+
* objects between types.
36+
*/
37+
public class App {
38+
/**
39+
* Program entry point
40+
*
41+
* @param args command line args
42+
*/
43+
public static void main(String[] args) {
44+
Converter<UserDto, User> userConverter = new Converter<>(
45+
userDto -> new User(userDto.getFirstName(), userDto.getLastName(), userDto.isActive(),
46+
userDto.getEmail()),
47+
user -> new UserDto(user.getFirstName(), user.getLastName(), user.isActive(), user.getUserId()));
48+
49+
UserDto dtoUser = new UserDto("John", "Doe", true, "whatever[at]wherever.com");
50+
User user = userConverter.convertFromDto(dtoUser);
51+
System.out.println("Entity converted from DTO:" + user);
52+
53+
ArrayList<User> users = Lists.newArrayList(new User("Camile", "Tough", false, "124sad"),
54+
new User("Marti", "Luther", true, "42309fd"), new User("Kate", "Smith", true, "if0243"));
55+
System.out.println("Domain entities:");
56+
users.forEach(System.out::println);
57+
58+
System.out.println("DTO entities converted from domain:");
59+
List<UserDto> dtoEntities = userConverter.createFromEntities(users);
60+
dtoEntities.forEach(System.out::println);
61+
62+
}
63+
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/**
2+
* The MIT License
3+
* Copyright (c) 2014-2016 Ilkka Seppälä
4+
* <p>
5+
* Permission is hereby granted, free of charge, to any person obtaining a copy
6+
* of this software and associated documentation files (the "Software"), to deal
7+
* in the Software without restriction, including without limitation the rights
8+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the Software is
10+
* furnished to do so, subject to the following conditions:
11+
* <p>
12+
* The above copyright notice and this permission notice shall be included in
13+
* all copies or substantial portions of the Software.
14+
* <p>
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
* THE SOFTWARE.
22+
*/
23+
24+
package com.iluwatar.converter;
25+
26+
import java.util.Collection;
27+
import java.util.List;
28+
import java.util.function.Function;
29+
import java.util.stream.Collectors;
30+
31+
/**
32+
* Generic converter, thanks to Java8 features not only provides a way of generic bidirectional
33+
* conversion between coresponding types, but also a common way of converting a collection of objects
34+
* of the same type, reducing boilerplate code to the absolute minimum.
35+
* @param <T> DTO representation's type
36+
* @param <U> Domain representation's type
37+
*/
38+
public class Converter<T, U> {
39+
40+
private final Function<T, U> fromDto;
41+
private final Function<U, T> fromEntity;
42+
43+
/**
44+
* @param fromDto Function that converts given dto entity into the domain entity.
45+
* @param fromEntity Function that converts given domain entity into the dto entity.
46+
*/
47+
public Converter(final Function<T, U> fromDto, final Function<U, T> fromEntity) {
48+
this.fromDto = fromDto;
49+
this.fromEntity = fromEntity;
50+
}
51+
52+
/**
53+
* @param userDto DTO entity
54+
* @return The domain representation - the result of the converting function application on dto entity.
55+
*/
56+
public final U convertFromDto(final T userDto) {
57+
return fromDto.apply(userDto);
58+
}
59+
60+
/**
61+
* @param user domain entity
62+
* @return The DTO representation - the result of the converting function application on domain entity.
63+
*/
64+
public final T convertFromEntity(final U user) {
65+
return fromEntity.apply(user);
66+
}
67+
68+
/**
69+
* @param dtoUsers collection of DTO entities
70+
* @return List of domain representation of provided entities retrieved by
71+
* mapping each of them with the convertion function
72+
*/
73+
public final List<U> createFromDtos(final Collection<T> dtoUsers) {
74+
return dtoUsers.stream().map(this::convertFromDto).collect(Collectors.toList());
75+
}
76+
77+
/**
78+
* @param users collection of domain entities
79+
* @return List of domain representation of provided entities retrieved by
80+
* mapping each of them with the convertion function
81+
*/
82+
public final List<T> createFromEntities(final Collection<U> users) {
83+
return users.stream().map(this::convertFromEntity).collect(Collectors.toList());
84+
}
85+
86+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/**
2+
* The MIT License
3+
* Copyright (c) 2014-2016 Ilkka Seppälä
4+
* <p>
5+
* Permission is hereby granted, free of charge, to any person obtaining a copy
6+
* of this software and associated documentation files (the "Software"), to deal
7+
* in the Software without restriction, including without limitation the rights
8+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the Software is
10+
* furnished to do so, subject to the following conditions:
11+
* <p>
12+
* The above copyright notice and this permission notice shall be included in
13+
* all copies or substantial portions of the Software.
14+
* <p>
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
* THE SOFTWARE.
22+
*/
23+
24+
package com.iluwatar.converter;
25+
26+
import java.util.Objects;
27+
28+
public class User {
29+
private String firstName;
30+
private String lastName;
31+
private boolean isActive;
32+
private String userId;
33+
34+
/**
35+
* @param firstName user's first name
36+
* @param lastName user's last name
37+
* @param isActive flag indicating whether the user is active
38+
* @param userId user's identificator
39+
*/
40+
public User(String firstName, String lastName, boolean isActive, String userId) {
41+
this.firstName = firstName;
42+
this.lastName = lastName;
43+
this.isActive = isActive;
44+
this.userId = userId;
45+
}
46+
47+
public String getFirstName() {
48+
return firstName;
49+
}
50+
51+
public String getLastName() {
52+
return lastName;
53+
}
54+
55+
public boolean isActive() {
56+
return isActive;
57+
}
58+
59+
public String getUserId() {
60+
return userId;
61+
}
62+
63+
@Override public boolean equals(Object o) {
64+
if (this == o) {
65+
return true;
66+
}
67+
if (o == null || getClass() != o.getClass()) {
68+
return false;
69+
}
70+
User user = (User) o;
71+
return isActive == user.isActive && Objects.equals(firstName, user.firstName) && Objects
72+
.equals(lastName, user.lastName) && Objects.equals(userId, user.userId);
73+
}
74+
75+
@Override public int hashCode() {
76+
return Objects.hash(firstName, lastName, isActive, userId);
77+
}
78+
79+
@Override public String toString() {
80+
return "User{" + "firstName='" + firstName + '\'' + ", lastName='" + lastName + '\''
81+
+ ", isActive=" + isActive + ", userId='" + userId + '\'' + '}';
82+
}
83+
}

0 commit comments

Comments
 (0)