From a204383f4571480cccd1d6802e72b89d630dfe5d Mon Sep 17 00:00:00 2001 From: Besok Date: Sat, 19 Oct 2019 16:17:59 +0100 Subject: [PATCH 01/31] init repo for role object --- role-object/README.md | 20 ++++++++++++++++++++ role-object/pom.xml | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 role-object/README.md create mode 100644 role-object/pom.xml diff --git a/role-object/README.md b/role-object/README.md new file mode 100644 index 000000000000..8ffe47400dd8 --- /dev/null +++ b/role-object/README.md @@ -0,0 +1,20 @@ +--- +layout: pattern +title: Role object +folder: Migration +permalink: /patterns/role-object/ +categories: Behavioral +tags: + - Java + - Easy-to-implement +--- + +## Also known as + +## Intent + +## Applicability + +## Real world examples + +## Credits diff --git a/role-object/pom.xml b/role-object/pom.xml new file mode 100644 index 000000000000..9d7e9b88be6e --- /dev/null +++ b/role-object/pom.xml @@ -0,0 +1,38 @@ + + + + 4.0.0 + + com.iluwatar + java-design-patterns + 1.22.0-SNAPSHOT + + + role-object + + + From c3656109a78ecad0604b92b21bf538866016dbee Mon Sep 17 00:00:00 2001 From: Besok Date: Sat, 19 Oct 2019 16:23:39 +0100 Subject: [PATCH 02/31] add to init --- .../com/iluwatar/roleobject/ApplicationRoleObject.java | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 role-object/src/main/java/com/iluwatar/roleobject/ApplicationRoleObject.java diff --git a/role-object/src/main/java/com/iluwatar/roleobject/ApplicationRoleObject.java b/role-object/src/main/java/com/iluwatar/roleobject/ApplicationRoleObject.java new file mode 100644 index 000000000000..89388099fd4e --- /dev/null +++ b/role-object/src/main/java/com/iluwatar/roleobject/ApplicationRoleObject.java @@ -0,0 +1,7 @@ +package com.iluwatar.roleobject; + +public class ApplicationRoleObject { + public static void main(String[] args) { + System.out.println("Role-object"); + } +} From f09a7eb468731ca32d099223d3e1c00221ed259a Mon Sep 17 00:00:00 2001 From: Besok Date: Sat, 19 Oct 2019 18:15:20 +0100 Subject: [PATCH 03/31] add to init --- role-object/README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/role-object/README.md b/role-object/README.md index 8ffe47400dd8..44f99228926c 100644 --- a/role-object/README.md +++ b/role-object/README.md @@ -3,13 +3,15 @@ layout: pattern title: Role object folder: Migration permalink: /patterns/role-object/ -categories: Behavioral +categories: Structural tags: - Java - - Easy-to-implement + - Difficulty-Medium + - Handle Body Pattern --- ## Also known as +Post pattern, Extension Object pattern ## Intent From 20b4195fb2bd0c5a6bff4280c758a4e6b4e3ef6e Mon Sep 17 00:00:00 2001 From: Besok Date: Sun, 20 Oct 2019 20:22:54 +0100 Subject: [PATCH 04/31] add first impl --- role-object/README.md | 17 +++++- .../roleobject/ApplicationRoleObject.java | 55 ++++++++++++++++++- .../com/iluwatar/roleobject/BorrowerRole.java | 4 ++ .../com/iluwatar/roleobject/Customer.java | 12 ++++ .../com/iluwatar/roleobject/CustomerCore.java | 35 ++++++++++++ .../com/iluwatar/roleobject/CustomerRole.java | 25 +++++++++ .../com/iluwatar/roleobject/InvestorRole.java | 4 ++ .../java/com/iluwatar/roleobject/Role.java | 30 ++++++++++ 8 files changed, 179 insertions(+), 3 deletions(-) create mode 100644 role-object/src/main/java/com/iluwatar/roleobject/BorrowerRole.java create mode 100644 role-object/src/main/java/com/iluwatar/roleobject/Customer.java create mode 100644 role-object/src/main/java/com/iluwatar/roleobject/CustomerCore.java create mode 100644 role-object/src/main/java/com/iluwatar/roleobject/CustomerRole.java create mode 100644 role-object/src/main/java/com/iluwatar/roleobject/InvestorRole.java create mode 100644 role-object/src/main/java/com/iluwatar/roleobject/Role.java diff --git a/role-object/README.md b/role-object/README.md index 44f99228926c..3f71341e18fb 100644 --- a/role-object/README.md +++ b/role-object/README.md @@ -14,9 +14,22 @@ tags: Post pattern, Extension Object pattern ## Intent +Adapt an object to different client’s needs through transparently attached role objects, each one representing a role +the object has to play in that client’s context. The object manages its role set dynamically. By representing roles as +individual objects, different contexts are kept separate and system configuration is simplified. ## Applicability - -## Real world examples +Use the Role Object pattern, if: +- you want to handle a key abstraction in different contexts and you do not want to put the resulting contextspecific interfaces into the same class interface. +Words: 4895 Page 3 of 11 +- you want to handle the available roles dynamically so that they can be attached and removed on demand, that is +at runtime, rather than fixing them statically at compile-time. +- you want to treat the extensions transparently and need to preserve the logical object identity of the resulting +object conglomerate. +- you want to keep role/client pairs independent from each other so that changes to a role do not affect clients +that are not interested in that role. ## Credits +- [Hillside - Role object pattern](https://hillside.net/plop/plop97/Proceedings/riehle.pdf) +- [Role object](http://wiki.c2.com/?RoleObject) +- [Fowler - Dealing with roles](https://martinfowler.com/apsupp/roles.pdf) \ No newline at end of file diff --git a/role-object/src/main/java/com/iluwatar/roleobject/ApplicationRoleObject.java b/role-object/src/main/java/com/iluwatar/roleobject/ApplicationRoleObject.java index 89388099fd4e..3dc83e470b77 100644 --- a/role-object/src/main/java/com/iluwatar/roleobject/ApplicationRoleObject.java +++ b/role-object/src/main/java/com/iluwatar/roleobject/ApplicationRoleObject.java @@ -1,7 +1,60 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package com.iluwatar.roleobject; +/** + * The Role Object pattern suggests to model context-specific views + * of an object as separate role objects which are + * dynamically attached to and removed from the core object. + * We call the resulting composite object structure, + * consisting of the core and its role objects, a subject. + * A subject often plays several roles and the same role is likely to + * be played by different subjects. + * As an example consider two different customers playing the role of borrower and + * investor, respectively. Both roles could as well be played by a single Customer object. + * The common superclass for customer-specific roles is provided by CustomerRole, + * which also supports the Customer interface. + * The CustomerRole class is abstract and not meant to be instantiated. + * Concrete subclasses of CustomerRole, for example Borrower or Investor, + * define and implement the interface for specific roles. It is only + * these subclasses which are instantiated at runtime. + * The Borrower class defines the context-specific view of + * Customer objects as needed by the loan department. + * It defines additional operations to manage the customer’s + * credits and securities. Similarly, the Investor class adds operations specific + * to the investment department’s view of customers. + * A client like the loan application may either work with objects of the CustomerCore class, using the interface class + * Customer, or with objects of concrete CustomerRole subclasses. Suppose the loan application knows a particular + * Customer instance through its Customer interface. The loan application may want to check whether the Customer + * object plays the role of Borrower. + * To this end it calls hasRole() with a suitable role specification. For the purpose of + * our example, let’s assume we can name roles with a simple string. + * If the Customer object can play the role named + * “Borrower,” the loan application will ask it to return a reference to the corresponding object. + * The loan application may now use this reference to call Borrower-specific operations. + * + */ public class ApplicationRoleObject { public static void main(String[] args) { - System.out.println("Role-object"); } } diff --git a/role-object/src/main/java/com/iluwatar/roleobject/BorrowerRole.java b/role-object/src/main/java/com/iluwatar/roleobject/BorrowerRole.java new file mode 100644 index 000000000000..c900e3eed743 --- /dev/null +++ b/role-object/src/main/java/com/iluwatar/roleobject/BorrowerRole.java @@ -0,0 +1,4 @@ +package com.iluwatar.roleobject; + +public class BorrowerRole extends CustomerRole{ +} diff --git a/role-object/src/main/java/com/iluwatar/roleobject/Customer.java b/role-object/src/main/java/com/iluwatar/roleobject/Customer.java new file mode 100644 index 000000000000..c9cdab4e1dab --- /dev/null +++ b/role-object/src/main/java/com/iluwatar/roleobject/Customer.java @@ -0,0 +1,12 @@ +package com.iluwatar.roleobject; + +import java.util.Optional; + +public abstract class Customer { + + public abstract boolean addRole(Role role); + public abstract boolean hasRole(Role role); + public abstract boolean remRole(Role role); + public abstract Optional getRole(Role role,Class expectedRole); + +} diff --git a/role-object/src/main/java/com/iluwatar/roleobject/CustomerCore.java b/role-object/src/main/java/com/iluwatar/roleobject/CustomerCore.java new file mode 100644 index 000000000000..496022c06fe5 --- /dev/null +++ b/role-object/src/main/java/com/iluwatar/roleobject/CustomerCore.java @@ -0,0 +1,35 @@ +package com.iluwatar.roleobject; + +import java.util.Map; +import java.util.Objects; +import java.util.Optional; + +public class CustomerCore extends Customer { + + private Map roles; + + + @Override + public boolean addRole(Role role) { + return role.instance() + .map(rI -> roles.put(role, rI)) + .isPresent(); + } + + @Override + public boolean hasRole(Role role) { + return roles.containsKey(role); + } + + @Override + public boolean remRole(Role role) { + return Objects.nonNull(roles.remove(role)); + } + + @Override + public Optional getRole(Role role, Class expectedRole) { + return Optional.ofNullable(roles.get(role)) + .filter(expectedRole::isInstance) + .map(expectedRole::cast); + } +} diff --git a/role-object/src/main/java/com/iluwatar/roleobject/CustomerRole.java b/role-object/src/main/java/com/iluwatar/roleobject/CustomerRole.java new file mode 100644 index 000000000000..af2801f3dd6e --- /dev/null +++ b/role-object/src/main/java/com/iluwatar/roleobject/CustomerRole.java @@ -0,0 +1,25 @@ +package com.iluwatar.roleobject; + +import java.util.Optional; + +public class CustomerRole extends Customer{ + @Override + public boolean addRole(Role role) { + return false; + } + + @Override + public boolean hasRole(Role role) { + return false; + } + + @Override + public boolean remRole(Role role) { + return false; + } + + @Override + public Optional getRole(Role role, Class expectedRole) { + return Optional.empty(); + } +} diff --git a/role-object/src/main/java/com/iluwatar/roleobject/InvestorRole.java b/role-object/src/main/java/com/iluwatar/roleobject/InvestorRole.java new file mode 100644 index 000000000000..a8a85d9da578 --- /dev/null +++ b/role-object/src/main/java/com/iluwatar/roleobject/InvestorRole.java @@ -0,0 +1,4 @@ +package com.iluwatar.roleobject; + +public class InvestorRole extends CustomerRole{ +} diff --git a/role-object/src/main/java/com/iluwatar/roleobject/Role.java b/role-object/src/main/java/com/iluwatar/roleobject/Role.java new file mode 100644 index 000000000000..a59d6377beb6 --- /dev/null +++ b/role-object/src/main/java/com/iluwatar/roleobject/Role.java @@ -0,0 +1,30 @@ +package com.iluwatar.roleobject; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import sun.rmi.runtime.Log; + +import java.util.Optional; + +public enum Role { + Borrower(BorrowerRole.class), Investor(InvestorRole.class); + + private Class typeCst; + + Role(Class typeCst) { + this.typeCst = typeCst; + } + private static final Logger logger = LoggerFactory.getLogger(Role.class); + + @SuppressWarnings("unchecked") + Optional instance(){ + Class typeCst = this.typeCst; + try { + return (Optional) Optional.of(typeCst.newInstance()); + } catch (InstantiationException | IllegalAccessException e) { + logger.error("error creating an object",e); + } + return Optional.empty(); + } + +} From 630532cdda100036a2d9e8553b76af2a157d9b82 Mon Sep 17 00:00:00 2001 From: Besok Date: Thu, 24 Oct 2019 20:56:09 +0100 Subject: [PATCH 05/31] add pattern --- role-object/README.md | 12 +-- role-object/pom.xml | 8 +- .../roleobject/ApplicationRoleObject.java | 44 ++++++++-- .../com/iluwatar/roleobject/BorrowerRole.java | 15 ++++ .../com/iluwatar/roleobject/Customer.java | 47 ++++++++++- .../com/iluwatar/roleobject/CustomerCore.java | 34 ++++++-- .../com/iluwatar/roleobject/CustomerRole.java | 27 +------ .../com/iluwatar/roleobject/InvestorRole.java | 25 +++++- .../java/com/iluwatar/roleobject/Role.java | 15 ++-- .../roleobject/ApplicationRoleObjectTest.java | 13 +++ .../iluwatar/roleobject/BorrowerRoleTest.java | 18 +++++ .../iluwatar/roleobject/CustomerCoreTest.java | 81 +++++++++++++++++++ .../iluwatar/roleobject/InvestorRoleTest.java | 18 +++++ .../com/iluwatar/roleobject/RoleTest.java | 18 +++++ 14 files changed, 321 insertions(+), 54 deletions(-) create mode 100644 role-object/src/test/java/com/iluwatar/roleobject/ApplicationRoleObjectTest.java create mode 100644 role-object/src/test/java/com/iluwatar/roleobject/BorrowerRoleTest.java create mode 100644 role-object/src/test/java/com/iluwatar/roleobject/CustomerCoreTest.java create mode 100644 role-object/src/test/java/com/iluwatar/roleobject/InvestorRoleTest.java create mode 100644 role-object/src/test/java/com/iluwatar/roleobject/RoleTest.java diff --git a/role-object/README.md b/role-object/README.md index 3f71341e18fb..c97177d7b1d5 100644 --- a/role-object/README.md +++ b/role-object/README.md @@ -20,14 +20,10 @@ individual objects, different contexts are kept separate and system configuratio ## Applicability Use the Role Object pattern, if: -- you want to handle a key abstraction in different contexts and you do not want to put the resulting contextspecific interfaces into the same class interface. -Words: 4895 Page 3 of 11 -- you want to handle the available roles dynamically so that they can be attached and removed on demand, that is -at runtime, rather than fixing them statically at compile-time. -- you want to treat the extensions transparently and need to preserve the logical object identity of the resulting -object conglomerate. -- you want to keep role/client pairs independent from each other so that changes to a role do not affect clients -that are not interested in that role. +- you want to handle a key abstraction in different contexts and you do not want to put the resulting context specific interfaces into the same class interface. +- you want to handle the available roles dynamically so that they can be attached and removed on demand, that is at runtime, rather than fixing them statically at compile-time. +- you want to treat the extensions transparently and need to preserve the logical object identity of the resultingobject conglomerate. +- you want to keep role/client pairs independent from each other so that changes to a role do not affect clients that are not interested in that role. ## Credits - [Hillside - Role object pattern](https://hillside.net/plop/plop97/Proceedings/riehle.pdf) diff --git a/role-object/pom.xml b/role-object/pom.xml index 9d7e9b88be6e..c9feb1419afd 100644 --- a/role-object/pom.xml +++ b/role-object/pom.xml @@ -33,6 +33,12 @@ role-object - + + + junit + junit + test + + diff --git a/role-object/src/main/java/com/iluwatar/roleobject/ApplicationRoleObject.java b/role-object/src/main/java/com/iluwatar/roleobject/ApplicationRoleObject.java index 3dc83e470b77..1006fe084fca 100644 --- a/role-object/src/main/java/com/iluwatar/roleobject/ApplicationRoleObject.java +++ b/role-object/src/main/java/com/iluwatar/roleobject/ApplicationRoleObject.java @@ -22,6 +22,11 @@ */ package com.iluwatar.roleobject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static com.iluwatar.roleobject.Role.*; + /** * The Role Object pattern suggests to model context-specific views * of an object as separate role objects which are @@ -34,12 +39,12 @@ * investor, respectively. Both roles could as well be played by a single Customer object. * The common superclass for customer-specific roles is provided by CustomerRole, * which also supports the Customer interface. + *

* The CustomerRole class is abstract and not meant to be instantiated. * Concrete subclasses of CustomerRole, for example Borrower or Investor, * define and implement the interface for specific roles. It is only * these subclasses which are instantiated at runtime. - * The Borrower class defines the context-specific view of - * Customer objects as needed by the loan department. + * The Borrower class defines the context-specific view of Customer objects as needed by the loan department. * It defines additional operations to manage the customer’s * credits and securities. Similarly, the Investor class adds operations specific * to the investment department’s view of customers. @@ -48,13 +53,40 @@ * Customer instance through its Customer interface. The loan application may want to check whether the Customer * object plays the role of Borrower. * To this end it calls hasRole() with a suitable role specification. For the purpose of - * our example, let’s assume we can name roles with a simple string. - * If the Customer object can play the role named - * “Borrower,” the loan application will ask it to return a reference to the corresponding object. + * our example, let’s assume we can name roles with enum. + * If the Customer object can play the role named “Borrower,” the loan application will ask it to return a reference to the corresponding object. * The loan application may now use this reference to call Borrower-specific operations. - * */ public class ApplicationRoleObject { + + private static final Logger logger = LoggerFactory.getLogger(Role.class); + public static void main(String[] args) { + Customer customer = Customer.newCustomer(Borrower, Investor); + + logger.info(" the new customer created : {}", customer); + + boolean hasBorrowerRole = customer.hasRole(Borrower); + logger.info(" customer has a borrowed role - {}", hasBorrowerRole); + boolean hasInvestorRole = customer.hasRole(Investor); + logger.info(" customer has an investor role - {}", hasInvestorRole); + + customer.getRole(Investor, InvestorRole.class) + .ifPresent(inv -> { + inv.setAmountToInvest(1000); + inv.setName("Billy"); + }); + customer.getRole(Borrower, BorrowerRole.class) + .ifPresent(inv -> inv.setName("Johny")); + + customer.getRole(Investor, InvestorRole.class) + .map(InvestorRole::invest) + .ifPresent(logger::info); + + customer.getRole(Borrower, BorrowerRole.class) + .map(BorrowerRole::borrow) + .ifPresent(logger::info); } + + } diff --git a/role-object/src/main/java/com/iluwatar/roleobject/BorrowerRole.java b/role-object/src/main/java/com/iluwatar/roleobject/BorrowerRole.java index c900e3eed743..8bc423e4bdc8 100644 --- a/role-object/src/main/java/com/iluwatar/roleobject/BorrowerRole.java +++ b/role-object/src/main/java/com/iluwatar/roleobject/BorrowerRole.java @@ -1,4 +1,19 @@ package com.iluwatar.roleobject; public class BorrowerRole extends CustomerRole{ + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String borrow(){ + return String.join(" ", + "A borrower",name,"wants to get some money."); + } + } diff --git a/role-object/src/main/java/com/iluwatar/roleobject/Customer.java b/role-object/src/main/java/com/iluwatar/roleobject/Customer.java index c9cdab4e1dab..c8bf5a857165 100644 --- a/role-object/src/main/java/com/iluwatar/roleobject/Customer.java +++ b/role-object/src/main/java/com/iluwatar/roleobject/Customer.java @@ -2,11 +2,56 @@ import java.util.Optional; +/** + * The main abstraction to work with Customer. + */ public abstract class Customer { + /** + * Add specific role @see {@link Role} + * + * @param role to add + * @return true if the operation has been successful otherwise false + */ public abstract boolean addRole(Role role); + + /** + * Check specific role @see {@link Role} + * + * @param role to check + * @return true if the role exists otherwise false + */ + public abstract boolean hasRole(Role role); + + /** + * Remove specific role @see {@link Role} + * + * @param role to remove + * @return true if the operation has been successful otherwise false + */ public abstract boolean remRole(Role role); - public abstract Optional getRole(Role role,Class expectedRole); + + /** + * Get specific instance associated with this role @see {@link Role} + * + * @param role to get + * @param expectedRole instance class expected to get + * @return optional with value if the instance exists and corresponds expected class + */ + public abstract Optional getRole(Role role, Class expectedRole); + + + public static Customer newCustomer() { + return new CustomerCore(); + } + + public static Customer newCustomer(Role... role) { + Customer customer = newCustomer(); + for (Role r : role) { + customer.addRole(r); + } + return customer; + } } diff --git a/role-object/src/main/java/com/iluwatar/roleobject/CustomerCore.java b/role-object/src/main/java/com/iluwatar/roleobject/CustomerCore.java index 496022c06fe5..3c2c7d4068ce 100644 --- a/role-object/src/main/java/com/iluwatar/roleobject/CustomerCore.java +++ b/role-object/src/main/java/com/iluwatar/roleobject/CustomerCore.java @@ -1,19 +1,30 @@ package com.iluwatar.roleobject; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; - +import java.util.*; + +/** + * Core class to store different customer roles + * + * @see CustomerRole + * Note: not thread safe + */ public class CustomerCore extends Customer { private Map roles; + public CustomerCore() { + roles = new HashMap<>(); + } @Override public boolean addRole(Role role) { - return role.instance() - .map(rI -> roles.put(role, rI)) - .isPresent(); + return role + .instance() + .map(inst -> { + roles.put(role, inst); + return true; + }) + .orElse(false); } @Override @@ -28,8 +39,15 @@ public boolean remRole(Role role) { @Override public Optional getRole(Role role, Class expectedRole) { - return Optional.ofNullable(roles.get(role)) + return Optional + .ofNullable(roles.get(role)) .filter(expectedRole::isInstance) .map(expectedRole::cast); } + + @Override + public String toString() { + String roles = Arrays.toString(this.roles.keySet().toArray()); + return "Customer{roles=" + roles + "}"; + } } diff --git a/role-object/src/main/java/com/iluwatar/roleobject/CustomerRole.java b/role-object/src/main/java/com/iluwatar/roleobject/CustomerRole.java index af2801f3dd6e..e9806246bae1 100644 --- a/role-object/src/main/java/com/iluwatar/roleobject/CustomerRole.java +++ b/role-object/src/main/java/com/iluwatar/roleobject/CustomerRole.java @@ -1,25 +1,6 @@ package com.iluwatar.roleobject; -import java.util.Optional; - -public class CustomerRole extends Customer{ - @Override - public boolean addRole(Role role) { - return false; - } - - @Override - public boolean hasRole(Role role) { - return false; - } - - @Override - public boolean remRole(Role role) { - return false; - } - - @Override - public Optional getRole(Role role, Class expectedRole) { - return Optional.empty(); - } -} +/** + * Key abstraction for segregated roles + */ +public abstract class CustomerRole extends CustomerCore{} diff --git a/role-object/src/main/java/com/iluwatar/roleobject/InvestorRole.java b/role-object/src/main/java/com/iluwatar/roleobject/InvestorRole.java index a8a85d9da578..4267d4d95784 100644 --- a/role-object/src/main/java/com/iluwatar/roleobject/InvestorRole.java +++ b/role-object/src/main/java/com/iluwatar/roleobject/InvestorRole.java @@ -1,4 +1,27 @@ package com.iluwatar.roleobject; -public class InvestorRole extends CustomerRole{ +public class InvestorRole extends CustomerRole { + private String name; + private long amountToInvest; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public long getAmountToInvest() { + return amountToInvest; + } + + public void setAmountToInvest(long amountToInvest) { + this.amountToInvest = amountToInvest; + } + + public String invest() { + return String.join(" ", + "Investor", name, "has invested", String.valueOf(amountToInvest), "dollars"); + } } diff --git a/role-object/src/main/java/com/iluwatar/roleobject/Role.java b/role-object/src/main/java/com/iluwatar/roleobject/Role.java index a59d6377beb6..c1934f7c524b 100644 --- a/role-object/src/main/java/com/iluwatar/roleobject/Role.java +++ b/role-object/src/main/java/com/iluwatar/roleobject/Role.java @@ -2,27 +2,30 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import sun.rmi.runtime.Log; import java.util.Optional; +/** + * Possible roles + */ public enum Role { Borrower(BorrowerRole.class), Investor(InvestorRole.class); - private Class typeCst; + private Class typeCst; - Role(Class typeCst) { + Role(Class typeCst) { this.typeCst = typeCst; } + private static final Logger logger = LoggerFactory.getLogger(Role.class); @SuppressWarnings("unchecked") - Optional instance(){ - Class typeCst = this.typeCst; + public Optional instance() { + Class typeCst = this.typeCst; try { return (Optional) Optional.of(typeCst.newInstance()); } catch (InstantiationException | IllegalAccessException e) { - logger.error("error creating an object",e); + logger.error("error creating an object", e); } return Optional.empty(); } diff --git a/role-object/src/test/java/com/iluwatar/roleobject/ApplicationRoleObjectTest.java b/role-object/src/test/java/com/iluwatar/roleobject/ApplicationRoleObjectTest.java new file mode 100644 index 000000000000..f2c822912332 --- /dev/null +++ b/role-object/src/test/java/com/iluwatar/roleobject/ApplicationRoleObjectTest.java @@ -0,0 +1,13 @@ +package com.iluwatar.roleobject; + +import org.junit.Test; + +import static org.junit.Assert.*; + +public class ApplicationRoleObjectTest { + + @Test + public void mainTest() { + ApplicationRoleObject.main(new String[]{}); + } +} \ No newline at end of file diff --git a/role-object/src/test/java/com/iluwatar/roleobject/BorrowerRoleTest.java b/role-object/src/test/java/com/iluwatar/roleobject/BorrowerRoleTest.java new file mode 100644 index 000000000000..6ba26009f1e0 --- /dev/null +++ b/role-object/src/test/java/com/iluwatar/roleobject/BorrowerRoleTest.java @@ -0,0 +1,18 @@ +package com.iluwatar.roleobject; + +import org.junit.Assert; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class BorrowerRoleTest { + + @Test + public void borrowTest() { + BorrowerRole borrowerRole = new BorrowerRole(); + borrowerRole.setName("test"); + String res = "A borrower test wants to get some money."; + + Assert.assertEquals(borrowerRole.borrow(),res); + } +} \ No newline at end of file diff --git a/role-object/src/test/java/com/iluwatar/roleobject/CustomerCoreTest.java b/role-object/src/test/java/com/iluwatar/roleobject/CustomerCoreTest.java new file mode 100644 index 000000000000..64712e11d184 --- /dev/null +++ b/role-object/src/test/java/com/iluwatar/roleobject/CustomerCoreTest.java @@ -0,0 +1,81 @@ +package com.iluwatar.roleobject; + +import org.junit.Test; + +import java.util.Optional; + +import static org.junit.Assert.*; + +public class CustomerCoreTest { + + @Test + public void addRole() { + CustomerCore core = new CustomerCore(); + boolean add = core.addRole(Role.Borrower); + assertTrue(add); + + } + + @Test + public void hasRole() { + CustomerCore core = new CustomerCore(); + core.addRole(Role.Borrower); + + boolean has = core.hasRole(Role.Borrower); + assertTrue(has); + + boolean notHas = core.hasRole(Role.Investor); + assertFalse(notHas); + } + + @Test + public void remRole() { + CustomerCore core = new CustomerCore(); + core.addRole(Role.Borrower); + + Optional bRole = core.getRole(Role.Borrower, BorrowerRole.class); + assertTrue(bRole.isPresent()); + + boolean res = core.remRole(Role.Borrower); + assertTrue(res); + + Optional empt = core.getRole(Role.Borrower, BorrowerRole.class); + assertFalse(empt.isPresent()); + + } + + @Test + public void getRole() { + CustomerCore core = new CustomerCore(); + core.addRole(Role.Borrower); + + Optional bRole = core.getRole(Role.Borrower, BorrowerRole.class); + assertTrue(bRole.isPresent()); + + Optional nonRole = core.getRole(Role.Borrower, InvestorRole.class); + assertFalse(nonRole.isPresent()); + + Optional invRole = core.getRole(Role.Investor, InvestorRole.class); + assertFalse(invRole.isPresent()); + + + } + + + @Test + public void toStringTest() { + CustomerCore core = new CustomerCore(); + core.addRole(Role.Borrower); + assertEquals(core.toString(), "Customer{roles=[Borrower]}"); + + core = new CustomerCore(); + core.addRole(Role.Investor); + assertEquals(core.toString(), "Customer{roles=[Investor]}"); + + core = new CustomerCore(); + assertEquals(core.toString(), "Customer{roles=[]}"); + + + } + +} \ No newline at end of file diff --git a/role-object/src/test/java/com/iluwatar/roleobject/InvestorRoleTest.java b/role-object/src/test/java/com/iluwatar/roleobject/InvestorRoleTest.java new file mode 100644 index 000000000000..9274eae7cfe7 --- /dev/null +++ b/role-object/src/test/java/com/iluwatar/roleobject/InvestorRoleTest.java @@ -0,0 +1,18 @@ +package com.iluwatar.roleobject; + +import org.junit.Assert; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class InvestorRoleTest { + + @Test + public void investTest() { + InvestorRole investorRole = new InvestorRole(); + investorRole.setName("test"); + investorRole.setAmountToInvest(10); + String res = "Investor test has invested 10 dollars"; + Assert.assertEquals(investorRole.invest(), res); + } +} \ No newline at end of file diff --git a/role-object/src/test/java/com/iluwatar/roleobject/RoleTest.java b/role-object/src/test/java/com/iluwatar/roleobject/RoleTest.java new file mode 100644 index 000000000000..dda32622851c --- /dev/null +++ b/role-object/src/test/java/com/iluwatar/roleobject/RoleTest.java @@ -0,0 +1,18 @@ +package com.iluwatar.roleobject; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.Optional; + +import static org.junit.Assert.*; + +public class RoleTest { + + @Test + public void instanceTest() { + Optional instance = Role.Borrower.instance(); + Assert.assertTrue(instance.isPresent()); + Assert.assertEquals(instance.get().getClass(),BorrowerRole.class); + } +} \ No newline at end of file From 9403d53096a63a8f2e4e0e8db6a153af621bebeb Mon Sep 17 00:00:00 2001 From: Besok Date: Thu, 24 Oct 2019 20:59:21 +0100 Subject: [PATCH 06/31] add license --- .../com/iluwatar/roleobject/BorrowerRole.java | 22 +++++++++++++++++ .../com/iluwatar/roleobject/Customer.java | 22 +++++++++++++++++ .../com/iluwatar/roleobject/CustomerCore.java | 22 +++++++++++++++++ .../com/iluwatar/roleobject/CustomerRole.java | 22 +++++++++++++++++ .../com/iluwatar/roleobject/InvestorRole.java | 22 +++++++++++++++++ .../java/com/iluwatar/roleobject/Role.java | 22 +++++++++++++++++ .../roleobject/ApplicationRoleObjectTest.java | 24 +++++++++++++++++-- .../iluwatar/roleobject/BorrowerRoleTest.java | 22 +++++++++++++++++ .../iluwatar/roleobject/CustomerCoreTest.java | 22 +++++++++++++++++ .../iluwatar/roleobject/InvestorRoleTest.java | 24 +++++++++++++++++-- .../com/iluwatar/roleobject/RoleTest.java | 22 +++++++++++++++++ 11 files changed, 242 insertions(+), 4 deletions(-) diff --git a/role-object/src/main/java/com/iluwatar/roleobject/BorrowerRole.java b/role-object/src/main/java/com/iluwatar/roleobject/BorrowerRole.java index 8bc423e4bdc8..c48829a0afd9 100644 --- a/role-object/src/main/java/com/iluwatar/roleobject/BorrowerRole.java +++ b/role-object/src/main/java/com/iluwatar/roleobject/BorrowerRole.java @@ -1,3 +1,25 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package com.iluwatar.roleobject; public class BorrowerRole extends CustomerRole{ diff --git a/role-object/src/main/java/com/iluwatar/roleobject/Customer.java b/role-object/src/main/java/com/iluwatar/roleobject/Customer.java index c8bf5a857165..ebcddff4b154 100644 --- a/role-object/src/main/java/com/iluwatar/roleobject/Customer.java +++ b/role-object/src/main/java/com/iluwatar/roleobject/Customer.java @@ -1,3 +1,25 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package com.iluwatar.roleobject; import java.util.Optional; diff --git a/role-object/src/main/java/com/iluwatar/roleobject/CustomerCore.java b/role-object/src/main/java/com/iluwatar/roleobject/CustomerCore.java index 3c2c7d4068ce..5de27aa9295d 100644 --- a/role-object/src/main/java/com/iluwatar/roleobject/CustomerCore.java +++ b/role-object/src/main/java/com/iluwatar/roleobject/CustomerCore.java @@ -1,3 +1,25 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package com.iluwatar.roleobject; import java.util.*; diff --git a/role-object/src/main/java/com/iluwatar/roleobject/CustomerRole.java b/role-object/src/main/java/com/iluwatar/roleobject/CustomerRole.java index e9806246bae1..40fe2341b3a9 100644 --- a/role-object/src/main/java/com/iluwatar/roleobject/CustomerRole.java +++ b/role-object/src/main/java/com/iluwatar/roleobject/CustomerRole.java @@ -1,3 +1,25 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package com.iluwatar.roleobject; /** diff --git a/role-object/src/main/java/com/iluwatar/roleobject/InvestorRole.java b/role-object/src/main/java/com/iluwatar/roleobject/InvestorRole.java index 4267d4d95784..9f3ecdae3725 100644 --- a/role-object/src/main/java/com/iluwatar/roleobject/InvestorRole.java +++ b/role-object/src/main/java/com/iluwatar/roleobject/InvestorRole.java @@ -1,3 +1,25 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package com.iluwatar.roleobject; public class InvestorRole extends CustomerRole { diff --git a/role-object/src/main/java/com/iluwatar/roleobject/Role.java b/role-object/src/main/java/com/iluwatar/roleobject/Role.java index c1934f7c524b..f6c739891566 100644 --- a/role-object/src/main/java/com/iluwatar/roleobject/Role.java +++ b/role-object/src/main/java/com/iluwatar/roleobject/Role.java @@ -1,3 +1,25 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package com.iluwatar.roleobject; import org.slf4j.Logger; diff --git a/role-object/src/test/java/com/iluwatar/roleobject/ApplicationRoleObjectTest.java b/role-object/src/test/java/com/iluwatar/roleobject/ApplicationRoleObjectTest.java index f2c822912332..831781d7103b 100644 --- a/role-object/src/test/java/com/iluwatar/roleobject/ApplicationRoleObjectTest.java +++ b/role-object/src/test/java/com/iluwatar/roleobject/ApplicationRoleObjectTest.java @@ -1,9 +1,29 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package com.iluwatar.roleobject; import org.junit.Test; -import static org.junit.Assert.*; - public class ApplicationRoleObjectTest { @Test diff --git a/role-object/src/test/java/com/iluwatar/roleobject/BorrowerRoleTest.java b/role-object/src/test/java/com/iluwatar/roleobject/BorrowerRoleTest.java index 6ba26009f1e0..1641e20fae5c 100644 --- a/role-object/src/test/java/com/iluwatar/roleobject/BorrowerRoleTest.java +++ b/role-object/src/test/java/com/iluwatar/roleobject/BorrowerRoleTest.java @@ -1,3 +1,25 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package com.iluwatar.roleobject; import org.junit.Assert; diff --git a/role-object/src/test/java/com/iluwatar/roleobject/CustomerCoreTest.java b/role-object/src/test/java/com/iluwatar/roleobject/CustomerCoreTest.java index 64712e11d184..1b2987400d05 100644 --- a/role-object/src/test/java/com/iluwatar/roleobject/CustomerCoreTest.java +++ b/role-object/src/test/java/com/iluwatar/roleobject/CustomerCoreTest.java @@ -1,3 +1,25 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package com.iluwatar.roleobject; import org.junit.Test; diff --git a/role-object/src/test/java/com/iluwatar/roleobject/InvestorRoleTest.java b/role-object/src/test/java/com/iluwatar/roleobject/InvestorRoleTest.java index 9274eae7cfe7..06afa1016275 100644 --- a/role-object/src/test/java/com/iluwatar/roleobject/InvestorRoleTest.java +++ b/role-object/src/test/java/com/iluwatar/roleobject/InvestorRoleTest.java @@ -1,10 +1,30 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package com.iluwatar.roleobject; import org.junit.Assert; import org.junit.Test; -import static org.junit.Assert.*; - public class InvestorRoleTest { @Test diff --git a/role-object/src/test/java/com/iluwatar/roleobject/RoleTest.java b/role-object/src/test/java/com/iluwatar/roleobject/RoleTest.java index dda32622851c..6ae5b0cd8857 100644 --- a/role-object/src/test/java/com/iluwatar/roleobject/RoleTest.java +++ b/role-object/src/test/java/com/iluwatar/roleobject/RoleTest.java @@ -1,3 +1,25 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package com.iluwatar.roleobject; import org.junit.Assert; From e3827945c8bbd0bc39c49b16960da03360c851ee Mon Sep 17 00:00:00 2001 From: Besok Date: Sat, 26 Oct 2019 18:28:20 +0100 Subject: [PATCH 07/31] add changes --- .../roleobject/ApplicationRoleObject.java | 25 ++++++++++--------- .../com/iluwatar/roleobject/BorrowerRole.java | 3 +-- .../com/iluwatar/roleobject/InvestorRole.java | 3 +-- .../iluwatar/roleobject/BorrowerRoleTest.java | 2 +- 4 files changed, 16 insertions(+), 17 deletions(-) diff --git a/role-object/src/main/java/com/iluwatar/roleobject/ApplicationRoleObject.java b/role-object/src/main/java/com/iluwatar/roleobject/ApplicationRoleObject.java index 1006fe084fca..b8296dabacc6 100644 --- a/role-object/src/main/java/com/iluwatar/roleobject/ApplicationRoleObject.java +++ b/role-object/src/main/java/com/iluwatar/roleobject/ApplicationRoleObject.java @@ -36,25 +36,26 @@ * A subject often plays several roles and the same role is likely to * be played by different subjects. * As an example consider two different customers playing the role of borrower and - * investor, respectively. Both roles could as well be played by a single Customer object. - * The common superclass for customer-specific roles is provided by CustomerRole, - * which also supports the Customer interface. + * investor, respectively. Both roles could as well be played by a single {@link Customer} object. + * The common superclass for customer-specific roles is provided by {@link CustomerRole}, + * which also supports the {@link Customer} interface. *

- * The CustomerRole class is abstract and not meant to be instantiated. - * Concrete subclasses of CustomerRole, for example Borrower or Investor, + * The {@link CustomerRole} class is abstract and not meant to be instantiated. + * Concrete subclasses of {@link CustomerRole}, for example {@link BorrowerRole} or {@link InvestorRole}, * define and implement the interface for specific roles. It is only * these subclasses which are instantiated at runtime. - * The Borrower class defines the context-specific view of Customer objects as needed by the loan department. + * The {@link BorrowerRole} class defines the context-specific view of {@link Customer} objects as needed by the loan department. * It defines additional operations to manage the customer’s - * credits and securities. Similarly, the Investor class adds operations specific + * credits and securities. Similarly, the {@link InvestorRole} class adds operations specific * to the investment department’s view of customers. - * A client like the loan application may either work with objects of the CustomerCore class, using the interface class - * Customer, or with objects of concrete CustomerRole subclasses. Suppose the loan application knows a particular - * Customer instance through its Customer interface. The loan application may want to check whether the Customer + * A client like the loan application may either work with objects of the {@link CustomerRole} class, using the interface class + * {@link Customer}, or with objects of concrete {@link CustomerRole} subclasses. Suppose the loan application knows a particular + * {@link Customer} instance through its {@link Customer} interface. The loan application may want to check whether the {@link Customer} * object plays the role of Borrower. - * To this end it calls hasRole() with a suitable role specification. For the purpose of + * To this end it calls {@link Customer#hasRole(Role)} with a suitable role specification. For the purpose of * our example, let’s assume we can name roles with enum. - * If the Customer object can play the role named “Borrower,” the loan application will ask it to return a reference to the corresponding object. + * If the {@link Customer} object can play the role named “Borrower,” the loan application will ask it + * to return a reference to the corresponding object. * The loan application may now use this reference to call Borrower-specific operations. */ public class ApplicationRoleObject { diff --git a/role-object/src/main/java/com/iluwatar/roleobject/BorrowerRole.java b/role-object/src/main/java/com/iluwatar/roleobject/BorrowerRole.java index c48829a0afd9..425d9511d083 100644 --- a/role-object/src/main/java/com/iluwatar/roleobject/BorrowerRole.java +++ b/role-object/src/main/java/com/iluwatar/roleobject/BorrowerRole.java @@ -34,8 +34,7 @@ public void setName(String name) { } public String borrow(){ - return String.join(" ", - "A borrower",name,"wants to get some money."); + return String.format("Borrower %s wants to get some money.",name); } } diff --git a/role-object/src/main/java/com/iluwatar/roleobject/InvestorRole.java b/role-object/src/main/java/com/iluwatar/roleobject/InvestorRole.java index 9f3ecdae3725..6d5c17c904f7 100644 --- a/role-object/src/main/java/com/iluwatar/roleobject/InvestorRole.java +++ b/role-object/src/main/java/com/iluwatar/roleobject/InvestorRole.java @@ -43,7 +43,6 @@ public void setAmountToInvest(long amountToInvest) { } public String invest() { - return String.join(" ", - "Investor", name, "has invested", String.valueOf(amountToInvest), "dollars"); + return String.format("Investor %s has invested %d dollars", name, amountToInvest); } } diff --git a/role-object/src/test/java/com/iluwatar/roleobject/BorrowerRoleTest.java b/role-object/src/test/java/com/iluwatar/roleobject/BorrowerRoleTest.java index 1641e20fae5c..0c0f92fc2322 100644 --- a/role-object/src/test/java/com/iluwatar/roleobject/BorrowerRoleTest.java +++ b/role-object/src/test/java/com/iluwatar/roleobject/BorrowerRoleTest.java @@ -33,7 +33,7 @@ public class BorrowerRoleTest { public void borrowTest() { BorrowerRole borrowerRole = new BorrowerRole(); borrowerRole.setName("test"); - String res = "A borrower test wants to get some money."; + String res = "Borrower test wants to get some money."; Assert.assertEquals(borrowerRole.borrow(),res); } From 768e6471085635c66c8128b100e628e9fcdae29b Mon Sep 17 00:00:00 2001 From: Besok Date: Sat, 2 Nov 2019 11:29:52 +0000 Subject: [PATCH 08/31] add saga init dsc --- pom.xml | 2 + saga/README.md | 45 +++++++++++ saga/pom.xml | 44 +++++++++++ stirring-clicker/pom.xml | 28 +++++++ .../ie/home/besok/stirrings/Application.java | 15 ++++ .../java/ie/home/besok/stirrings/Counter.java | 14 ++++ .../ie/home/besok/stirrings/FileStorage.java | 37 +++++++++ .../java/ie/home/besok/stirrings/Gui.java | 73 ++++++++++++++++++ stirring-clicker/src/main/resources/1.png | Bin 0 -> 4434 bytes stirring-clicker/src/main/resources/2.jpg | Bin 0 -> 3603 bytes stirring-clicker/src/main/resources/3.jpg | Bin 0 -> 2903 bytes .../home/besok/stirrings/FileStorageTest.java | 25 ++++++ 12 files changed, 283 insertions(+) create mode 100644 saga/README.md create mode 100644 saga/pom.xml create mode 100644 stirring-clicker/pom.xml create mode 100644 stirring-clicker/src/main/java/ie/home/besok/stirrings/Application.java create mode 100644 stirring-clicker/src/main/java/ie/home/besok/stirrings/Counter.java create mode 100644 stirring-clicker/src/main/java/ie/home/besok/stirrings/FileStorage.java create mode 100644 stirring-clicker/src/main/java/ie/home/besok/stirrings/Gui.java create mode 100644 stirring-clicker/src/main/resources/1.png create mode 100644 stirring-clicker/src/main/resources/2.jpg create mode 100644 stirring-clicker/src/main/resources/3.jpg create mode 100644 stirring-clicker/src/test/java/ie/home/besok/stirrings/FileStorageTest.java diff --git a/pom.xml b/pom.xml index 22dedc14a59e..4e8b76c78ab7 100644 --- a/pom.xml +++ b/pom.xml @@ -183,6 +183,8 @@ data-locality subclass-sandbox circuit-breaker + role-object + saga diff --git a/saga/README.md b/saga/README.md new file mode 100644 index 000000000000..12e4c8482396 --- /dev/null +++ b/saga/README.md @@ -0,0 +1,45 @@ +--- +layout: pattern +title: Saga +folder: Communication +permalink: /patterns/saga/ +categories: Behavioral +tags: + - Java + - Difficulty-Expert + - Idiom + - Distributed communication +--- + +## Also known as +This pattern has a similar goal with two-phase commit (XA transaction) + +## Intent +This pattern is used in distributed services to perform a group of operations atomically. +This is an analog of transaction in a database but in terms of microservices architecture this is performed in a distributed environment + +## Explanation +A saga is a sequence of local transactions in a certain context. If one transaction fails for some reason, +the saga executes compensating transactions(rollbacks) to undo the impact of the preceding transactions. +There are two types of Saga: + +- Choreography-Based Saga. +In this approach, there is no central orchestrator. +Each service participating in the Saga performs their transaction and publish events. +The other services act upon those events and perform their transactions. +Also, they may or not publish other events based on the situation. + +- Orchestration-Based Saga +In this approach, there is a Saga orchestrator that manages all the transactions and directs +the participant services to execute local transactions based on events. +This orchestrator can also be though of as a Saga Manager. + +## Applicability +Use the Saga pattern, if: +- you need to perform a group of operations related to different microservices atomically +- you need to rollback changes in different places in case of failure one of the operation +- you need to take care of data consistency in different places including different databases +- you can not use 2PC(two phase commit) + +## Credits +- [pattern description](https://microservices.io/patterns/data/saga.html) \ No newline at end of file diff --git a/saga/pom.xml b/saga/pom.xml new file mode 100644 index 000000000000..26c3312373a2 --- /dev/null +++ b/saga/pom.xml @@ -0,0 +1,44 @@ + + + + 4.0.0 + + com.iluwatar + java-design-patterns + 1.22.0-SNAPSHOT + + + saga + + + junit + junit + test + + + + diff --git a/stirring-clicker/pom.xml b/stirring-clicker/pom.xml new file mode 100644 index 000000000000..b0d223016f24 --- /dev/null +++ b/stirring-clicker/pom.xml @@ -0,0 +1,28 @@ + + + 4.0.0 + + ie.home.besok + move-clicker + 1.0 + + 1.8 + 1.8 + + + + + org.projectlombok + lombok + 1.18.10 + + + + junit + junit + 4.12 + + + \ No newline at end of file diff --git a/stirring-clicker/src/main/java/ie/home/besok/stirrings/Application.java b/stirring-clicker/src/main/java/ie/home/besok/stirrings/Application.java new file mode 100644 index 000000000000..0835470bc987 --- /dev/null +++ b/stirring-clicker/src/main/java/ie/home/besok/stirrings/Application.java @@ -0,0 +1,15 @@ +package ie.home.besok.stirrings; + +import java.awt.*; +import java.io.IOException; + +public class Application { + public static void main(String[] args) throws IOException { + FileStorage storage = new FileStorage(); + + EventQueue.invokeLater(() -> { + Gui gui = new Gui(storage); + gui.setVisible(true); + }); + } +} diff --git a/stirring-clicker/src/main/java/ie/home/besok/stirrings/Counter.java b/stirring-clicker/src/main/java/ie/home/besok/stirrings/Counter.java new file mode 100644 index 000000000000..b0f93f9d76c3 --- /dev/null +++ b/stirring-clicker/src/main/java/ie/home/besok/stirrings/Counter.java @@ -0,0 +1,14 @@ +package ie.home.besok.stirrings; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +public class Counter { + public Map count(List dates){ + return null; + } +} diff --git a/stirring-clicker/src/main/java/ie/home/besok/stirrings/FileStorage.java b/stirring-clicker/src/main/java/ie/home/besok/stirrings/FileStorage.java new file mode 100644 index 000000000000..c5784eb50795 --- /dev/null +++ b/stirring-clicker/src/main/java/ie/home/besok/stirrings/FileStorage.java @@ -0,0 +1,37 @@ +package ie.home.besok.stirrings; + +import lombok.extern.slf4j.Slf4j; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.time.LocalDateTime; +import java.util.List; + +public class FileStorage { + + private Path file; + + public FileStorage() throws IOException { + this.file = Paths.get("data.log"); + if(!Files.exists(file)){ + Files.createFile(file); + } + } + + public void plus() { + String line = LocalDateTime.now().toString()+System.lineSeparator(); + try { + Files.write(file, line.getBytes(), StandardOpenOption.APPEND); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public List get() throws IOException { + return Files.readAllLines(file); + } + +} diff --git a/stirring-clicker/src/main/java/ie/home/besok/stirrings/Gui.java b/stirring-clicker/src/main/java/ie/home/besok/stirrings/Gui.java new file mode 100644 index 000000000000..3df3e21313b5 --- /dev/null +++ b/stirring-clicker/src/main/java/ie/home/besok/stirrings/Gui.java @@ -0,0 +1,73 @@ +package ie.home.besok.stirrings; + +import javax.imageio.ImageIO; +import javax.swing.*; +import java.awt.*; +import java.io.IOException; +import java.net.URL; + +public class Gui extends JFrame { + + private FileStorage storage; + + public Gui(FileStorage storage) { + this.storage = storage; + try { + createUI(storage); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private void createUI(FileStorage storage) throws IOException { + setTitle("Stirring counter"); + setSize(300, 300); + setLocationRelativeTo(null); + + + JButton button = createButton(storage); + JButton graphick = new JButton(); + graphick.setIcon(getIcon("3.jpg")); + + + Container pane = getContentPane(); + GroupLayout gl = new GroupLayout(pane); + pane.setLayout(gl); + + gl.setAutoCreateContainerGaps(true); + + gl.setHorizontalGroup( + gl.createSequentialGroup().addComponent(button).addComponent(graphick) + ); + + gl.setVerticalGroup(gl.createSequentialGroup().addComponent(button).addComponent(graphick)); + + + button.addActionListener((event) -> { + storage.plus(); + try { + JOptionPane.showMessageDialog(null,"","",JOptionPane.INFORMATION_MESSAGE, getIcon("2.jpg")); + } catch (IOException e) { + e.printStackTrace(); + } + }); + + setDefaultCloseOperation(EXIT_ON_CLOSE); + } + + private JButton createButton(FileStorage storage) throws IOException { + ImageIcon babyIcon = getIcon("1.png"); + + JButton button = new JButton(); + + button.setIcon(babyIcon); + return button; + } + + private ImageIcon getIcon(String name) throws IOException { + URL file = this.getClass().getClassLoader().getResource(name); + return new ImageIcon(ImageIO.read(file)); + } + + +} diff --git a/stirring-clicker/src/main/resources/1.png b/stirring-clicker/src/main/resources/1.png new file mode 100644 index 0000000000000000000000000000000000000000..1ff5944d67256918b8cc12d43bda1aadf8040a82 GIT binary patch literal 4434 zcmV-Y5v}ftP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D5a&rmK~#8N?Op3{ z6xADEDinp54uZXb?LesHH*a19?dbIB(}&8+%Hky@C2>iT;>E?qF&u~R-jRxmio-QE zHNlr(ep%u7uOSO8TC_+~6s7y-n{STdGzN;hq4M%_emA^t-#!(`Yp{!V-+fnsM2GbW zw47YGG!88c=a>+0&-`RS*h z9@AgC2BM{+gu3bx0 zVVbC-qN2Dg%XG?~Ios0G(jc7qIEFxrc%7>o_4V~Zm>JW=fIMYDGFGfuK`k&{6AYp@ z<_8xpT##0;UOm8&5U1*6k3BZdF6R=pwY38bJ<-&NW(W>C^vWx*NyM@L6qBNv!t1$`3z(dQ#S2#3QmLb)JRlXg;cDnZT7 z&7RoL0|yQ;yA_OwRz|FHhKa`f`SYofV!Q|ok!Z*yGJ)03)P9rlnK+-1!udc2xf4M~pNJzR&YFklJ;dm0E zP2xAuKBB$oKM1XW>5RYj+H3w2miG2`I@tsx;>(sTa};kQ@}e&g-|y_~%uBdx0}LEQ zKkvBX4qurk4YDj#iW8lTojiHcwzMEw6UigAA^zNR&-uBZRhn>wgeM> zU3%6NSgo%}^f+GsVdl)4qH+mSkh50t*$f=fruC*OCJT=t3E?pTbtg}v_pc^%~+nGZy6mO z)z37k{qMv>{PD*hLKAR3>Fck*4swlJf5|q=%ggmvAaLo@rGPIP@!fadiAlV8@nT?P zWJEtpjgLP1NN-&R*O~REr-1)@wxpy)Kf4Sv2aI=Q3XNkzK%%#N2B^PK+c|UQ#O)O9 z@Htbob#n;lqjba0 z>aEN8_uqf@R&Ma+mtTH7Ha7OGej51o*Iyk~cM*h$G5-1IpToXn1SG9XZw97Kn>MUB z)1tnpkIY$?SmWwf7fBp5ggl$5hD2l1x1WC8Gq}blxE@438dpOT!ok@bG zhB2AqdWeFYlqn?Rh6a$WF-|C;rXrc+hF?S^PHZn7X5zb^Cv*rRq`JB~X8PhfBrqh_ z-`{UL!E0)25{{bH*Lm~i`L8AhyDK6Q4BSx}yQrv0lsHODOFdtPY-wo`Ma2X$iEM6e zcBFlkm6f8fsYhP^$|D|l-~svg@#8`|AZefIOBxF`~xY!HOCi8#&;-W6z#F zs&ShSv_G>pz#&Nk0|PV@QKKr6xU2`Kn8{H|ci(+?h?{RMw!;fz3|&@Mc4X(yotiDb z_10SjBS4lDIDh_p6`B*JwByu@B2`sY!VZ(bu)Lcn^jl~HgeS8$^!D~Dm^{-!tOy(( z=LiP}2UUERlR3^zWTMW_&gimb%f#}bE&#@;Ny0V5jN8#R5k4D3G{S*u0)miI!oW>q zV2%Ne&P#-ntPK#N^x8m4pFMlF?MdwD=twYwJFn9+fcGW9B*kaWoN4*K6+yD8m4Swa z29?@ne2;_(BnETFkkv}MBt2O&eFwiabjvNbgkE^z1;=LAEsQ%;5ca0mhNqu?S_apW zJ5H5WxX1tf_up3_WyUz26ho{(0OpMwux`5}u=V>33k#L~`}d2BpEz+s3I>C8qCqPs zn;=d;G?dIp{!DDus#Rosrpc6`Eh)7d{_4o`<;!y#;z9srqZXq->9qlqYzqBgzr){u z|NXdu!ls*Ibqk6il8Hd_Z6!QkeDMXf$#m@u6j{1-siR~HK|(00$YvsFUL0CN#(EA2 zp)j`)tn}KjefxHk4J$1zr7EQaY`IXiB#J;oTxFayX3R*-3_5n0mGD`Pr;h~2flJJ8xSz-V<*Cy%5AAfW; zNeLj#wKOA)yxQB_HGkm*Fgw~)1za@WEC(meu z=?78*jwe}iV|dLIN$Tn8F?F0oUxT2)(FE<@y<3K<4OdiDr1U=tf+dK-jz_?(Afqk3 z<{4lPIWO9E7;bOexH0wb!#0W!!>q)&Zrz&Fv|z%8y(7`)wY0Q&8WJWuZ`g0!wwnP5 zY;wxz4dJg=IsqNtv13ON<59-O#yp*TBbu6;jKK}HJvAUT?6|ED>!FwSSqwO~dGlsZ znXq{AVhNI&=nI(;J$dq^t%*W3qF{nkX#j(VP-SJMEC1yddPuMJK{vZ;A^ZbWG_5m% zL}@l0Y9FJ6zx=9qSigQfO^}$tyY9Nnw#fqnP1?%51xGFX2IU2qCo#8~0wB}fD{I!Q zNoxiU9y}=3*VhNPZQGWUr9I=ym7d+(1|&{lHje0vCNr-LFu*vT^br%JTrdKv?Rog- z1bU%Q>kB5vLfcq{J08{iVR)het+6eDg@2bLY+p|As{Pgx<77fpLc%+Bu6L>>wVe@LUEYD6f6V77T^| z`s*(-hFC0?cJERF!Z)!o3*l?E-pmGSXJ_Z({{DW)5f!p$y%h*x5MuMzWCWr#`ND+@ z`kD4{nDm;8tXgErFiq(_dj@RUw24k!3n7_^!Dc&>YGl90WHE+}-8c5$DKM`h0$i|Q z!GEfr3M*Hx6tOPL02eP_%*G^$5E2qWhB(68Z@I7pu_Jen(Lhd;P};jf0PMb#*zG!rtCqQ$n?S_ik5NH!^)wK`}wl zu%U*AhR}fn2eQ#v0sX;QDl={zqbz^mXd-GP7~}YQ&;U_3BK7t4*_+S%@4w%)#sH~| z;Wb+m$s`X46^>p=z}&fW$yiq~<`QY>$l}F|!;m_4*REX|lgoSWy;tT|7VbI4#D+1! zQ6zpw$+x1&mMvRcnI>fQVhl)99VMoLb?ep%Uy&g03qlwfeDcXB)i>UFLw@na7v+r` zH}bhdYI%8iu(q}~3KL{CAXld3`RAXPSyD$cK}RSQhI30|V1S5ghys8K=F^Kg_$b!` z&`- z5#X%MbzYbyODSY!lad4*9bp+ACO|k?Iyf9%!5A^YEM^?U;NT!1zSYf5YX~=ktiZCS zLn zQMvQZI~82OB=L|iVbUPUt{pW)XZ#k!)kwC>t`muO-g!p?!-Ywr&w_98e3>94jEsQf zxn{&<1+>@XTfqod!AjOJG6F<1b=5%Mh9j83brh~N^1TTMY_nhl9M)B%5eOQBG(%`= z#HCvJC0BupCqRb;BM^;T6^!8hbS%H1sS)dRTeog?6}Ec@L@h!+vvJmw1$@l5apxel z0+t}JtD71S!ixAAp{?uibuxetykcaBrbet$H8(eBmoIn)Bx0tto|~5W`jrIke<~|0 zV|`1E6XW&|6NsmtdWsV-I*5EA|7z+jSmGC1KZ!m8{?LEpG#2OJC+NJd2rOT|oHyUl z?+GSwqg{DOlryzaU>n{(*@hafr(hc;==Q(s@7 zs&A1L;~~KuFC@3f}t$%aP zg0K4!e7H%f`?Vu@Z}MqDGUgk$qm$OHTbFrX&jjH7`SX-+Zgd!TBR`3&cRf8llgXT> z2cP&jb?Q`;x+AK}Co?2fRT+v}nILV~3XZI#PEIqF4$QWbcX-IM9L>dFomt_%_ukW_ zf7Pm05lDY>6r>T$*6;zTZkWGv@bJSA^OjoE;0p^2wfo|t(WvKxhsn_L^0umi4E-u#oU;50M zGu+l*GBPqE;j=Q{=e^#t@&1D}I0`L13Wj}x>-**=mb~K8M;{%4%^s&6UJ^~8z9)*# zdGd##xdb;T&zd!hdr(uF61&9JF=$DY&wc9e?+7_WbG`t<3ey}iAoAAb0u{~qb=2!X)= Y0pTRxRwVqi+W-In07*qoM6N<$g05LsLjV8( literal 0 HcmV?d00001 diff --git a/stirring-clicker/src/main/resources/2.jpg b/stirring-clicker/src/main/resources/2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6220fba24faf9895b96e999a0063de7fef8a8fd2 GIT binary patch literal 3603 zcmbW3c|6qnzsJ90#=bKOgDIwH(IgHTWk}Y_R>>|Q%N)s)A;V0BYzd|9W<-&YFt*6f zgmZLc8OAnaJ*1zpG=`Zmzj4p+{_f-6f9~&h-=ELxug~&$KR?Us^Wly1Xn>53g|!6$ z0)c?*`~vXC0W$zBAh1{Y0pV9c5kWx+L{LmvSV%-dOhQ6jOk7-2N=`;nN>)l-TxOq) ztUOdfK|w-#zv4cqq8wBKx;F_3%pU_06crQ{g-VJ`LjUdHwF0stfG^++2B`xAvLLW5 zh}Q|g0RSY(&vq~2e*{Q?pQDhlh^Ux2ze9}-AOHe`1t8$PtoglT`RxEiR#5Jsj;WBm zgSW7HDD>35tk)tM=PKJ290wQ(-5X)?qGJ2@D=H};I;^R6U7Q7#ns2x@1}o1U{H9(ok(m{^xcH}iAl*1Qc|;X9zV%_`t13Og2Fd%i;CZs zysxSz)zsG2H+*XE=~Vnr z@LyQ}B>P`nvV1N92m}lf-s1uZVEF>eLIe-$2+5f`2z!UhtDm|j0zH@Yy0T4FL)Vd^ za3gF$Y#&08erRnE?LW!>HL&>q7ui3-{+o*mNPt27%>&B?3ngE-+WRdGm$^MB2A>wVPPVi3c-ZJpa0dC{G^F--k7(w_q)Z?}E%K|4bZ7twkw>^T zXV>*L4KIhLmB3*|EN@14Aj$6jrz-^)8keqSAMtS_Q~yS23+{v;m103?NxoZltYcf` z@BCHZ7&3T3yO)&pLCP7-3HDH3&(jqvy3+w+bo1lH*>@>J+~u9iOeFXD=IU4o?N%oJ z89k-RJR&XT!_+&$;wC@XQ*1;g*Ol46SgJy>X6wauw@Bjs%B8f7x zwa%+lE$}*<*}AuR%U&WsHP&*NxAWMh!<+sF6l2xFIUj_HfTx>okA~7D=*v-Oq@vko z#fmWd*U{aPW>7B0NhXj7$ZVb-zJpP0zS3aUK6$QX!lwht&>>qm#+6lksTc>hZFw>5 zc)<9DcC>QS{$EF?WY!LK{2p8ECRrKsW&cQPgt+?YEZx?y+b81*XpeyRca1CjXC&3h zR|Xf|O2tRz7N(+hSF%1OS*Uf&;FTNxx=lC?4-kZMYkwlg@TPxobZMo|70v2Vk9A0= zx)!w`gW{u`y*Q+-|M+2UsN{rD2@a_$U2oYHt0}<1#d$zrO9EUa>Df+QvR;l~$nhxd zXg%q3%xn3)w1qeKk=*bQ8-P(Uw%EY~zEl zi5KOj=1YI!0h0JOLv&zfhBCz1aE;jY{grr^!9ZGRtkLD>#@rdzj-ypoDkgVv4`2ba zKz!jy%XQ*IqDs@jweK$6yxmjOAQZQs7Ph1PAL32ouHA6f5xYyr zo4<$k^~It_Fr^K%wY7;Cdi45bWi1iaYJgf1;dDr5i~NT;369blKBH_ikYkE12we9t zFLsN+*nd(e^oxn@f<{59+VFNbW04umEk@Jwl_Q9<9Pc&t*>*Lx=B$?&YU;BiGKS;~ z+^7~;9S^1p`!rM%U#`N3r^RrN46n=+#WjqtX`66a_g3BGDBEJm!ETh_{a>v(82;_< zMc&^vX@ZCZkZjmEFRTjP#4rS|q)&F8M^H{RdSe)A|KW#+gN9eu<-Z+Uj9 zf_0P!5U#HgS1>b|Obey4^uF=4uA{S$aP#rDv1b}4b`_YaxIzADQXkGA-~l)AsdD`$ za%1D;T4$*j-Z_M_YVl$KXPEl}e+!v0UA;e<11e>aCZmdJAIjWpNlAYqG9XSr=233F z#sPEbzOtINH!`lZVbPMiQc?2l z*s7FOJyjv{g*bv$e6XN|Hw#bbXllmpU+9GPx2T% zuV!(4pEE)Xgl^~T#5G6xcizROpD}v-{nOcRUV*4rW!T)OI>cP(H}-#aEQ|cIK&XxwJ_|ws1$qdE1XLV+kk`7 zrZ17kN9qPvYlNt|+10o7zZuTkLGBOD+b>`B{(k8pyNmbgG zXdeSpnADrmJKzy$woAr~;fys|czW2?Nmh>hCc2L};WFZSi_JkQrFy5B;UW&nDuj{dI^kpqtiSK_-&=iIDWlISeNDoyc z;6*m2@A2JX6E4Jx98<6SR<2R2yB$>JUiCrQMMR}hrP7#xJc2kBzR&k^u4~i11aYu| z3m)I8-1Q)=(<9usXf0QxsI}?eo}{QTC{#45_{R~xHH^j3f1gfmx)#}dQ~9isO-gIS zkUv@00Y#M2Xg@W4=HTGe-PQCEHmb(KOC2>_jgR8Dj$%&XGCsHHbkq#5*0TzdQLBf$yuE~ zUcNaG1#OGcL#RH?r+nh@NjKJonTo`swK{_KsHtD9UfDpIPof)!_Qpq5{mF&BUw`an znl$TJ@(O!~?flYtxCSre@e!0iOzQEopJXs+95TZ*^DC+lk LXche5;*I?spOLmY literal 0 HcmV?d00001 diff --git a/stirring-clicker/src/main/resources/3.jpg b/stirring-clicker/src/main/resources/3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f2b5f6443e42014ce3fb1048422fcf2bc6a0e72a GIT binary patch literal 2903 zcmbW22~-p37RSGAvJ(SgQI?3rf`vXSUAsC@6?x#Em@@wG=@i6-p6Q zVu=E6Wf2h&3IW7|MP(Hbgs=z!A(B9VEF|+Lba}p>^UitieKT|J%zVq--<|vYFWe0e zfTi0!ygUF3g#!M_0pMP+8DP+8)rmALa^lo+I4l;Ysiw9>U0YLITT4?*OGj64sg5o| zS4(TD;ZlM=(ZIk!8*gN6NHo?X8W2^BpfJcBEKUQ5(;(_-=@9?t2G;4NWa%z@w!Ajly8iSd7YRWOOXj53mHBp2gZt zOZ0sYtE~(p+FiWku#SxG!2c6mn~oQk(Kr8j~&*1w%*Zc!{#mS z9-dphwtc>5?-%>N+(|jLdA# z-FrE?c|ZPC{IKLvX<7N>in=HDPk(J_eD+&gd&jHJuI|@8gG0k_M@IQ$V5cF8yC*e}Vmrs|RRfP{_~25C9b@b{=zn&|KIB zgM6=Y(aUH>tn$0{{gmh#-W&ODMwN8xeQX{ooOE!WFJ*_UC(#&C#$6c9&MdrG1B1d* zWzd2((ye+81I?WcT|D+ERF?{at{KQ)No3qsp6ciKGmXN`L@dAl(WLtDUtOZ3*-^W) zy7^g153Ai&;i4=7m8=44E)4wA!)7gI(Cj#M2g4Bt6K&__8irZQD)5itW=FvUa%aLS zaE^7UE@9_5BICx!1<8(rNtZFSJ2}~Vz}a^T6i&*X%Vrw$B9t*OuorkCt4O&S_vpVs zu22T&PsacxQ_?^56p~3*EDGnD-Z%0Vlq{TI_IRF?Tk7<0R@^W?HG2nxyp}~Pg2x4{ z2GY>+sOSJugCr9{Qc&w#Q0={>WNLk@EI^EW8Zqr<2v>4eU%ARppjg{rRux}G%01;A zjgO-4dIMQZdBWi55#{EEVDuJwISg8&G_AcWVNfq7`e00^%=@IuW2%TY&rk=q@gnA? znr9r?xeQep0d?2H+`Ow82@~aSb{v^;2P1BvdPDhZyiYRNL&rBnt9;U@rPE5%1r{Ry zFi#M6KL#(c%7^M!hu%p~8c7@sJzAbZ)^RA_vC033oBn$yuHE7@@g07PY=1Cy)o_J7 z**#4|_qt`QvC>Vi=ubR~%FD+vLrI+C_aSr*&dy+k4AY z+`!D`!D0Z8MX>7)`}KwW`T6~7a`TMi>)zH`eE)j6kw52gU1qz&Icy=miV@4;@q|98 z0V&;8H^%B(MEsC$4)l;-5PDd??Mo@!qAcOln5J)DzVVN1o-YTawPgYq`2l6i0ctX1 zt;D{bCQOd7shwVSwB7dTCCB_B45QXGacAw9!sj$6J|??s3XZsg0tMeb9?hdT+F{gY3hKJj1v1 zD$y@F2LcE8dhD{_XkKuuuu%Ss=4#84SjH`UT_QLUJKPd3`(T@-Rf`14j4T)&@NOsN zayyxL#2{&v;n3RigxtQh=!sr>B-!5pEF-7V)L~HT2A$+yp=u~CB%25EbtVz<$uaK4 z&rKRGTBT9OGp$!91U`>`eLW!v3-%emWhE^{i!A4gB`-uKyA&A|XlP5@qdpHoKzZ`f z(o%ho)=18a%vWLLO~fLtl=^|U0|1X`z=<`I)yM7)c`sdG$A0~?hfa`WDqf^UB-Yul z)jhM!_Pf}**&7RY0t*-1#-J{Yk0*$@fVI0ppy~B!E;Z3qT+KeLPwa2syOSg3Mk?^hG%hN8XMy?qm%!ELtRKIBk@jZNGbJLvwk z=^DQ2udn1boC!m}6>TRU?fmSWiD1Jtw!E~W^t7l+KQA!waILnwlX%^<_kuydmKHiU zpinPld3AC{+WVX5gJq$OgZFb&&RuIXY2nyiZ+WX*ZaG~yKgdmH7%HDL^d+@-WA=SE zm$jneriVGHZFYZlW!Y7I%O$89n=9RRC?1rbd? zsgp*TovHH9OCF6UqIWym1vuYR(|D=7$>trc2wKpG!45^HxI;w0hO4d=xk|TtooCy* zID9J2j$`$oO|ABme(d-xm^+XOgJRlc1|h~w*j(=@=-neKOf1Qx=XAUue$w;Q&gN=_ zkz@~gJ@tz@W6UHBV6d-gAr6p~h3QgFs^6RNIrEP5^UbCoS`;~^uyBm3Y0XM&?w?1r z-WruO&q8EHq0(|h_}a?)U5cPJ$|_P0)f7s&gTKn9L*3i=EAF1>=}KTQsN~|~87m_g zwZy8rOvK6+VGNJ5}(B z#ih~hxibgWSZ}v2Fj^I0`%|L2si_dhU@~qfT;i+#R24*C7Biw%c44@zXr3b$G)$X| zAz8UfT`{*M2|^gSNq!uN4XShf=)oaRw^xFm&Uf9nPJQ0kS*6aV`osqmDu93S$x zbO0aZ#RLpGIfe553P{#b6+0tCLXih1rWOIbx_Hz=M6M7-RW~w=GC%Lyfn-rZlsrr9 z!wzS^sBGPc@=b}lAoCqz%=l}o! literal 0 HcmV?d00001 diff --git a/stirring-clicker/src/test/java/ie/home/besok/stirrings/FileStorageTest.java b/stirring-clicker/src/test/java/ie/home/besok/stirrings/FileStorageTest.java new file mode 100644 index 000000000000..1eaaba6d5358 --- /dev/null +++ b/stirring-clicker/src/test/java/ie/home/besok/stirrings/FileStorageTest.java @@ -0,0 +1,25 @@ +package ie.home.besok.stirrings; + +import org.junit.Test; + +import java.io.IOException; +import java.util.List; + +import static org.junit.Assert.*; + +public class FileStorageTest { + + @Test + public void fsTest() throws IOException { + FileStorage fs = new FileStorage(); + List arrs = fs.get(); + int oldSize = arrs.size(); + fs.plus(); + fs.plus(); + fs.plus(); + fs.plus(); + arrs = fs.get(); + int newSize = arrs.size(); + assertEquals(4, newSize - oldSize); + } +} \ No newline at end of file From 564cf1239f22f7b352b8fc2da20a7c9c137a4b4c Mon Sep 17 00:00:00 2001 From: Besok Date: Sat, 2 Nov 2019 11:30:41 +0000 Subject: [PATCH 09/31] add init saga dsc --- stirring-clicker/pom.xml | 28 ------- .../ie/home/besok/stirrings/Application.java | 15 ---- .../java/ie/home/besok/stirrings/Counter.java | 14 ---- .../ie/home/besok/stirrings/FileStorage.java | 37 --------- .../java/ie/home/besok/stirrings/Gui.java | 73 ------------------ stirring-clicker/src/main/resources/1.png | Bin 4434 -> 0 bytes stirring-clicker/src/main/resources/2.jpg | Bin 3603 -> 0 bytes stirring-clicker/src/main/resources/3.jpg | Bin 2903 -> 0 bytes .../home/besok/stirrings/FileStorageTest.java | 25 ------ 9 files changed, 192 deletions(-) delete mode 100644 stirring-clicker/pom.xml delete mode 100644 stirring-clicker/src/main/java/ie/home/besok/stirrings/Application.java delete mode 100644 stirring-clicker/src/main/java/ie/home/besok/stirrings/Counter.java delete mode 100644 stirring-clicker/src/main/java/ie/home/besok/stirrings/FileStorage.java delete mode 100644 stirring-clicker/src/main/java/ie/home/besok/stirrings/Gui.java delete mode 100644 stirring-clicker/src/main/resources/1.png delete mode 100644 stirring-clicker/src/main/resources/2.jpg delete mode 100644 stirring-clicker/src/main/resources/3.jpg delete mode 100644 stirring-clicker/src/test/java/ie/home/besok/stirrings/FileStorageTest.java diff --git a/stirring-clicker/pom.xml b/stirring-clicker/pom.xml deleted file mode 100644 index b0d223016f24..000000000000 --- a/stirring-clicker/pom.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - 4.0.0 - - ie.home.besok - move-clicker - 1.0 - - 1.8 - 1.8 - - - - - org.projectlombok - lombok - 1.18.10 - - - - junit - junit - 4.12 - - - \ No newline at end of file diff --git a/stirring-clicker/src/main/java/ie/home/besok/stirrings/Application.java b/stirring-clicker/src/main/java/ie/home/besok/stirrings/Application.java deleted file mode 100644 index 0835470bc987..000000000000 --- a/stirring-clicker/src/main/java/ie/home/besok/stirrings/Application.java +++ /dev/null @@ -1,15 +0,0 @@ -package ie.home.besok.stirrings; - -import java.awt.*; -import java.io.IOException; - -public class Application { - public static void main(String[] args) throws IOException { - FileStorage storage = new FileStorage(); - - EventQueue.invokeLater(() -> { - Gui gui = new Gui(storage); - gui.setVisible(true); - }); - } -} diff --git a/stirring-clicker/src/main/java/ie/home/besok/stirrings/Counter.java b/stirring-clicker/src/main/java/ie/home/besok/stirrings/Counter.java deleted file mode 100644 index b0f93f9d76c3..000000000000 --- a/stirring-clicker/src/main/java/ie/home/besok/stirrings/Counter.java +++ /dev/null @@ -1,14 +0,0 @@ -package ie.home.besok.stirrings; - -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.util.List; -import java.util.Map; -import java.util.function.Function; -import java.util.stream.Collectors; - -public class Counter { - public Map count(List dates){ - return null; - } -} diff --git a/stirring-clicker/src/main/java/ie/home/besok/stirrings/FileStorage.java b/stirring-clicker/src/main/java/ie/home/besok/stirrings/FileStorage.java deleted file mode 100644 index c5784eb50795..000000000000 --- a/stirring-clicker/src/main/java/ie/home/besok/stirrings/FileStorage.java +++ /dev/null @@ -1,37 +0,0 @@ -package ie.home.besok.stirrings; - -import lombok.extern.slf4j.Slf4j; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.StandardOpenOption; -import java.time.LocalDateTime; -import java.util.List; - -public class FileStorage { - - private Path file; - - public FileStorage() throws IOException { - this.file = Paths.get("data.log"); - if(!Files.exists(file)){ - Files.createFile(file); - } - } - - public void plus() { - String line = LocalDateTime.now().toString()+System.lineSeparator(); - try { - Files.write(file, line.getBytes(), StandardOpenOption.APPEND); - } catch (IOException e) { - e.printStackTrace(); - } - } - - public List get() throws IOException { - return Files.readAllLines(file); - } - -} diff --git a/stirring-clicker/src/main/java/ie/home/besok/stirrings/Gui.java b/stirring-clicker/src/main/java/ie/home/besok/stirrings/Gui.java deleted file mode 100644 index 3df3e21313b5..000000000000 --- a/stirring-clicker/src/main/java/ie/home/besok/stirrings/Gui.java +++ /dev/null @@ -1,73 +0,0 @@ -package ie.home.besok.stirrings; - -import javax.imageio.ImageIO; -import javax.swing.*; -import java.awt.*; -import java.io.IOException; -import java.net.URL; - -public class Gui extends JFrame { - - private FileStorage storage; - - public Gui(FileStorage storage) { - this.storage = storage; - try { - createUI(storage); - } catch (IOException e) { - e.printStackTrace(); - } - } - - private void createUI(FileStorage storage) throws IOException { - setTitle("Stirring counter"); - setSize(300, 300); - setLocationRelativeTo(null); - - - JButton button = createButton(storage); - JButton graphick = new JButton(); - graphick.setIcon(getIcon("3.jpg")); - - - Container pane = getContentPane(); - GroupLayout gl = new GroupLayout(pane); - pane.setLayout(gl); - - gl.setAutoCreateContainerGaps(true); - - gl.setHorizontalGroup( - gl.createSequentialGroup().addComponent(button).addComponent(graphick) - ); - - gl.setVerticalGroup(gl.createSequentialGroup().addComponent(button).addComponent(graphick)); - - - button.addActionListener((event) -> { - storage.plus(); - try { - JOptionPane.showMessageDialog(null,"","",JOptionPane.INFORMATION_MESSAGE, getIcon("2.jpg")); - } catch (IOException e) { - e.printStackTrace(); - } - }); - - setDefaultCloseOperation(EXIT_ON_CLOSE); - } - - private JButton createButton(FileStorage storage) throws IOException { - ImageIcon babyIcon = getIcon("1.png"); - - JButton button = new JButton(); - - button.setIcon(babyIcon); - return button; - } - - private ImageIcon getIcon(String name) throws IOException { - URL file = this.getClass().getClassLoader().getResource(name); - return new ImageIcon(ImageIO.read(file)); - } - - -} diff --git a/stirring-clicker/src/main/resources/1.png b/stirring-clicker/src/main/resources/1.png deleted file mode 100644 index 1ff5944d67256918b8cc12d43bda1aadf8040a82..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4434 zcmV-Y5v}ftP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D5a&rmK~#8N?Op3{ z6xADEDinp54uZXb?LesHH*a19?dbIB(}&8+%Hky@C2>iT;>E?qF&u~R-jRxmio-QE zHNlr(ep%u7uOSO8TC_+~6s7y-n{STdGzN;hq4M%_emA^t-#!(`Yp{!V-+fnsM2GbW zw47YGG!88c=a>+0&-`RS*h z9@AgC2BM{+gu3bx0 zVVbC-qN2Dg%XG?~Ios0G(jc7qIEFxrc%7>o_4V~Zm>JW=fIMYDGFGfuK`k&{6AYp@ z<_8xpT##0;UOm8&5U1*6k3BZdF6R=pwY38bJ<-&NW(W>C^vWx*NyM@L6qBNv!t1$`3z(dQ#S2#3QmLb)JRlXg;cDnZT7 z&7RoL0|yQ;yA_OwRz|FHhKa`f`SYofV!Q|ok!Z*yGJ)03)P9rlnK+-1!udc2xf4M~pNJzR&YFklJ;dm0E zP2xAuKBB$oKM1XW>5RYj+H3w2miG2`I@tsx;>(sTa};kQ@}e&g-|y_~%uBdx0}LEQ zKkvBX4qurk4YDj#iW8lTojiHcwzMEw6UigAA^zNR&-uBZRhn>wgeM> zU3%6NSgo%}^f+GsVdl)4qH+mSkh50t*$f=fruC*OCJT=t3E?pTbtg}v_pc^%~+nGZy6mO z)z37k{qMv>{PD*hLKAR3>Fck*4swlJf5|q=%ggmvAaLo@rGPIP@!fadiAlV8@nT?P zWJEtpjgLP1NN-&R*O~REr-1)@wxpy)Kf4Sv2aI=Q3XNkzK%%#N2B^PK+c|UQ#O)O9 z@Htbob#n;lqjba0 z>aEN8_uqf@R&Ma+mtTH7Ha7OGej51o*Iyk~cM*h$G5-1IpToXn1SG9XZw97Kn>MUB z)1tnpkIY$?SmWwf7fBp5ggl$5hD2l1x1WC8Gq}blxE@438dpOT!ok@bG zhB2AqdWeFYlqn?Rh6a$WF-|C;rXrc+hF?S^PHZn7X5zb^Cv*rRq`JB~X8PhfBrqh_ z-`{UL!E0)25{{bH*Lm~i`L8AhyDK6Q4BSx}yQrv0lsHODOFdtPY-wo`Ma2X$iEM6e zcBFlkm6f8fsYhP^$|D|l-~svg@#8`|AZefIOBxF`~xY!HOCi8#&;-W6z#F zs&ShSv_G>pz#&Nk0|PV@QKKr6xU2`Kn8{H|ci(+?h?{RMw!;fz3|&@Mc4X(yotiDb z_10SjBS4lDIDh_p6`B*JwByu@B2`sY!VZ(bu)Lcn^jl~HgeS8$^!D~Dm^{-!tOy(( z=LiP}2UUERlR3^zWTMW_&gimb%f#}bE&#@;Ny0V5jN8#R5k4D3G{S*u0)miI!oW>q zV2%Ne&P#-ntPK#N^x8m4pFMlF?MdwD=twYwJFn9+fcGW9B*kaWoN4*K6+yD8m4Swa z29?@ne2;_(BnETFkkv}MBt2O&eFwiabjvNbgkE^z1;=LAEsQ%;5ca0mhNqu?S_apW zJ5H5WxX1tf_up3_WyUz26ho{(0OpMwux`5}u=V>33k#L~`}d2BpEz+s3I>C8qCqPs zn;=d;G?dIp{!DDus#Rosrpc6`Eh)7d{_4o`<;!y#;z9srqZXq->9qlqYzqBgzr){u z|NXdu!ls*Ibqk6il8Hd_Z6!QkeDMXf$#m@u6j{1-siR~HK|(00$YvsFUL0CN#(EA2 zp)j`)tn}KjefxHk4J$1zr7EQaY`IXiB#J;oTxFayX3R*-3_5n0mGD`Pr;h~2flJJ8xSz-V<*Cy%5AAfW; zNeLj#wKOA)yxQB_HGkm*Fgw~)1za@WEC(meu z=?78*jwe}iV|dLIN$Tn8F?F0oUxT2)(FE<@y<3K<4OdiDr1U=tf+dK-jz_?(Afqk3 z<{4lPIWO9E7;bOexH0wb!#0W!!>q)&Zrz&Fv|z%8y(7`)wY0Q&8WJWuZ`g0!wwnP5 zY;wxz4dJg=IsqNtv13ON<59-O#yp*TBbu6;jKK}HJvAUT?6|ED>!FwSSqwO~dGlsZ znXq{AVhNI&=nI(;J$dq^t%*W3qF{nkX#j(VP-SJMEC1yddPuMJK{vZ;A^ZbWG_5m% zL}@l0Y9FJ6zx=9qSigQfO^}$tyY9Nnw#fqnP1?%51xGFX2IU2qCo#8~0wB}fD{I!Q zNoxiU9y}=3*VhNPZQGWUr9I=ym7d+(1|&{lHje0vCNr-LFu*vT^br%JTrdKv?Rog- z1bU%Q>kB5vLfcq{J08{iVR)het+6eDg@2bLY+p|As{Pgx<77fpLc%+Bu6L>>wVe@LUEYD6f6V77T^| z`s*(-hFC0?cJERF!Z)!o3*l?E-pmGSXJ_Z({{DW)5f!p$y%h*x5MuMzWCWr#`ND+@ z`kD4{nDm;8tXgErFiq(_dj@RUw24k!3n7_^!Dc&>YGl90WHE+}-8c5$DKM`h0$i|Q z!GEfr3M*Hx6tOPL02eP_%*G^$5E2qWhB(68Z@I7pu_Jen(Lhd;P};jf0PMb#*zG!rtCqQ$n?S_ik5NH!^)wK`}wl zu%U*AhR}fn2eQ#v0sX;QDl={zqbz^mXd-GP7~}YQ&;U_3BK7t4*_+S%@4w%)#sH~| z;Wb+m$s`X46^>p=z}&fW$yiq~<`QY>$l}F|!;m_4*REX|lgoSWy;tT|7VbI4#D+1! zQ6zpw$+x1&mMvRcnI>fQVhl)99VMoLb?ep%Uy&g03qlwfeDcXB)i>UFLw@na7v+r` zH}bhdYI%8iu(q}~3KL{CAXld3`RAXPSyD$cK}RSQhI30|V1S5ghys8K=F^Kg_$b!` z&`- z5#X%MbzYbyODSY!lad4*9bp+ACO|k?Iyf9%!5A^YEM^?U;NT!1zSYf5YX~=ktiZCS zLn zQMvQZI~82OB=L|iVbUPUt{pW)XZ#k!)kwC>t`muO-g!p?!-Ywr&w_98e3>94jEsQf zxn{&<1+>@XTfqod!AjOJG6F<1b=5%Mh9j83brh~N^1TTMY_nhl9M)B%5eOQBG(%`= z#HCvJC0BupCqRb;BM^;T6^!8hbS%H1sS)dRTeog?6}Ec@L@h!+vvJmw1$@l5apxel z0+t}JtD71S!ixAAp{?uibuxetykcaBrbet$H8(eBmoIn)Bx0tto|~5W`jrIke<~|0 zV|`1E6XW&|6NsmtdWsV-I*5EA|7z+jSmGC1KZ!m8{?LEpG#2OJC+NJd2rOT|oHyUl z?+GSwqg{DOlryzaU>n{(*@hafr(hc;==Q(s@7 zs&A1L;~~KuFC@3f}t$%aP zg0K4!e7H%f`?Vu@Z}MqDGUgk$qm$OHTbFrX&jjH7`SX-+Zgd!TBR`3&cRf8llgXT> z2cP&jb?Q`;x+AK}Co?2fRT+v}nILV~3XZI#PEIqF4$QWbcX-IM9L>dFomt_%_ukW_ zf7Pm05lDY>6r>T$*6;zTZkWGv@bJSA^OjoE;0p^2wfo|t(WvKxhsn_L^0umi4E-u#oU;50M zGu+l*GBPqE;j=Q{=e^#t@&1D}I0`L13Wj}x>-**=mb~K8M;{%4%^s&6UJ^~8z9)*# zdGd##xdb;T&zd!hdr(uF61&9JF=$DY&wc9e?+7_WbG`t<3ey}iAoAAb0u{~qb=2!X)= Y0pTRxRwVqi+W-In07*qoM6N<$g05LsLjV8( diff --git a/stirring-clicker/src/main/resources/2.jpg b/stirring-clicker/src/main/resources/2.jpg deleted file mode 100644 index 6220fba24faf9895b96e999a0063de7fef8a8fd2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3603 zcmbW3c|6qnzsJ90#=bKOgDIwH(IgHTWk}Y_R>>|Q%N)s)A;V0BYzd|9W<-&YFt*6f zgmZLc8OAnaJ*1zpG=`Zmzj4p+{_f-6f9~&h-=ELxug~&$KR?Us^Wly1Xn>53g|!6$ z0)c?*`~vXC0W$zBAh1{Y0pV9c5kWx+L{LmvSV%-dOhQ6jOk7-2N=`;nN>)l-TxOq) ztUOdfK|w-#zv4cqq8wBKx;F_3%pU_06crQ{g-VJ`LjUdHwF0stfG^++2B`xAvLLW5 zh}Q|g0RSY(&vq~2e*{Q?pQDhlh^Ux2ze9}-AOHe`1t8$PtoglT`RxEiR#5Jsj;WBm zgSW7HDD>35tk)tM=PKJ290wQ(-5X)?qGJ2@D=H};I;^R6U7Q7#ns2x@1}o1U{H9(ok(m{^xcH}iAl*1Qc|;X9zV%_`t13Og2Fd%i;CZs zysxSz)zsG2H+*XE=~Vnr z@LyQ}B>P`nvV1N92m}lf-s1uZVEF>eLIe-$2+5f`2z!UhtDm|j0zH@Yy0T4FL)Vd^ za3gF$Y#&08erRnE?LW!>HL&>q7ui3-{+o*mNPt27%>&B?3ngE-+WRdGm$^MB2A>wVPPVi3c-ZJpa0dC{G^F--k7(w_q)Z?}E%K|4bZ7twkw>^T zXV>*L4KIhLmB3*|EN@14Aj$6jrz-^)8keqSAMtS_Q~yS23+{v;m103?NxoZltYcf` z@BCHZ7&3T3yO)&pLCP7-3HDH3&(jqvy3+w+bo1lH*>@>J+~u9iOeFXD=IU4o?N%oJ z89k-RJR&XT!_+&$;wC@XQ*1;g*Ol46SgJy>X6wauw@Bjs%B8f7x zwa%+lE$}*<*}AuR%U&WsHP&*NxAWMh!<+sF6l2xFIUj_HfTx>okA~7D=*v-Oq@vko z#fmWd*U{aPW>7B0NhXj7$ZVb-zJpP0zS3aUK6$QX!lwht&>>qm#+6lksTc>hZFw>5 zc)<9DcC>QS{$EF?WY!LK{2p8ECRrKsW&cQPgt+?YEZx?y+b81*XpeyRca1CjXC&3h zR|Xf|O2tRz7N(+hSF%1OS*Uf&;FTNxx=lC?4-kZMYkwlg@TPxobZMo|70v2Vk9A0= zx)!w`gW{u`y*Q+-|M+2UsN{rD2@a_$U2oYHt0}<1#d$zrO9EUa>Df+QvR;l~$nhxd zXg%q3%xn3)w1qeKk=*bQ8-P(Uw%EY~zEl zi5KOj=1YI!0h0JOLv&zfhBCz1aE;jY{grr^!9ZGRtkLD>#@rdzj-ypoDkgVv4`2ba zKz!jy%XQ*IqDs@jweK$6yxmjOAQZQs7Ph1PAL32ouHA6f5xYyr zo4<$k^~It_Fr^K%wY7;Cdi45bWi1iaYJgf1;dDr5i~NT;369blKBH_ikYkE12we9t zFLsN+*nd(e^oxn@f<{59+VFNbW04umEk@Jwl_Q9<9Pc&t*>*Lx=B$?&YU;BiGKS;~ z+^7~;9S^1p`!rM%U#`N3r^RrN46n=+#WjqtX`66a_g3BGDBEJm!ETh_{a>v(82;_< zMc&^vX@ZCZkZjmEFRTjP#4rS|q)&F8M^H{RdSe)A|KW#+gN9eu<-Z+Uj9 zf_0P!5U#HgS1>b|Obey4^uF=4uA{S$aP#rDv1b}4b`_YaxIzADQXkGA-~l)AsdD`$ za%1D;T4$*j-Z_M_YVl$KXPEl}e+!v0UA;e<11e>aCZmdJAIjWpNlAYqG9XSr=233F z#sPEbzOtINH!`lZVbPMiQc?2l z*s7FOJyjv{g*bv$e6XN|Hw#bbXllmpU+9GPx2T% zuV!(4pEE)Xgl^~T#5G6xcizROpD}v-{nOcRUV*4rW!T)OI>cP(H}-#aEQ|cIK&XxwJ_|ws1$qdE1XLV+kk`7 zrZ17kN9qPvYlNt|+10o7zZuTkLGBOD+b>`B{(k8pyNmbgG zXdeSpnADrmJKzy$woAr~;fys|czW2?Nmh>hCc2L};WFZSi_JkQrFy5B;UW&nDuj{dI^kpqtiSK_-&=iIDWlISeNDoyc z;6*m2@A2JX6E4Jx98<6SR<2R2yB$>JUiCrQMMR}hrP7#xJc2kBzR&k^u4~i11aYu| z3m)I8-1Q)=(<9usXf0QxsI}?eo}{QTC{#45_{R~xHH^j3f1gfmx)#}dQ~9isO-gIS zkUv@00Y#M2Xg@W4=HTGe-PQCEHmb(KOC2>_jgR8Dj$%&XGCsHHbkq#5*0TzdQLBf$yuE~ zUcNaG1#OGcL#RH?r+nh@NjKJonTo`swK{_KsHtD9UfDpIPof)!_Qpq5{mF&BUw`an znl$TJ@(O!~?flYtxCSre@e!0iOzQEopJXs+95TZ*^DC+lk LXche5;*I?spOLmY diff --git a/stirring-clicker/src/main/resources/3.jpg b/stirring-clicker/src/main/resources/3.jpg deleted file mode 100644 index f2b5f6443e42014ce3fb1048422fcf2bc6a0e72a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2903 zcmbW22~-p37RSGAvJ(SgQI?3rf`vXSUAsC@6?x#Em@@wG=@i6-p6Q zVu=E6Wf2h&3IW7|MP(Hbgs=z!A(B9VEF|+Lba}p>^UitieKT|J%zVq--<|vYFWe0e zfTi0!ygUF3g#!M_0pMP+8DP+8)rmALa^lo+I4l;Ysiw9>U0YLITT4?*OGj64sg5o| zS4(TD;ZlM=(ZIk!8*gN6NHo?X8W2^BpfJcBEKUQ5(;(_-=@9?t2G;4NWa%z@w!Ajly8iSd7YRWOOXj53mHBp2gZt zOZ0sYtE~(p+FiWku#SxG!2c6mn~oQk(Kr8j~&*1w%*Zc!{#mS z9-dphwtc>5?-%>N+(|jLdA# z-FrE?c|ZPC{IKLvX<7N>in=HDPk(J_eD+&gd&jHJuI|@8gG0k_M@IQ$V5cF8yC*e}Vmrs|RRfP{_~25C9b@b{=zn&|KIB zgM6=Y(aUH>tn$0{{gmh#-W&ODMwN8xeQX{ooOE!WFJ*_UC(#&C#$6c9&MdrG1B1d* zWzd2((ye+81I?WcT|D+ERF?{at{KQ)No3qsp6ciKGmXN`L@dAl(WLtDUtOZ3*-^W) zy7^g153Ai&;i4=7m8=44E)4wA!)7gI(Cj#M2g4Bt6K&__8irZQD)5itW=FvUa%aLS zaE^7UE@9_5BICx!1<8(rNtZFSJ2}~Vz}a^T6i&*X%Vrw$B9t*OuorkCt4O&S_vpVs zu22T&PsacxQ_?^56p~3*EDGnD-Z%0Vlq{TI_IRF?Tk7<0R@^W?HG2nxyp}~Pg2x4{ z2GY>+sOSJugCr9{Qc&w#Q0={>WNLk@EI^EW8Zqr<2v>4eU%ARppjg{rRux}G%01;A zjgO-4dIMQZdBWi55#{EEVDuJwISg8&G_AcWVNfq7`e00^%=@IuW2%TY&rk=q@gnA? znr9r?xeQep0d?2H+`Ow82@~aSb{v^;2P1BvdPDhZyiYRNL&rBnt9;U@rPE5%1r{Ry zFi#M6KL#(c%7^M!hu%p~8c7@sJzAbZ)^RA_vC033oBn$yuHE7@@g07PY=1Cy)o_J7 z**#4|_qt`QvC>Vi=ubR~%FD+vLrI+C_aSr*&dy+k4AY z+`!D`!D0Z8MX>7)`}KwW`T6~7a`TMi>)zH`eE)j6kw52gU1qz&Icy=miV@4;@q|98 z0V&;8H^%B(MEsC$4)l;-5PDd??Mo@!qAcOln5J)DzVVN1o-YTawPgYq`2l6i0ctX1 zt;D{bCQOd7shwVSwB7dTCCB_B45QXGacAw9!sj$6J|??s3XZsg0tMeb9?hdT+F{gY3hKJj1v1 zD$y@F2LcE8dhD{_XkKuuuu%Ss=4#84SjH`UT_QLUJKPd3`(T@-Rf`14j4T)&@NOsN zayyxL#2{&v;n3RigxtQh=!sr>B-!5pEF-7V)L~HT2A$+yp=u~CB%25EbtVz<$uaK4 z&rKRGTBT9OGp$!91U`>`eLW!v3-%emWhE^{i!A4gB`-uKyA&A|XlP5@qdpHoKzZ`f z(o%ho)=18a%vWLLO~fLtl=^|U0|1X`z=<`I)yM7)c`sdG$A0~?hfa`WDqf^UB-Yul z)jhM!_Pf}**&7RY0t*-1#-J{Yk0*$@fVI0ppy~B!E;Z3qT+KeLPwa2syOSg3Mk?^hG%hN8XMy?qm%!ELtRKIBk@jZNGbJLvwk z=^DQ2udn1boC!m}6>TRU?fmSWiD1Jtw!E~W^t7l+KQA!waILnwlX%^<_kuydmKHiU zpinPld3AC{+WVX5gJq$OgZFb&&RuIXY2nyiZ+WX*ZaG~yKgdmH7%HDL^d+@-WA=SE zm$jneriVGHZFYZlW!Y7I%O$89n=9RRC?1rbd? zsgp*TovHH9OCF6UqIWym1vuYR(|D=7$>trc2wKpG!45^HxI;w0hO4d=xk|TtooCy* zID9J2j$`$oO|ABme(d-xm^+XOgJRlc1|h~w*j(=@=-neKOf1Qx=XAUue$w;Q&gN=_ zkz@~gJ@tz@W6UHBV6d-gAr6p~h3QgFs^6RNIrEP5^UbCoS`;~^uyBm3Y0XM&?w?1r z-WruO&q8EHq0(|h_}a?)U5cPJ$|_P0)f7s&gTKn9L*3i=EAF1>=}KTQsN~|~87m_g zwZy8rOvK6+VGNJ5}(B z#ih~hxibgWSZ}v2Fj^I0`%|L2si_dhU@~qfT;i+#R24*C7Biw%c44@zXr3b$G)$X| zAz8UfT`{*M2|^gSNq!uN4XShf=)oaRw^xFm&Uf9nPJQ0kS*6aV`osqmDu93S$x zbO0aZ#RLpGIfe553P{#b6+0tCLXih1rWOIbx_Hz=M6M7-RW~w=GC%Lyfn-rZlsrr9 z!wzS^sBGPc@=b}lAoCqz%=l}o! diff --git a/stirring-clicker/src/test/java/ie/home/besok/stirrings/FileStorageTest.java b/stirring-clicker/src/test/java/ie/home/besok/stirrings/FileStorageTest.java deleted file mode 100644 index 1eaaba6d5358..000000000000 --- a/stirring-clicker/src/test/java/ie/home/besok/stirrings/FileStorageTest.java +++ /dev/null @@ -1,25 +0,0 @@ -package ie.home.besok.stirrings; - -import org.junit.Test; - -import java.io.IOException; -import java.util.List; - -import static org.junit.Assert.*; - -public class FileStorageTest { - - @Test - public void fsTest() throws IOException { - FileStorage fs = new FileStorage(); - List arrs = fs.get(); - int oldSize = arrs.size(); - fs.plus(); - fs.plus(); - fs.plus(); - fs.plus(); - arrs = fs.get(); - int newSize = arrs.size(); - assertEquals(4, newSize - oldSize); - } -} \ No newline at end of file From 7ac47b291d5cd9d68fd291acdce2ade5297c0701 Mon Sep 17 00:00:00 2001 From: Besok Date: Sat, 2 Nov 2019 11:39:02 +0000 Subject: [PATCH 10/31] add changes to dsc --- saga/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/saga/README.md b/saga/README.md index 12e4c8482396..276f12ee1f37 100644 --- a/saga/README.md +++ b/saga/README.md @@ -16,7 +16,8 @@ This pattern has a similar goal with two-phase commit (XA transaction) ## Intent This pattern is used in distributed services to perform a group of operations atomically. -This is an analog of transaction in a database but in terms of microservices architecture this is performed in a distributed environment +This is an analog of transaction in a database but in terms of microservices architecture this is executed +in a distributed environment ## Explanation A saga is a sequence of local transactions in a certain context. If one transaction fails for some reason, From c4c37d77e9cdc9514b48193aad14426c878e530e Mon Sep 17 00:00:00 2001 From: Besok Date: Sat, 2 Nov 2019 14:45:05 +0000 Subject: [PATCH 11/31] add --- .../iluwatar/saga/orchestration/Chapter.java | 35 ++++++++ .../saga/orchestration/ChapterResult.java | 22 +++++ .../saga/orchestration/FlyBookingService.java | 8 ++ .../orchestration/HotelBookingService.java | 8 ++ .../saga/orchestration/OrderService.java | 8 ++ .../com/iluwatar/saga/orchestration/Saga.java | 80 +++++++++++++++++++ .../saga/orchestration/SagaApplication.java | 50 ++++++++++++ .../saga/orchestration/SagaException.java | 29 +++++++ .../saga/orchestration/SagaOrchestrator.java | 30 +++++++ .../iluwatar/saga/orchestration/Service.java | 33 ++++++++ .../ServiceDiscoveryService.java | 46 +++++++++++ .../iluwatar/saga/orchestration/Utility.java | 16 ++++ .../orchestration/WithdrawMoneyService.java | 16 ++++ 13 files changed, 381 insertions(+) create mode 100644 saga/src/main/java/com/iluwatar/saga/orchestration/Chapter.java create mode 100644 saga/src/main/java/com/iluwatar/saga/orchestration/ChapterResult.java create mode 100644 saga/src/main/java/com/iluwatar/saga/orchestration/FlyBookingService.java create mode 100644 saga/src/main/java/com/iluwatar/saga/orchestration/HotelBookingService.java create mode 100644 saga/src/main/java/com/iluwatar/saga/orchestration/OrderService.java create mode 100644 saga/src/main/java/com/iluwatar/saga/orchestration/Saga.java create mode 100644 saga/src/main/java/com/iluwatar/saga/orchestration/SagaApplication.java create mode 100644 saga/src/main/java/com/iluwatar/saga/orchestration/SagaException.java create mode 100644 saga/src/main/java/com/iluwatar/saga/orchestration/SagaOrchestrator.java create mode 100644 saga/src/main/java/com/iluwatar/saga/orchestration/Service.java create mode 100644 saga/src/main/java/com/iluwatar/saga/orchestration/ServiceDiscoveryService.java create mode 100644 saga/src/main/java/com/iluwatar/saga/orchestration/Utility.java create mode 100644 saga/src/main/java/com/iluwatar/saga/orchestration/WithdrawMoneyService.java diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/Chapter.java b/saga/src/main/java/com/iluwatar/saga/orchestration/Chapter.java new file mode 100644 index 000000000000..9b1e1feac666 --- /dev/null +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/Chapter.java @@ -0,0 +1,35 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.saga.orchestration; + +/** + * Chapter including into Saga + */ +public interface Chapter { + + String getName(); + + ChapterResult process(K value); + ChapterResult rollback(K value); + +} diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/ChapterResult.java b/saga/src/main/java/com/iluwatar/saga/orchestration/ChapterResult.java new file mode 100644 index 000000000000..ee5ae8ba1ac2 --- /dev/null +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/ChapterResult.java @@ -0,0 +1,22 @@ +package com.iluwatar.saga.orchestration; + +public class ChapterResult { + K value; + State state; + + public ChapterResult(K value, State state) { + this.value = value; + this.state = state; + } + + public static ChapterResult success(K val) { + return new ChapterResult<>(val, State.SUCCESS); + } + public static ChapterResult failure(K val) { + return new ChapterResult<>(val, State.FAILURE); + } + + public enum State { + SUCCESS, FAILURE + } +} diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/FlyBookingService.java b/saga/src/main/java/com/iluwatar/saga/orchestration/FlyBookingService.java new file mode 100644 index 000000000000..7a78b5f17839 --- /dev/null +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/FlyBookingService.java @@ -0,0 +1,8 @@ +package com.iluwatar.saga.orchestration; + +public class FlyBookingService extends Service { + @Override + public String getName() { + return "booking a Fly"; + } +} diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/HotelBookingService.java b/saga/src/main/java/com/iluwatar/saga/orchestration/HotelBookingService.java new file mode 100644 index 000000000000..8f294cd40911 --- /dev/null +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/HotelBookingService.java @@ -0,0 +1,8 @@ +package com.iluwatar.saga.orchestration; + +public class HotelBookingService extends Service { + @Override + public String getName() { + return "booking a Hotel"; + } +} diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/OrderService.java b/saga/src/main/java/com/iluwatar/saga/orchestration/OrderService.java new file mode 100644 index 000000000000..d5d79ac413b6 --- /dev/null +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/OrderService.java @@ -0,0 +1,8 @@ +package com.iluwatar.saga.orchestration; + +public class OrderService extends Service { + @Override + public String getName() { + return "init an order"; + } +} diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/Saga.java b/saga/src/main/java/com/iluwatar/saga/orchestration/Saga.java new file mode 100644 index 000000000000..b74d689591ff --- /dev/null +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/Saga.java @@ -0,0 +1,80 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.saga.orchestration; + +import java.util.ArrayList; +import java.util.List; + +public class Saga { + + private List chapters; + private Result result; + + public Saga() { + this.chapters = new ArrayList<>(); + this.result = Result.INPROCESS; + } + + public void setResult(Result result) { + this.result = result; + } + + public boolean isSuccess(){ + return result == Result.FINISHED; + } + + public boolean isFinished(){ + return result != Result.INPROCESS; + } + + public Saga chapter(String name, int timeoutInSec) { + this.chapters.add(new Chapter(name, timeoutInSec)); + return this; + } + + public Chapter get(int idx) { + if (chapters.size() < idx || idx < 0) { + throw new SagaException("idx shoud be less then ch size or more then 0"); + } + return chapters.get(idx); + } + + + + public static Saga create() { + return new Saga(); + } + + public enum Result{ + FINISHED,CANCELED, INPROCESS; + } + private static class Chapter { + String name; + int timeoutInSec; + + public Chapter(String name, int timeoutInSec) { + this.name = name; + this.timeoutInSec = timeoutInSec; + } + } +} diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/SagaApplication.java b/saga/src/main/java/com/iluwatar/saga/orchestration/SagaApplication.java new file mode 100644 index 000000000000..154f97bab6e6 --- /dev/null +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/SagaApplication.java @@ -0,0 +1,50 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.saga.orchestration; + + +public class SagaApplication { + public static void main(String[] args) { + + } + + + + private Saga createSaga() { + return Saga.create() + .chapter("init an order",10) + .chapter("booking a Fly",10) + .chapter("booking a Hotel",10) + .chapter("withdrawing Money",10); + } + + private static ServiceDiscoveryService sd() { + return + new ServiceDiscoveryService() + .discover(new OrderService()) + .discover(new FlyBookingService()) + .discover(new HotelBookingService()) + .discover(new WithdrawMoneyService()); + } +} diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/SagaException.java b/saga/src/main/java/com/iluwatar/saga/orchestration/SagaException.java new file mode 100644 index 000000000000..0055bb85ee6b --- /dev/null +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/SagaException.java @@ -0,0 +1,29 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.saga.orchestration; + +public class SagaException extends RuntimeException { + public SagaException(String message) { + super(message); + } +} diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/SagaOrchestrator.java b/saga/src/main/java/com/iluwatar/saga/orchestration/SagaOrchestrator.java new file mode 100644 index 000000000000..edc94bb2236f --- /dev/null +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/SagaOrchestrator.java @@ -0,0 +1,30 @@ +package com.iluwatar.saga.orchestration; + +import java.util.Objects; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; + +public class SagaOrchestrator { + + private ExecutorService executor; + private AtomicBoolean isNormalFlow; + private AtomicBoolean isFinished; + private AtomicInteger currentState; + private final Saga saga; + + public SagaOrchestrator(Saga saga) { + this.saga = saga; + this.isNormalFlow = new AtomicBoolean(true); + this.isFinished = new AtomicBoolean(false); + this.currentState = new AtomicInteger(0); + this.executor = Executors.newFixedThreadPool(20); + } + + public Saga.Result kickOff(K value) { + + } + + +} diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/Service.java b/saga/src/main/java/com/iluwatar/saga/orchestration/Service.java new file mode 100644 index 000000000000..31a2ab70241e --- /dev/null +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/Service.java @@ -0,0 +1,33 @@ +package com.iluwatar.saga.orchestration; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static com.iluwatar.saga.orchestration.Utility.sleepInSec; + +public abstract class Service implements Chapter { + private static final Logger logger = LoggerFactory.getLogger(Service.class); + + @Override + public abstract String getName(); + + + @Override + public ChapterResult process(K value) { + logger.info("The chapter about {} is starting", getName()); + logger.info("storing or calculating a data {} to db", value); + sleepInSec(1); + logger.info("the data {} has been stored or calculated successfully", value); + return ChapterResult.success(value); + } + + @Override + public ChapterResult rollback(K value) { + logger.info("Something is going wrong hence The chapter about {} is starting the rollback procedure", getName()); + sleepInSec(1); + logger.info("the data {} has been rollbacked successfully", value); + return ChapterResult.success(value); + } + + +} diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/ServiceDiscoveryService.java b/saga/src/main/java/com/iluwatar/saga/orchestration/ServiceDiscoveryService.java new file mode 100644 index 000000000000..522f3f94401f --- /dev/null +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/ServiceDiscoveryService.java @@ -0,0 +1,46 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.saga.orchestration; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +public class ServiceDiscoveryService { + private Map> services; + + public Optional> find(String service) { + return Optional.ofNullable(services.getOrDefault(service, null)); + } + + public ServiceDiscoveryService discover(Chapter chapterService) { + services.put(chapterService.getName(), chapterService); + return this; + } + + public ServiceDiscoveryService() { + this.services = new HashMap<>(); + } + + +} diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/Utility.java b/saga/src/main/java/com/iluwatar/saga/orchestration/Utility.java new file mode 100644 index 000000000000..bf5e902c0ce3 --- /dev/null +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/Utility.java @@ -0,0 +1,16 @@ +package com.iluwatar.saga.orchestration; + +public class Utility { + private Utility() { + } + + public static void sleepInSec(int sec){ + try { + Thread.sleep(sec*1000); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + + +} diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/WithdrawMoneyService.java b/saga/src/main/java/com/iluwatar/saga/orchestration/WithdrawMoneyService.java new file mode 100644 index 000000000000..25c7710dcce8 --- /dev/null +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/WithdrawMoneyService.java @@ -0,0 +1,16 @@ +package com.iluwatar.saga.orchestration; + +public class WithdrawMoneyService extends Service { + @Override + public String getName() { + return "withdrawing Money"; + } + + @Override + public ChapterResult process(String value) { + if(value.equals("no-money")){ + return ChapterResult.failure(value); + } + return super.process(value); + } +} From 3a4677c56d19a1b5d1044cf32b535f729141ec99 Mon Sep 17 00:00:00 2001 From: Besok Date: Sat, 2 Nov 2019 20:52:59 +0000 Subject: [PATCH 12/31] add orchestrator --- .../iluwatar/saga/orchestration/Chapter.java | 17 ++- .../saga/orchestration/ChapterResult.java | 41 ++++- .../saga/orchestration/FlyBookingService.java | 25 ++++ .../orchestration/HotelBookingService.java | 42 ++++++ .../saga/orchestration/OrderService.java | 25 ++++ .../com/iluwatar/saga/orchestration/Saga.java | 40 +++-- .../saga/orchestration/SagaApplication.java | 42 +++++- .../saga/orchestration/SagaException.java | 29 ---- .../saga/orchestration/SagaOrchestrator.java | 141 ++++++++++++++++-- .../iluwatar/saga/orchestration/Service.java | 42 ++++-- .../ServiceDiscoveryService.java | 5 +- .../iluwatar/saga/orchestration/Utility.java | 16 -- .../orchestration/WithdrawMoneyService.java | 30 +++- .../orchestration/SagaApplicationTest.java | 13 ++ .../SagaOrchestratorInternallyTest.java | 117 +++++++++++++++ .../orchestration/SagaOrchestratorTest.java | 37 +++++ 16 files changed, 554 insertions(+), 108 deletions(-) delete mode 100644 saga/src/main/java/com/iluwatar/saga/orchestration/SagaException.java delete mode 100644 saga/src/main/java/com/iluwatar/saga/orchestration/Utility.java create mode 100644 saga/src/test/java/com/iluwatar/saga/orchestration/SagaApplicationTest.java create mode 100644 saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorInternallyTest.java create mode 100644 saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorTest.java diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/Chapter.java b/saga/src/main/java/com/iluwatar/saga/orchestration/Chapter.java index 9b1e1feac666..961a8893733a 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/Chapter.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/Chapter.java @@ -23,13 +23,28 @@ package com.iluwatar.saga.orchestration; /** - * Chapter including into Saga + * Chapter is an interface representing a contract for an external service. + * @param is type for passing params */ public interface Chapter { + /** + * @return service name. + */ String getName(); + /** + * The operation executed in general case. + * @param value incoming value + * @return result {@link ChapterResult} + */ ChapterResult process(K value); + + /** + * The operation executed in rollback case. + * @param value incoming value + * @return result {@link ChapterResult} + */ ChapterResult rollback(K value); } diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/ChapterResult.java b/saga/src/main/java/com/iluwatar/saga/orchestration/ChapterResult.java index ee5ae8ba1ac2..eae95b3391f8 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/ChapterResult.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/ChapterResult.java @@ -1,17 +1,52 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package com.iluwatar.saga.orchestration; +/** + * Executing result for chapter + * @param incoming value + */ public class ChapterResult { - K value; - State state; + private K value; + private State state; - public ChapterResult(K value, State state) { + public K getValue() { + return value; + } + + ChapterResult(K value, State state) { this.value = value; this.state = state; } + public boolean isSuccess(){ + return state == State.SUCCESS; + } + public static ChapterResult success(K val) { return new ChapterResult<>(val, State.SUCCESS); } + public static ChapterResult failure(K val) { return new ChapterResult<>(val, State.FAILURE); } diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/FlyBookingService.java b/saga/src/main/java/com/iluwatar/saga/orchestration/FlyBookingService.java index 7a78b5f17839..6cb8479c07b2 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/FlyBookingService.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/FlyBookingService.java @@ -1,5 +1,30 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package com.iluwatar.saga.orchestration; +/** + * Class representing a service to book a fly + */ public class FlyBookingService extends Service { @Override public String getName() { diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/HotelBookingService.java b/saga/src/main/java/com/iluwatar/saga/orchestration/HotelBookingService.java index 8f294cd40911..e21046328918 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/HotelBookingService.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/HotelBookingService.java @@ -1,8 +1,50 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package com.iluwatar.saga.orchestration; +/** + * Class representing a service to book a hotel + */ public class HotelBookingService extends Service { @Override public String getName() { return "booking a Hotel"; } + + + @Override + public ChapterResult rollback(String value) { + if(value.equals("crashed_order")){ + logger.info("The Rollback for a chapter '{}' has been started. " + + "The data {} has been failed.The saga has been crashed.", + getName(), value); + + return ChapterResult.failure(value); + } + + logger.info("The Rollback for a chapter '{}' has been started. The data {} has been rollbacked successfully", + getName(), value); + + return super.rollback(value); + } } diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/OrderService.java b/saga/src/main/java/com/iluwatar/saga/orchestration/OrderService.java index d5d79ac413b6..6edd94ace40a 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/OrderService.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/OrderService.java @@ -1,5 +1,30 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package com.iluwatar.saga.orchestration; +/** + * Class representing a service to init a new order. + */ public class OrderService extends Service { @Override public String getName() { diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/Saga.java b/saga/src/main/java/com/iluwatar/saga/orchestration/Saga.java index b74d689591ff..c21435f20db6 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/Saga.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/Saga.java @@ -25,56 +25,50 @@ import java.util.ArrayList; import java.util.List; +/** + * Saga representation. + * Saca consists of chapters. + * Every Chapter is executed a certain service. + */ public class Saga { private List chapters; - private Result result; public Saga() { this.chapters = new ArrayList<>(); - this.result = Result.INPROCESS; } - public void setResult(Result result) { - this.result = result; - } - public boolean isSuccess(){ - return result == Result.FINISHED; - } - - public boolean isFinished(){ - return result != Result.INPROCESS; - } - public Saga chapter(String name, int timeoutInSec) { - this.chapters.add(new Chapter(name, timeoutInSec)); + public Saga chapter(String name) { + this.chapters.add(new Chapter(name)); return this; } + public Chapter get(int idx) { - if (chapters.size() < idx || idx < 0) { - throw new SagaException("idx shoud be less then ch size or more then 0"); - } return chapters.get(idx); } + public boolean isPresent(int idx) { + return idx >= 0 && idx < chapters.size(); + } public static Saga create() { return new Saga(); } - public enum Result{ - FINISHED,CANCELED, INPROCESS; + public enum Result { + FINISHED, ROLLBACK, CRASHED } - private static class Chapter { + + public static class Chapter { String name; - int timeoutInSec; - public Chapter(String name, int timeoutInSec) { + public Chapter(String name) { this.name = name; - this.timeoutInSec = timeoutInSec; } + } } diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/SagaApplication.java b/saga/src/main/java/com/iluwatar/saga/orchestration/SagaApplication.java index 154f97bab6e6..71db1a7bfb85 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/SagaApplication.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/SagaApplication.java @@ -24,22 +24,48 @@ package com.iluwatar.saga.orchestration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This pattern is used in distributed services to perform a group of operations atomically. + * This is an analog of transaction in a database but in terms of microservices architecture this is executed + * in a distributed environment + * + * A saga is a sequence of local transactions in a certain context. If one transaction fails for some reason, + * the saga executes compensating transactions(rollbacks) to undo the impact of the preceding transactions. + * + * In this approach, there is an orchestrator @see {@link SagaOrchestrator} that manages all the transactions and directs + * the participant services to execute local transactions based on events. + * + * @see Saga + * @see SagaOrchestrator + * @see Service + */ public class SagaApplication { + private static final Logger logger = LoggerFactory.getLogger(SagaApplication.class); + public static void main(String[] args) { + SagaOrchestrator sagaOrchestrator = new SagaOrchestrator(newSaga(), serviceDiscovery()); - } + Saga.Result goodOrder = sagaOrchestrator.execute("god_order"); + Saga.Result badOrder = sagaOrchestrator.execute("bad_order"); + Saga.Result crashedOrder = sagaOrchestrator.execute("crashed_order"); + logger.info("orders: goodOrder is {}, badOrder is {},crashedOrder is {}",goodOrder,badOrder,crashedOrder); + } - private Saga createSaga() { - return Saga.create() - .chapter("init an order",10) - .chapter("booking a Fly",10) - .chapter("booking a Hotel",10) - .chapter("withdrawing Money",10); + private static Saga newSaga() { + return Saga + .create() + .chapter("init an order") + .chapter("booking a Fly") + .chapter("booking a Hotel") + .chapter("withdrawing Money"); } - private static ServiceDiscoveryService sd() { + private static ServiceDiscoveryService serviceDiscovery() { return new ServiceDiscoveryService() .discover(new OrderService()) diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/SagaException.java b/saga/src/main/java/com/iluwatar/saga/orchestration/SagaException.java deleted file mode 100644 index 0055bb85ee6b..000000000000 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/SagaException.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * The MIT License - * Copyright © 2014-2019 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.saga.orchestration; - -public class SagaException extends RuntimeException { - public SagaException(String message) { - super(message); - } -} diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/SagaOrchestrator.java b/saga/src/main/java/com/iluwatar/saga/orchestration/SagaOrchestrator.java index edc94bb2236f..34ad29b267d1 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/SagaOrchestrator.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/SagaOrchestrator.java @@ -1,30 +1,139 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package com.iluwatar.saga.orchestration; -import java.util.Objects; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -public class SagaOrchestrator { +import java.util.Optional; + +import static com.iluwatar.saga.orchestration.Saga.Result.*; - private ExecutorService executor; - private AtomicBoolean isNormalFlow; - private AtomicBoolean isFinished; - private AtomicInteger currentState; +/** + * The orchestrator that manages all the transactions and directs + * the participant services to execute local transactions based on events. + */ +public class SagaOrchestrator { + private static final Logger logger = LoggerFactory.getLogger(SagaOrchestrator.class); private final Saga saga; + private final ServiceDiscoveryService sd; + private final CurrentState state; - public SagaOrchestrator(Saga saga) { + + public SagaOrchestrator(Saga saga, ServiceDiscoveryService sd) { this.saga = saga; - this.isNormalFlow = new AtomicBoolean(true); - this.isFinished = new AtomicBoolean(false); - this.currentState = new AtomicInteger(0); - this.executor = Executors.newFixedThreadPool(20); + this.sd = sd; + this.state = new CurrentState(); } - public Saga.Result kickOff(K value) { + /** + * + * @param value incoming value + * @param type for incoming value + * @return result @see {@link Saga.Result} + */ + @SuppressWarnings("unchecked") + public Saga.Result execute(K value) { + state.cleanUp(); + logger.info(" The new saga is about to start"); + Saga.Result result = FINISHED; + K tempVal = value; + + while (true) { + int next = state.current(); + Saga.Chapter ch = saga.get(next); + Optional srvOpt = sd.find(ch.name); + + if (!srvOpt.isPresent()) { + state.directionToBack(); + state.back(); + continue; + } + + Chapter srv = srvOpt.get(); + + if (state.isForward()) { + ChapterResult processRes = srv.process(tempVal); + if (processRes.isSuccess()) { + next = state.forward(); + tempVal = (K) processRes.getValue(); + } else { + state.directionToBack(); + } + } else { + ChapterResult rlRes = srv.rollback(tempVal); + if (rlRes.isSuccess()) { + next = state.back(); + tempVal = (K) rlRes.getValue(); + } else { + result = CRASHED; + next = state.back(); + } + } + + + if (!saga.isPresent(next)) { + return state.isForward() ? FINISHED : result == CRASHED ? CRASHED : ROLLBACK; + } + } } + private static class CurrentState { + int currentNumber; + boolean isForward; + + void cleanUp() { + currentNumber = 0; + isForward = true; + } + + CurrentState() { + this.currentNumber = 0; + this.isForward = true; + } + + + boolean isForward() { + return isForward; + } + + void directionToBack() { + isForward = false; + } + + int forward() { + return ++currentNumber; + } + + int back() { + return --currentNumber; + } + + int current() { + return currentNumber; + } + } + } diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/Service.java b/saga/src/main/java/com/iluwatar/saga/orchestration/Service.java index 31a2ab70241e..20b34f55aa95 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/Service.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/Service.java @@ -1,12 +1,37 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package com.iluwatar.saga.orchestration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import static com.iluwatar.saga.orchestration.Utility.sleepInSec; - +/** + * Common abstraction class representing services + * implementing a general contract @see {@link Chapter} + * @param type of incoming param + */ public abstract class Service implements Chapter { - private static final Logger logger = LoggerFactory.getLogger(Service.class); + protected static final Logger logger = LoggerFactory.getLogger(Service.class); @Override public abstract String getName(); @@ -14,18 +39,15 @@ public abstract class Service implements Chapter { @Override public ChapterResult process(K value) { - logger.info("The chapter about {} is starting", getName()); - logger.info("storing or calculating a data {} to db", value); - sleepInSec(1); - logger.info("the data {} has been stored or calculated successfully", value); + logger.info("The chapter '{}' has been started. The data {} has been stored or calculated successfully", + getName(),value); return ChapterResult.success(value); } @Override public ChapterResult rollback(K value) { - logger.info("Something is going wrong hence The chapter about {} is starting the rollback procedure", getName()); - sleepInSec(1); - logger.info("the data {} has been rollbacked successfully", value); + logger.info("The Rollback for a chapter '{}' has been started. The data {} has been rollbacked successfully", + getName(),value); return ChapterResult.success(value); } diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/ServiceDiscoveryService.java b/saga/src/main/java/com/iluwatar/saga/orchestration/ServiceDiscoveryService.java index 522f3f94401f..652740051b5e 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/ServiceDiscoveryService.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/ServiceDiscoveryService.java @@ -26,10 +26,13 @@ import java.util.Map; import java.util.Optional; +/** + * The class representing a service discovery pattern. + */ public class ServiceDiscoveryService { private Map> services; - public Optional> find(String service) { + public Optional find(String service) { return Optional.ofNullable(services.getOrDefault(service, null)); } diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/Utility.java b/saga/src/main/java/com/iluwatar/saga/orchestration/Utility.java deleted file mode 100644 index bf5e902c0ce3..000000000000 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/Utility.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.iluwatar.saga.orchestration; - -public class Utility { - private Utility() { - } - - public static void sleepInSec(int sec){ - try { - Thread.sleep(sec*1000); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - - -} diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/WithdrawMoneyService.java b/saga/src/main/java/com/iluwatar/saga/orchestration/WithdrawMoneyService.java index 25c7710dcce8..dad15cec3864 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/WithdrawMoneyService.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/WithdrawMoneyService.java @@ -1,5 +1,30 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package com.iluwatar.saga.orchestration; +/** + * Class representing a service to withdraw a money + */ public class WithdrawMoneyService extends Service { @Override public String getName() { @@ -8,7 +33,10 @@ public String getName() { @Override public ChapterResult process(String value) { - if(value.equals("no-money")){ + if (value.equals("bad_order") || value.equals("crashed_order")) { + logger.info("The chapter '{}' has been started. But the exception has been raised." + + "The rollback is about to start", + getName(), value); return ChapterResult.failure(value); } return super.process(value); diff --git a/saga/src/test/java/com/iluwatar/saga/orchestration/SagaApplicationTest.java b/saga/src/test/java/com/iluwatar/saga/orchestration/SagaApplicationTest.java new file mode 100644 index 000000000000..6950158aaef1 --- /dev/null +++ b/saga/src/test/java/com/iluwatar/saga/orchestration/SagaApplicationTest.java @@ -0,0 +1,13 @@ +package com.iluwatar.saga.orchestration; + +import org.junit.Test; + +import static org.junit.Assert.*; + +public class SagaApplicationTest { + + @Test + public void mainTest() { + SagaApplication.main(new String[]{}); + } +} \ No newline at end of file diff --git a/saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorInternallyTest.java b/saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorInternallyTest.java new file mode 100644 index 000000000000..b8377cebf525 --- /dev/null +++ b/saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorInternallyTest.java @@ -0,0 +1,117 @@ +package com.iluwatar.saga.orchestration; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +public class SagaOrchestratorInternallyTest { + + private List records = new ArrayList<>(); + + @Test + public void execute() { + SagaOrchestrator sagaOrchestrator = new SagaOrchestrator(newSaga(), serviceDiscovery()); + Saga.Result result = sagaOrchestrator.execute(1); + Assert.assertEquals(result, Saga.Result.ROLLBACK); + Assert.assertArrayEquals( + records.toArray(new String[]{}), + new String[]{"+1","+2","+3","+4","-4","-3","-2","-1"}); + } + + private static Saga newSaga() { + return Saga + .create() + .chapter("1") + .chapter("2") + .chapter("3") + .chapter("4"); + } + + private ServiceDiscoveryService serviceDiscovery() { + return + new ServiceDiscoveryService() + .discover(new Service1()) + .discover(new Service2()) + .discover(new Service3()) + .discover(new Service4()); + } + + class Service1 extends Service { + + @Override + public String getName() { + return "1"; + } + + @Override + public ChapterResult process(Integer value) { + records.add("+1"); + return ChapterResult.success(value); + } + + @Override + public ChapterResult rollback(Integer value) { + records.add("-1"); + return ChapterResult.success(value); + } + } + + class Service2 extends Service { + + @Override + public String getName() { + return "2"; + } + @Override + public ChapterResult process(Integer value) { + records.add("+2"); + return ChapterResult.success(value); + } + + @Override + public ChapterResult rollback(Integer value) { + records.add("-2"); + return ChapterResult.success(value); + } + } + + class Service3 extends Service { + + @Override + public String getName() { + return "3"; + } + @Override + public ChapterResult process(Integer value) { + records.add("+3"); + return ChapterResult.success(value); + } + + @Override + public ChapterResult rollback(Integer value) { + records.add("-3"); + return ChapterResult.success(value); + } + } + + class Service4 extends Service { + + @Override + public String getName() { + return "4"; + } + @Override + public ChapterResult process(Integer value) { + records.add("+4"); + return ChapterResult.failure(value); + } + + @Override + public ChapterResult rollback(Integer value) { + records.add("-4"); + return ChapterResult.success(value); + } + } +} \ No newline at end of file diff --git a/saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorTest.java b/saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorTest.java new file mode 100644 index 000000000000..8558b1f5a170 --- /dev/null +++ b/saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorTest.java @@ -0,0 +1,37 @@ +package com.iluwatar.saga.orchestration; + +import org.junit.Assert; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class SagaOrchestratorTest { + + @Test + public void execute() { + SagaOrchestrator sagaOrchestrator = new SagaOrchestrator(newSaga(), serviceDiscovery()); + Saga.Result badOrder = sagaOrchestrator.execute("bad_order"); + Saga.Result crashedOrder = sagaOrchestrator.execute("crashed_order"); + + Assert.assertEquals(badOrder, Saga.Result.ROLLBACK); + Assert.assertEquals(crashedOrder, Saga.Result.CRASHED); + } + + private static Saga newSaga() { + return Saga + .create() + .chapter("init an order") + .chapter("booking a Fly") + .chapter("booking a Hotel") + .chapter("withdrawing Money"); + } + + private static ServiceDiscoveryService serviceDiscovery() { + return + new ServiceDiscoveryService() + .discover(new OrderService()) + .discover(new FlyBookingService()) + .discover(new HotelBookingService()) + .discover(new WithdrawMoneyService()); + } +} \ No newline at end of file From 1b32e23493d1383033603162741c42264c8c965d Mon Sep 17 00:00:00 2001 From: Besok Date: Sun, 3 Nov 2019 12:03:33 +0000 Subject: [PATCH 13/31] add ch --- .../ServiceDiscoveryService.java | 4 +- .../iluwatar/saga/choreography/Chapter.java | 59 +++++++++++++++++++ .../choreography/ChoreographyService.java | 33 +++++++++++ .../iluwatar/saga/choreography/RichSaga.java | 4 ++ .../saga/orchestration/FlyBookingService.java | 2 +- .../orchestration/HotelBookingService.java | 2 +- ...Service.java => OrchestrationService.java} | 4 +- .../saga/orchestration/OrderService.java | 2 +- .../com/iluwatar/saga/orchestration/Saga.java | 3 + .../saga/orchestration/SagaApplication.java | 3 +- .../saga/orchestration/SagaOrchestrator.java | 1 + .../orchestration/WithdrawMoneyService.java | 2 +- .../SagaOrchestratorInternallyTest.java | 9 +-- .../orchestration/SagaOrchestratorTest.java | 3 +- 14 files changed, 117 insertions(+), 14 deletions(-) rename saga/src/main/java/com/iluwatar/saga/{orchestration => }/ServiceDiscoveryService.java (95%) create mode 100644 saga/src/main/java/com/iluwatar/saga/choreography/Chapter.java create mode 100644 saga/src/main/java/com/iluwatar/saga/choreography/ChoreographyService.java create mode 100644 saga/src/main/java/com/iluwatar/saga/choreography/RichSaga.java rename saga/src/main/java/com/iluwatar/saga/orchestration/{Service.java => OrchestrationService.java} (95%) diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/ServiceDiscoveryService.java b/saga/src/main/java/com/iluwatar/saga/ServiceDiscoveryService.java similarity index 95% rename from saga/src/main/java/com/iluwatar/saga/orchestration/ServiceDiscoveryService.java rename to saga/src/main/java/com/iluwatar/saga/ServiceDiscoveryService.java index 652740051b5e..f9d91b53e3de 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/ServiceDiscoveryService.java +++ b/saga/src/main/java/com/iluwatar/saga/ServiceDiscoveryService.java @@ -20,7 +20,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package com.iluwatar.saga.orchestration; +package com.iluwatar.saga; + +import com.iluwatar.saga.orchestration.Chapter; import java.util.HashMap; import java.util.Map; diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/Chapter.java b/saga/src/main/java/com/iluwatar/saga/choreography/Chapter.java new file mode 100644 index 000000000000..a76e2c4dfaa2 --- /dev/null +++ b/saga/src/main/java/com/iluwatar/saga/choreography/Chapter.java @@ -0,0 +1,59 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.saga.choreography; + +import com.iluwatar.saga.orchestration.ChapterResult; + +/** + * Chapter is an interface representing a contract for an external service. + * @param is type for passing params + */ +public interface Chapter { + + /** + * @return service name. + */ + String getName(); + + /** + * every chapter is responsible for a part of saga. + * @param value incoming value + * @return saga result @see {@link RichSaga} + */ + RichSaga execute(K value); + + /** + * The operation executed in general case. + * @param value incoming value + * @return result {@link ChapterResult} + */ + ChapterResult process(K value); + + /** + * The operation executed in rollback case. + * @param value incoming value + * @return result {@link ChapterResult} + */ + ChapterResult rollback(K value); + +} diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/ChoreographyService.java b/saga/src/main/java/com/iluwatar/saga/choreography/ChoreographyService.java new file mode 100644 index 000000000000..e88a131b2189 --- /dev/null +++ b/saga/src/main/java/com/iluwatar/saga/choreography/ChoreographyService.java @@ -0,0 +1,33 @@ +package com.iluwatar.saga.choreography; + +import com.iluwatar.saga.ServiceDiscoveryService; +import com.iluwatar.saga.orchestration.Chapter; +import com.iluwatar.saga.orchestration.ChapterResult; +import com.iluwatar.saga.orchestration.OrchestrationService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public abstract class ChoreographyService implements Chapter { + + protected static final Logger logger = LoggerFactory.getLogger(OrchestrationService.class); + + private final ServiceDiscoveryService service; + protected ChoreographyService(ServiceDiscoveryService service) { + this.service = service; + } + + @Override + public ChapterResult process(K value) { + logger.info("The chapter '{}' has been started. The data {} has been stored or calculated successfully", + getName(),value); + return ChapterResult.success(value); + } + + @Override + public ChapterResult rollback(K value) { + logger.info("The Rollback for a chapter '{}' has been started. The data {} has been rollbacked successfully", + getName(),value); + return ChapterResult.success(value); + } + +} diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/RichSaga.java b/saga/src/main/java/com/iluwatar/saga/choreography/RichSaga.java new file mode 100644 index 000000000000..27e099fc793f --- /dev/null +++ b/saga/src/main/java/com/iluwatar/saga/choreography/RichSaga.java @@ -0,0 +1,4 @@ +package com.iluwatar.saga.choreography; + +public class RichSaga { +} diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/FlyBookingService.java b/saga/src/main/java/com/iluwatar/saga/orchestration/FlyBookingService.java index 6cb8479c07b2..34f3f4f18eb2 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/FlyBookingService.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/FlyBookingService.java @@ -25,7 +25,7 @@ /** * Class representing a service to book a fly */ -public class FlyBookingService extends Service { +public class FlyBookingService extends OrchestrationService { @Override public String getName() { return "booking a Fly"; diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/HotelBookingService.java b/saga/src/main/java/com/iluwatar/saga/orchestration/HotelBookingService.java index e21046328918..a4da64d36ed3 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/HotelBookingService.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/HotelBookingService.java @@ -25,7 +25,7 @@ /** * Class representing a service to book a hotel */ -public class HotelBookingService extends Service { +public class HotelBookingService extends OrchestrationService { @Override public String getName() { return "booking a Hotel"; diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/Service.java b/saga/src/main/java/com/iluwatar/saga/orchestration/OrchestrationService.java similarity index 95% rename from saga/src/main/java/com/iluwatar/saga/orchestration/Service.java rename to saga/src/main/java/com/iluwatar/saga/orchestration/OrchestrationService.java index 20b34f55aa95..7f0e9a03cfe3 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/Service.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/OrchestrationService.java @@ -30,8 +30,8 @@ * implementing a general contract @see {@link Chapter} * @param type of incoming param */ -public abstract class Service implements Chapter { - protected static final Logger logger = LoggerFactory.getLogger(Service.class); +public abstract class OrchestrationService implements Chapter { + protected static final Logger logger = LoggerFactory.getLogger(OrchestrationService.class); @Override public abstract String getName(); diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/OrderService.java b/saga/src/main/java/com/iluwatar/saga/orchestration/OrderService.java index 6edd94ace40a..8fb7b118d739 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/OrderService.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/OrderService.java @@ -25,7 +25,7 @@ /** * Class representing a service to init a new order. */ -public class OrderService extends Service { +public class OrderService extends OrchestrationService { @Override public String getName() { return "init an order"; diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/Saga.java b/saga/src/main/java/com/iluwatar/saga/orchestration/Saga.java index c21435f20db6..9f8312d9f231 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/Saga.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/Saga.java @@ -70,5 +70,8 @@ public Chapter(String name) { this.name = name; } + public String getName() { + return name; + } } } diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/SagaApplication.java b/saga/src/main/java/com/iluwatar/saga/orchestration/SagaApplication.java index 71db1a7bfb85..b69d040136bd 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/SagaApplication.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/SagaApplication.java @@ -24,6 +24,7 @@ package com.iluwatar.saga.orchestration; +import com.iluwatar.saga.ServiceDiscoveryService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -40,7 +41,7 @@ * * @see Saga * @see SagaOrchestrator - * @see Service + * @see OrchestrationService */ public class SagaApplication { private static final Logger logger = LoggerFactory.getLogger(SagaApplication.class); diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/SagaOrchestrator.java b/saga/src/main/java/com/iluwatar/saga/orchestration/SagaOrchestrator.java index 34ad29b267d1..588a860aa16d 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/SagaOrchestrator.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/SagaOrchestrator.java @@ -22,6 +22,7 @@ */ package com.iluwatar.saga.orchestration; +import com.iluwatar.saga.ServiceDiscoveryService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/WithdrawMoneyService.java b/saga/src/main/java/com/iluwatar/saga/orchestration/WithdrawMoneyService.java index dad15cec3864..d53f106cb1b4 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/WithdrawMoneyService.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/WithdrawMoneyService.java @@ -25,7 +25,7 @@ /** * Class representing a service to withdraw a money */ -public class WithdrawMoneyService extends Service { +public class WithdrawMoneyService extends OrchestrationService { @Override public String getName() { return "withdrawing Money"; diff --git a/saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorInternallyTest.java b/saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorInternallyTest.java index b8377cebf525..a40a3ebec2a1 100644 --- a/saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorInternallyTest.java +++ b/saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorInternallyTest.java @@ -1,5 +1,6 @@ package com.iluwatar.saga.orchestration; +import com.iluwatar.saga.ServiceDiscoveryService; import org.junit.Assert; import org.junit.Test; @@ -38,7 +39,7 @@ private ServiceDiscoveryService serviceDiscovery() { .discover(new Service4()); } - class Service1 extends Service { + class Service1 extends OrchestrationService { @Override public String getName() { @@ -58,7 +59,7 @@ public ChapterResult rollback(Integer value) { } } - class Service2 extends Service { + class Service2 extends OrchestrationService { @Override public String getName() { @@ -77,7 +78,7 @@ public ChapterResult rollback(Integer value) { } } - class Service3 extends Service { + class Service3 extends OrchestrationService { @Override public String getName() { @@ -96,7 +97,7 @@ public ChapterResult rollback(Integer value) { } } - class Service4 extends Service { + class Service4 extends OrchestrationService { @Override public String getName() { diff --git a/saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorTest.java b/saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorTest.java index 8558b1f5a170..cd659601eacc 100644 --- a/saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorTest.java +++ b/saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorTest.java @@ -1,10 +1,9 @@ package com.iluwatar.saga.orchestration; +import com.iluwatar.saga.ServiceDiscoveryService; import org.junit.Assert; import org.junit.Test; -import static org.junit.Assert.*; - public class SagaOrchestratorTest { @Test From ffeee2f1a48f1fd041f3a327814a31efe99c9434 Mon Sep 17 00:00:00 2001 From: Besok Date: Sun, 3 Nov 2019 12:35:01 +0000 Subject: [PATCH 14/31] separate pkgs --- .../iluwatar/saga/choreography/Chapter.java | 59 ------------------- .../choreography/ChoreographyService.java | 33 ----------- .../iluwatar/saga/choreography/RichSaga.java | 4 -- .../saga/orchestration/FlyBookingService.java | 2 +- .../orchestration/HotelBookingService.java | 2 +- .../saga/orchestration/OrderService.java | 2 +- .../saga/orchestration/SagaApplication.java | 2 +- ...OrchestrationService.java => Service.java} | 4 +- .../orchestration/WithdrawMoneyService.java | 2 +- .../SagaOrchestratorInternallyTest.java | 8 +-- 10 files changed, 11 insertions(+), 107 deletions(-) delete mode 100644 saga/src/main/java/com/iluwatar/saga/choreography/Chapter.java delete mode 100644 saga/src/main/java/com/iluwatar/saga/choreography/ChoreographyService.java delete mode 100644 saga/src/main/java/com/iluwatar/saga/choreography/RichSaga.java rename saga/src/main/java/com/iluwatar/saga/orchestration/{OrchestrationService.java => Service.java} (95%) diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/Chapter.java b/saga/src/main/java/com/iluwatar/saga/choreography/Chapter.java deleted file mode 100644 index a76e2c4dfaa2..000000000000 --- a/saga/src/main/java/com/iluwatar/saga/choreography/Chapter.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * The MIT License - * Copyright © 2014-2019 Ilkka Seppälä - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.iluwatar.saga.choreography; - -import com.iluwatar.saga.orchestration.ChapterResult; - -/** - * Chapter is an interface representing a contract for an external service. - * @param is type for passing params - */ -public interface Chapter { - - /** - * @return service name. - */ - String getName(); - - /** - * every chapter is responsible for a part of saga. - * @param value incoming value - * @return saga result @see {@link RichSaga} - */ - RichSaga execute(K value); - - /** - * The operation executed in general case. - * @param value incoming value - * @return result {@link ChapterResult} - */ - ChapterResult process(K value); - - /** - * The operation executed in rollback case. - * @param value incoming value - * @return result {@link ChapterResult} - */ - ChapterResult rollback(K value); - -} diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/ChoreographyService.java b/saga/src/main/java/com/iluwatar/saga/choreography/ChoreographyService.java deleted file mode 100644 index e88a131b2189..000000000000 --- a/saga/src/main/java/com/iluwatar/saga/choreography/ChoreographyService.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.iluwatar.saga.choreography; - -import com.iluwatar.saga.ServiceDiscoveryService; -import com.iluwatar.saga.orchestration.Chapter; -import com.iluwatar.saga.orchestration.ChapterResult; -import com.iluwatar.saga.orchestration.OrchestrationService; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public abstract class ChoreographyService implements Chapter { - - protected static final Logger logger = LoggerFactory.getLogger(OrchestrationService.class); - - private final ServiceDiscoveryService service; - protected ChoreographyService(ServiceDiscoveryService service) { - this.service = service; - } - - @Override - public ChapterResult process(K value) { - logger.info("The chapter '{}' has been started. The data {} has been stored or calculated successfully", - getName(),value); - return ChapterResult.success(value); - } - - @Override - public ChapterResult rollback(K value) { - logger.info("The Rollback for a chapter '{}' has been started. The data {} has been rollbacked successfully", - getName(),value); - return ChapterResult.success(value); - } - -} diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/RichSaga.java b/saga/src/main/java/com/iluwatar/saga/choreography/RichSaga.java deleted file mode 100644 index 27e099fc793f..000000000000 --- a/saga/src/main/java/com/iluwatar/saga/choreography/RichSaga.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.iluwatar.saga.choreography; - -public class RichSaga { -} diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/FlyBookingService.java b/saga/src/main/java/com/iluwatar/saga/orchestration/FlyBookingService.java index 34f3f4f18eb2..6cb8479c07b2 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/FlyBookingService.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/FlyBookingService.java @@ -25,7 +25,7 @@ /** * Class representing a service to book a fly */ -public class FlyBookingService extends OrchestrationService { +public class FlyBookingService extends Service { @Override public String getName() { return "booking a Fly"; diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/HotelBookingService.java b/saga/src/main/java/com/iluwatar/saga/orchestration/HotelBookingService.java index a4da64d36ed3..e21046328918 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/HotelBookingService.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/HotelBookingService.java @@ -25,7 +25,7 @@ /** * Class representing a service to book a hotel */ -public class HotelBookingService extends OrchestrationService { +public class HotelBookingService extends Service { @Override public String getName() { return "booking a Hotel"; diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/OrderService.java b/saga/src/main/java/com/iluwatar/saga/orchestration/OrderService.java index 8fb7b118d739..6edd94ace40a 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/OrderService.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/OrderService.java @@ -25,7 +25,7 @@ /** * Class representing a service to init a new order. */ -public class OrderService extends OrchestrationService { +public class OrderService extends Service { @Override public String getName() { return "init an order"; diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/SagaApplication.java b/saga/src/main/java/com/iluwatar/saga/orchestration/SagaApplication.java index b69d040136bd..013d9a5f02f3 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/SagaApplication.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/SagaApplication.java @@ -41,7 +41,7 @@ * * @see Saga * @see SagaOrchestrator - * @see OrchestrationService + * @see Service */ public class SagaApplication { private static final Logger logger = LoggerFactory.getLogger(SagaApplication.class); diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/OrchestrationService.java b/saga/src/main/java/com/iluwatar/saga/orchestration/Service.java similarity index 95% rename from saga/src/main/java/com/iluwatar/saga/orchestration/OrchestrationService.java rename to saga/src/main/java/com/iluwatar/saga/orchestration/Service.java index 7f0e9a03cfe3..20b34f55aa95 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/OrchestrationService.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/Service.java @@ -30,8 +30,8 @@ * implementing a general contract @see {@link Chapter} * @param type of incoming param */ -public abstract class OrchestrationService implements Chapter { - protected static final Logger logger = LoggerFactory.getLogger(OrchestrationService.class); +public abstract class Service implements Chapter { + protected static final Logger logger = LoggerFactory.getLogger(Service.class); @Override public abstract String getName(); diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/WithdrawMoneyService.java b/saga/src/main/java/com/iluwatar/saga/orchestration/WithdrawMoneyService.java index d53f106cb1b4..dad15cec3864 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/WithdrawMoneyService.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/WithdrawMoneyService.java @@ -25,7 +25,7 @@ /** * Class representing a service to withdraw a money */ -public class WithdrawMoneyService extends OrchestrationService { +public class WithdrawMoneyService extends Service { @Override public String getName() { return "withdrawing Money"; diff --git a/saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorInternallyTest.java b/saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorInternallyTest.java index a40a3ebec2a1..16c54c9200c1 100644 --- a/saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorInternallyTest.java +++ b/saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorInternallyTest.java @@ -39,7 +39,7 @@ private ServiceDiscoveryService serviceDiscovery() { .discover(new Service4()); } - class Service1 extends OrchestrationService { + class Service1 extends Service { @Override public String getName() { @@ -59,7 +59,7 @@ public ChapterResult rollback(Integer value) { } } - class Service2 extends OrchestrationService { + class Service2 extends Service { @Override public String getName() { @@ -78,7 +78,7 @@ public ChapterResult rollback(Integer value) { } } - class Service3 extends OrchestrationService { + class Service3 extends Service { @Override public String getName() { @@ -97,7 +97,7 @@ public ChapterResult rollback(Integer value) { } } - class Service4 extends OrchestrationService { + class Service4 extends Service { @Override public String getName() { From fbcfeb072a588ff6dff203c447674b40c61dccc3 Mon Sep 17 00:00:00 2001 From: Besok Date: Sun, 3 Nov 2019 12:52:38 +0000 Subject: [PATCH 15/31] add info --- .../iluwatar/saga/choreography/Chapter.java | 53 +++++++++++++++++++ .../com/iluwatar/saga/choreography/Saga.java | 34 ++++++++++++ .../com/iluwatar/saga/orchestration/Saga.java | 2 +- 3 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 saga/src/main/java/com/iluwatar/saga/choreography/Chapter.java create mode 100644 saga/src/main/java/com/iluwatar/saga/choreography/Saga.java diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/Chapter.java b/saga/src/main/java/com/iluwatar/saga/choreography/Chapter.java new file mode 100644 index 000000000000..f610b9f62b03 --- /dev/null +++ b/saga/src/main/java/com/iluwatar/saga/choreography/Chapter.java @@ -0,0 +1,53 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.saga.choreography; + +import com.iluwatar.saga.orchestration.ChapterResult; + +/** + * Chapter is an interface representing a contract for an external service. + * @param is type for passing params + */ +public interface Chapter { + + /** + * @return service name. + */ + String getName(); + + /** + * The operation executed in general case. + * @param value incoming value + * @return result {@link ChapterResult} + */ + ChapterResult process(K value); + + /** + * The operation executed in rollback case. + * @param value incoming value + * @return result {@link ChapterResult} + */ + ChapterResult rollback(K value); + + +} diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/Saga.java b/saga/src/main/java/com/iluwatar/saga/choreography/Saga.java new file mode 100644 index 000000000000..94c8a119dcec --- /dev/null +++ b/saga/src/main/java/com/iluwatar/saga/choreography/Saga.java @@ -0,0 +1,34 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.saga.choreography; + +/** + * Saga representation. + * Saga consists of chapters. + * Every Chapter is executed a certain service. + */ +public class Saga { + + + +} diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/Saga.java b/saga/src/main/java/com/iluwatar/saga/orchestration/Saga.java index 9f8312d9f231..d6a703706e73 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/Saga.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/Saga.java @@ -27,7 +27,7 @@ /** * Saga representation. - * Saca consists of chapters. + * Saga consists of chapters. * Every Chapter is executed a certain service. */ public class Saga { From 09b4663b9a15c406b899bc6900320a8361c92253 Mon Sep 17 00:00:00 2001 From: Besok Date: Sat, 9 Nov 2019 17:42:49 +0000 Subject: [PATCH 16/31] add choreogr --- .../iluwatar/saga/choreography/Chapter.java | 27 ++-- .../saga/choreography/FlyBookingService.java | 38 ++++++ .../choreography/HotelBookingService.java | 40 ++++++ .../saga/choreography/OrderService.java | 39 ++++++ .../com/iluwatar/saga/choreography/Saga.java | 125 ++++++++++++++++++ .../saga/choreography/SagaApplication.java | 77 +++++++++++ .../iluwatar/saga/choreography/Service.java | 103 +++++++++++++++ .../choreography/ServiceDiscoveryService.java | 60 +++++++++ .../choreography/WithdrawMoneyService.java | 53 ++++++++ .../com/iluwatar/saga/orchestration/Saga.java | 3 +- .../saga/orchestration/SagaApplication.java | 5 +- .../saga/orchestration/SagaOrchestrator.java | 2 +- .../ServiceDiscoveryService.java | 4 +- .../choreography/SagaApplicationTest.java | 35 +++++ .../choreography/SagaChoreographyTest.java | 59 +++++++++ .../orchestration/SagaApplicationTest.java | 22 +++ .../SagaOrchestratorInternallyTest.java | 25 +++- .../orchestration/SagaOrchestratorTest.java | 23 +++- 18 files changed, 719 insertions(+), 21 deletions(-) create mode 100644 saga/src/main/java/com/iluwatar/saga/choreography/FlyBookingService.java create mode 100644 saga/src/main/java/com/iluwatar/saga/choreography/HotelBookingService.java create mode 100644 saga/src/main/java/com/iluwatar/saga/choreography/OrderService.java create mode 100644 saga/src/main/java/com/iluwatar/saga/choreography/SagaApplication.java create mode 100644 saga/src/main/java/com/iluwatar/saga/choreography/Service.java create mode 100644 saga/src/main/java/com/iluwatar/saga/choreography/ServiceDiscoveryService.java create mode 100644 saga/src/main/java/com/iluwatar/saga/choreography/WithdrawMoneyService.java rename saga/src/main/java/com/iluwatar/saga/{ => orchestration}/ServiceDiscoveryService.java (95%) create mode 100644 saga/src/test/java/com/iluwatar/saga/choreography/SagaApplicationTest.java create mode 100644 saga/src/test/java/com/iluwatar/saga/choreography/SagaChoreographyTest.java diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/Chapter.java b/saga/src/main/java/com/iluwatar/saga/choreography/Chapter.java index f610b9f62b03..51b0ce6b83f9 100644 --- a/saga/src/main/java/com/iluwatar/saga/choreography/Chapter.java +++ b/saga/src/main/java/com/iluwatar/saga/choreography/Chapter.java @@ -22,13 +22,20 @@ */ package com.iluwatar.saga.choreography; -import com.iluwatar.saga.orchestration.ChapterResult; /** * Chapter is an interface representing a contract for an external service. - * @param is type for passing params - */ -public interface Chapter { + * In that case, a service needs to make a decision what to do further + * hence the server needs to get all context representing {@link Saga} + * */ +public interface Chapter { + + /** + * In that case, every method is responsible to make a decision on what to do then + * @param saga incoming saga + * @return saga result + */ + Saga execute(Saga saga); /** * @return service name. @@ -37,17 +44,17 @@ public interface Chapter { /** * The operation executed in general case. - * @param value incoming value - * @return result {@link ChapterResult} + * @param saga incoming saga + * @return result {@link Saga} */ - ChapterResult process(K value); + Saga process(Saga saga); /** * The operation executed in rollback case. - * @param value incoming value - * @return result {@link ChapterResult} + * @param saga incoming saga + * @return result {@link Saga} */ - ChapterResult rollback(K value); + Saga rollback(Saga saga); } diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/FlyBookingService.java b/saga/src/main/java/com/iluwatar/saga/choreography/FlyBookingService.java new file mode 100644 index 000000000000..591324c52848 --- /dev/null +++ b/saga/src/main/java/com/iluwatar/saga/choreography/FlyBookingService.java @@ -0,0 +1,38 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.saga.choreography; + + +/** + * Class representing a service to book a fly + */ +public class FlyBookingService extends Service { + public FlyBookingService(ServiceDiscoveryService service) { + super(service); + } + + @Override + public String getName() { + return "booking a Fly"; + } +} diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/HotelBookingService.java b/saga/src/main/java/com/iluwatar/saga/choreography/HotelBookingService.java new file mode 100644 index 000000000000..e822a35682cf --- /dev/null +++ b/saga/src/main/java/com/iluwatar/saga/choreography/HotelBookingService.java @@ -0,0 +1,40 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.saga.choreography; + + +/** + * Class representing a service to book a hotel + */ +public class HotelBookingService extends Service { + public HotelBookingService(ServiceDiscoveryService service) { + super(service); + } + + @Override + public String getName() { + return "booking a Hotel"; + } + + + } diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/OrderService.java b/saga/src/main/java/com/iluwatar/saga/choreography/OrderService.java new file mode 100644 index 000000000000..6c8b9912ec10 --- /dev/null +++ b/saga/src/main/java/com/iluwatar/saga/choreography/OrderService.java @@ -0,0 +1,39 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.saga.choreography; + + +/** + * Class representing a service to init a new order. + */ +public class OrderService extends Service{ + + public OrderService(ServiceDiscoveryService service) { + super(service); + } + + @Override + public String getName() { + return "init an order"; + } +} diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/Saga.java b/saga/src/main/java/com/iluwatar/saga/choreography/Saga.java index 94c8a119dcec..34a8d6a0f39d 100644 --- a/saga/src/main/java/com/iluwatar/saga/choreography/Saga.java +++ b/saga/src/main/java/com/iluwatar/saga/choreography/Saga.java @@ -22,6 +22,10 @@ */ package com.iluwatar.saga.choreography; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + /** * Saga representation. * Saga consists of chapters. @@ -29,6 +33,127 @@ */ public class Saga { + private List chapters; + private int pos; + private boolean forward; + private boolean finished; + + + public static Saga create() { + return new Saga(); + } + public SagaResult getResult() { + return !finished ? + SagaResult.PROGRESS : + forward ? + SagaResult.FINISHED : + SagaResult.ROLLBACKED; + } + public Saga chapter(String name) { + this.chapters.add(new Chapter(name)); + return this; + } + public Saga setInValue(Object value){ + if(chapters.isEmpty()){ + return this; + } + chapters.get(chapters.size()-1).setInValue(value); + return this; + } + public Object getCurrentValue(){ + return chapters.get(pos).getInValue(); + } + public void setCurrentValue(Object value){ + chapters.get(pos).setInValue(value); + } + public void setCurrentStatus(ChapterResult result){ + chapters.get(pos).setResult(result); + } + + void setFinished(boolean finished) { + this.finished = finished; + } + boolean isForward() { + return forward; + } + int forward() { + return ++pos; + } + + int back() { + this.forward = false; + return --pos; + } + + + public Saga() { + this.chapters = new ArrayList<>(); + this.pos = 0; + this.forward = true; + this.finished = false; + } + + Chapter getCurrent() { + return chapters.get(pos); + } + + + boolean isPresent() { + return pos >= 0 && pos < chapters.size(); + } + boolean isCurrentSuccess(){ + return chapters.get(pos).isSuccess(); + } + + /*** + * Class presents a chapter status and incoming parameters(incoming parameter transforms to outcoming parameter) + */ + public static class Chapter { + private String name; + private ChapterResult result; + private Object inValue; + + + public Chapter(String name) { + this.name = name; + this.result = ChapterResult.INIT; + } + + public Object getInValue() { + return inValue; + } + + public void setInValue(Object object) { + this.inValue = object; + } + + public String getName() { + return name; + } + public void setResult(ChapterResult result){ + this.result = result; + } + + public boolean isSuccess(){ + return result == ChapterResult.SUCCESS; + } + } + + + public enum ChapterResult { + INIT, SUCCESS, ROLLBACK + } + public enum SagaResult { + PROGRESS, FINISHED, ROLLBACKED + } + @Override + public String toString() { + return "Saga{" + + "chapters=" + Arrays.toString(chapters.toArray()) + + ", pos=" + pos + + ", forward=" + forward + + '}'; + } } diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/SagaApplication.java b/saga/src/main/java/com/iluwatar/saga/choreography/SagaApplication.java new file mode 100644 index 000000000000..46792adac113 --- /dev/null +++ b/saga/src/main/java/com/iluwatar/saga/choreography/SagaApplication.java @@ -0,0 +1,77 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.saga.choreography; + + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This pattern is used in distributed services to perform a group of operations atomically. + * This is an analog of transaction in a database but in terms of microservices architecture this is executed + * in a distributed environment + *

+ * A saga is a sequence of local transactions in a certain context. If one transaction fails for some reason, + * the saga executes compensating transactions(rollbacks) to undo the impact of the preceding transactions. + *

+ * In this approach, there are no mediators or orchestrators services. + * All chapters are handled and moved by services manually. + *

+ * The major difference with choreography saga is an ability to handle crashed services + * (otherwise in choreography services very hard to prevent a saga if one of them has been crashed) + * + * @see com.iluwatar.saga.choreography.Saga + * @see Service + */ +public class SagaApplication { + private static final Logger logger = LoggerFactory.getLogger(SagaApplication.class); + + public static void main(String[] args) { + ServiceDiscoveryService sd = serviceDiscovery(); + Chapter service = sd.findAny(); + Saga goodOrderSaga = service.execute(newSaga("good_order")); + Saga badOrderSaga = service.execute(newSaga("bad_order")); + logger.info("orders: goodOrder is {}, badOrder is {}", + goodOrderSaga.getResult(), badOrderSaga.getResult()); + + } + + + private static Saga newSaga(Object value) { + return Saga + .create() + .chapter("init an order").setInValue(value) + .chapter("booking a Fly") + .chapter("booking a Hotel") + .chapter("withdrawing Money"); + } + + private static ServiceDiscoveryService serviceDiscovery() { + ServiceDiscoveryService sd = new ServiceDiscoveryService(); + return sd + .discover(new OrderService(sd)) + .discover(new FlyBookingService(sd)) + .discover(new HotelBookingService(sd)) + .discover(new WithdrawMoneyService(sd)); + } +} diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/Service.java b/saga/src/main/java/com/iluwatar/saga/choreography/Service.java new file mode 100644 index 000000000000..0f182e570927 --- /dev/null +++ b/saga/src/main/java/com/iluwatar/saga/choreography/Service.java @@ -0,0 +1,103 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.saga.choreography; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Common abstraction class representing services + * implementing a general contract @see {@link Chapter} + */ +public abstract class Service implements Chapter { + protected static final Logger logger = LoggerFactory.getLogger(Service.class); + + private final ServiceDiscoveryService sd; + + public Service(ServiceDiscoveryService service) { + this.sd = service; + } + + @Override + public Saga execute(Saga saga) { + Saga nextSaga = saga; + Object nextVal; + String chapterName = saga.getCurrent().getName(); + if (chapterName.equals(getName())) { + if (saga.isForward()) { + nextSaga = process(saga); + nextVal = nextSaga.getCurrentValue(); + if (nextSaga.isCurrentSuccess()) { + nextSaga.forward(); + } else { + nextSaga.back(); + } + } else { + nextSaga = rollback(saga); + nextVal = nextSaga.getCurrentValue(); + nextSaga.back(); + } + + if (isSagaFinished(nextSaga)) { + return nextSaga; + } + + nextSaga.setCurrentValue(nextVal); + } + Saga finalNextSaga = nextSaga; + + return sd.find(chapterName).map(ch -> ch.execute(finalNextSaga)) + .orElseThrow(RuntimeException::new); + } + + @Override + public Saga process(Saga saga) { + Object inValue = saga.getCurrentValue(); + logger.info("The chapter '{}' has been started. The data {} has been stored or calculated successfully", + getName(), inValue); + saga.setCurrentStatus(Saga.ChapterResult.SUCCESS); + saga.setCurrentValue(inValue); + return saga; + } + + @Override + public Saga rollback(Saga saga) { + Object inValue = saga.getCurrentValue(); + logger.info("The Rollback for a chapter '{}' has been started. The data {} has been rollbacked successfully", + getName(), inValue); + + saga.setCurrentStatus(Saga.ChapterResult.ROLLBACK); + saga.setCurrentValue(inValue); + return saga; + } + + private boolean isSagaFinished(Saga saga) { + if (!saga.isPresent()) { + saga.setFinished(true); + logger.info(" the saga has been finished with {} status", saga.getResult()); + return true; + } + return false; + } + +} diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/ServiceDiscoveryService.java b/saga/src/main/java/com/iluwatar/saga/choreography/ServiceDiscoveryService.java new file mode 100644 index 000000000000..11512d112ea5 --- /dev/null +++ b/saga/src/main/java/com/iluwatar/saga/choreography/ServiceDiscoveryService.java @@ -0,0 +1,60 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.saga.choreography; + + +import java.util.HashMap; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Optional; + +/** + * The class representing a service discovery pattern. + */ +public class ServiceDiscoveryService { + private Map services; + + /** + * find any service + * @return any service + * @throws NoSuchElementException if no elements further + */ + public Chapter findAny(){ + return services.values().iterator().next(); + } + + public Optional find(String service) { + return Optional.ofNullable(services.getOrDefault(service, null)); + } + + public ServiceDiscoveryService discover(Chapter chapterService) { + services.put(chapterService.getName(), chapterService); + return this; + } + + public ServiceDiscoveryService() { + this.services = new HashMap<>(); + } + + +} diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/WithdrawMoneyService.java b/saga/src/main/java/com/iluwatar/saga/choreography/WithdrawMoneyService.java new file mode 100644 index 000000000000..c13b1b1f8891 --- /dev/null +++ b/saga/src/main/java/com/iluwatar/saga/choreography/WithdrawMoneyService.java @@ -0,0 +1,53 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.saga.choreography; + + +/** + * Class representing a service to withdraw a money + */ +public class WithdrawMoneyService extends Service { + + public WithdrawMoneyService(ServiceDiscoveryService service) { + super(service); + } + + @Override + public String getName() { + return "withdrawing Money"; + } + + @Override + public Saga process(Saga saga) { + Object inValue = saga.getCurrentValue(); + + if (inValue.equals("bad_order") ) { + logger.info("The chapter '{}' has been started. But the exception has been raised." + + "The rollback is about to start", + getName(), inValue); + saga.setCurrentStatus(Saga.ChapterResult.ROLLBACK); + return saga; + } + return super.process(saga); + } +} diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/Saga.java b/saga/src/main/java/com/iluwatar/saga/orchestration/Saga.java index d6a703706e73..f24a8366c56f 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/Saga.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/Saga.java @@ -28,7 +28,7 @@ /** * Saga representation. * Saga consists of chapters. - * Every Chapter is executed a certain service. + * Every Chapter is executed by a certain service. */ public class Saga { @@ -39,7 +39,6 @@ public Saga() { } - public Saga chapter(String name) { this.chapters.add(new Chapter(name)); return this; diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/SagaApplication.java b/saga/src/main/java/com/iluwatar/saga/orchestration/SagaApplication.java index 013d9a5f02f3..bbeca62bb039 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/SagaApplication.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/SagaApplication.java @@ -24,7 +24,6 @@ package com.iluwatar.saga.orchestration; -import com.iluwatar.saga.ServiceDiscoveryService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -38,6 +37,8 @@ * * In this approach, there is an orchestrator @see {@link SagaOrchestrator} that manages all the transactions and directs * the participant services to execute local transactions based on events. + * The major difference with choreography saga is an ability to handle crashed services + * (otherwise in choreography services very hard to prevent a saga if one of them has been crashed) * * @see Saga * @see SagaOrchestrator @@ -49,7 +50,7 @@ public class SagaApplication { public static void main(String[] args) { SagaOrchestrator sagaOrchestrator = new SagaOrchestrator(newSaga(), serviceDiscovery()); - Saga.Result goodOrder = sagaOrchestrator.execute("god_order"); + Saga.Result goodOrder = sagaOrchestrator.execute("good_order"); Saga.Result badOrder = sagaOrchestrator.execute("bad_order"); Saga.Result crashedOrder = sagaOrchestrator.execute("crashed_order"); diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/SagaOrchestrator.java b/saga/src/main/java/com/iluwatar/saga/orchestration/SagaOrchestrator.java index 588a860aa16d..c005d70df187 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/SagaOrchestrator.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/SagaOrchestrator.java @@ -22,7 +22,6 @@ */ package com.iluwatar.saga.orchestration; -import com.iluwatar.saga.ServiceDiscoveryService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -48,6 +47,7 @@ public SagaOrchestrator(Saga saga, ServiceDiscoveryService sd) { } /** + * pipeline to execute saga process/story * * @param value incoming value * @param type for incoming value diff --git a/saga/src/main/java/com/iluwatar/saga/ServiceDiscoveryService.java b/saga/src/main/java/com/iluwatar/saga/orchestration/ServiceDiscoveryService.java similarity index 95% rename from saga/src/main/java/com/iluwatar/saga/ServiceDiscoveryService.java rename to saga/src/main/java/com/iluwatar/saga/orchestration/ServiceDiscoveryService.java index f9d91b53e3de..652740051b5e 100644 --- a/saga/src/main/java/com/iluwatar/saga/ServiceDiscoveryService.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/ServiceDiscoveryService.java @@ -20,9 +20,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package com.iluwatar.saga; - -import com.iluwatar.saga.orchestration.Chapter; +package com.iluwatar.saga.orchestration; import java.util.HashMap; import java.util.Map; diff --git a/saga/src/test/java/com/iluwatar/saga/choreography/SagaApplicationTest.java b/saga/src/test/java/com/iluwatar/saga/choreography/SagaApplicationTest.java new file mode 100644 index 000000000000..5802f54ec6c5 --- /dev/null +++ b/saga/src/test/java/com/iluwatar/saga/choreography/SagaApplicationTest.java @@ -0,0 +1,35 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.saga.choreography; + +import com.iluwatar.saga.orchestration.SagaApplication; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class SagaApplicationTest { + @Test + public void mainTest() { + SagaApplication.main(new String[]{}); + } +} \ No newline at end of file diff --git a/saga/src/test/java/com/iluwatar/saga/choreography/SagaChoreographyTest.java b/saga/src/test/java/com/iluwatar/saga/choreography/SagaChoreographyTest.java new file mode 100644 index 000000000000..8c8daa7c991f --- /dev/null +++ b/saga/src/test/java/com/iluwatar/saga/choreography/SagaChoreographyTest.java @@ -0,0 +1,59 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.saga.choreography; + +import org.junit.Assert; +import org.junit.Test; + +public class SagaChoreographyTest { + + + @Test + public void executeTest() { + ServiceDiscoveryService sd = serviceDiscovery(); + Chapter service = sd.findAny(); + Saga badOrderSaga = service.execute(newSaga("bad_order")); + Saga goodOrderSaga = service.execute(newSaga("good_order")); + + Assert.assertEquals(badOrderSaga.getResult(), Saga.SagaResult.ROLLBACKED); + Assert.assertEquals(goodOrderSaga.getResult(), Saga.SagaResult.FINISHED); + } + + private static Saga newSaga(Object value) { + return Saga + .create() + .chapter("init an order").setInValue(value) + .chapter("booking a Fly") + .chapter("booking a Hotel") + .chapter("withdrawing Money"); + } + + private static ServiceDiscoveryService serviceDiscovery() { + ServiceDiscoveryService sd = new ServiceDiscoveryService(); + return sd + .discover(new OrderService(sd)) + .discover(new FlyBookingService(sd)) + .discover(new HotelBookingService(sd)) + .discover(new WithdrawMoneyService(sd)); + } +} diff --git a/saga/src/test/java/com/iluwatar/saga/orchestration/SagaApplicationTest.java b/saga/src/test/java/com/iluwatar/saga/orchestration/SagaApplicationTest.java index 6950158aaef1..4e4d86644b10 100644 --- a/saga/src/test/java/com/iluwatar/saga/orchestration/SagaApplicationTest.java +++ b/saga/src/test/java/com/iluwatar/saga/orchestration/SagaApplicationTest.java @@ -1,3 +1,25 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package com.iluwatar.saga.orchestration; import org.junit.Test; diff --git a/saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorInternallyTest.java b/saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorInternallyTest.java index 16c54c9200c1..ce3b926a3775 100644 --- a/saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorInternallyTest.java +++ b/saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorInternallyTest.java @@ -1,6 +1,27 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package com.iluwatar.saga.orchestration; -import com.iluwatar.saga.ServiceDiscoveryService; import org.junit.Assert; import org.junit.Test; @@ -12,7 +33,7 @@ public class SagaOrchestratorInternallyTest { private List records = new ArrayList<>(); @Test - public void execute() { + public void executeTest() { SagaOrchestrator sagaOrchestrator = new SagaOrchestrator(newSaga(), serviceDiscovery()); Saga.Result result = sagaOrchestrator.execute(1); Assert.assertEquals(result, Saga.Result.ROLLBACK); diff --git a/saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorTest.java b/saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorTest.java index cd659601eacc..bead0343d1b9 100644 --- a/saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorTest.java +++ b/saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorTest.java @@ -1,6 +1,27 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package com.iluwatar.saga.orchestration; -import com.iluwatar.saga.ServiceDiscoveryService; import org.junit.Assert; import org.junit.Test; From 74c7273381a9c2fb521f1aa3b2924d9d290c876b Mon Sep 17 00:00:00 2001 From: Besok Date: Sat, 9 Nov 2019 18:57:31 +0000 Subject: [PATCH 17/31] rem space --- .../src/main/java/com/iluwatar/roleobject/InvestorRole.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/role-object/src/main/java/com/iluwatar/roleobject/InvestorRole.java b/role-object/src/main/java/com/iluwatar/roleobject/InvestorRole.java index 6d5c17c904f7..d6ec6bc42050 100644 --- a/role-object/src/main/java/com/iluwatar/roleobject/InvestorRole.java +++ b/role-object/src/main/java/com/iluwatar/roleobject/InvestorRole.java @@ -43,6 +43,6 @@ public void setAmountToInvest(long amountToInvest) { } public String invest() { - return String.format("Investor %s has invested %d dollars", name, amountToInvest); + return String.format("Investor %s has invested %d dollars", name, amountToInvest); } } From de56cbb971207e7d754e0d86038e5ac9f998ea79 Mon Sep 17 00:00:00 2001 From: Besok Date: Sun, 10 Nov 2019 13:09:41 +0000 Subject: [PATCH 18/31] change according to cgeckstyle --- saga/README.md | 4 +- saga/pom.xml | 33 +- ...{Chapter.java => ChoreographyChapter.java} | 61 ++-- .../saga/choreography/FlyBookingService.java | 14 +- .../choreography/HotelBookingService.java | 16 +- .../saga/choreography/OrderService.java | 16 +- .../com/iluwatar/saga/choreography/Saga.java | 296 +++++++++++------- .../saga/choreography/SagaApplication.java | 53 ++-- .../iluwatar/saga/choreography/Service.java | 126 ++++---- .../choreography/ServiceDiscoveryService.java | 47 +-- .../choreography/WithdrawMoneyService.java | 36 +-- .../saga/orchestration/ChapterResult.java | 46 +-- .../saga/orchestration/FlyBookingService.java | 8 +- .../orchestration/HotelBookingService.java | 32 +- ...Chapter.java => OrchestrationChapter.java} | 39 +-- .../saga/orchestration/OrderService.java | 8 +- .../com/iluwatar/saga/orchestration/Saga.java | 65 ++-- .../saga/orchestration/SagaApplication.java | 58 ++-- .../saga/orchestration/SagaOrchestrator.java | 179 ++++++----- .../iluwatar/saga/orchestration/Service.java | 43 +-- .../ServiceDiscoveryService.java | 22 +- .../orchestration/WithdrawMoneyService.java | 26 +- .../choreography/SagaApplicationTest.java | 12 +- .../choreography/SagaChoreographyTest.java | 53 ++-- .../orchestration/SagaApplicationTest.java | 11 +- .../SagaOrchestratorInternallyTest.java | 184 +++++------ .../orchestration/SagaOrchestratorTest.java | 51 +-- 27 files changed, 825 insertions(+), 714 deletions(-) rename saga/src/main/java/com/iluwatar/saga/choreography/{Chapter.java => ChoreographyChapter.java} (65%) rename saga/src/main/java/com/iluwatar/saga/orchestration/{Chapter.java => OrchestrationChapter.java} (69%) diff --git a/saga/README.md b/saga/README.md index 276f12ee1f37..546ad598b7c0 100644 --- a/saga/README.md +++ b/saga/README.md @@ -1,7 +1,7 @@ --- layout: pattern title: Saga -folder: Communication +folder: saga permalink: /patterns/saga/ categories: Behavioral tags: @@ -43,4 +43,4 @@ Use the Saga pattern, if: - you can not use 2PC(two phase commit) ## Credits -- [pattern description](https://microservices.io/patterns/data/saga.html) \ No newline at end of file +- [Pattern: Saga](https://microservices.io/patterns/data/saga.html) \ No newline at end of file diff --git a/saga/pom.xml b/saga/pom.xml index 26c3312373a2..111f4e7b8134 100644 --- a/saga/pom.xml +++ b/saga/pom.xml @@ -23,22 +23,23 @@ THE SOFTWARE. --> - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.22.0-SNAPSHOT - + + 4.0.0 + + com.iluwatar + java-design-patterns + 1.22.0-SNAPSHOT + - saga - - - junit - junit - test - - + saga + + + junit + junit + test + + diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/Chapter.java b/saga/src/main/java/com/iluwatar/saga/choreography/ChoreographyChapter.java similarity index 65% rename from saga/src/main/java/com/iluwatar/saga/choreography/Chapter.java rename to saga/src/main/java/com/iluwatar/saga/choreography/ChoreographyChapter.java index 51b0ce6b83f9..caa377a1e118 100644 --- a/saga/src/main/java/com/iluwatar/saga/choreography/Chapter.java +++ b/saga/src/main/java/com/iluwatar/saga/choreography/ChoreographyChapter.java @@ -24,37 +24,40 @@ /** - * Chapter is an interface representing a contract for an external service. + * ChoreographyChapter is an interface representing a contract for an external service. * In that case, a service needs to make a decision what to do further * hence the server needs to get all context representing {@link Saga} - * */ -public interface Chapter { - - /** - * In that case, every method is responsible to make a decision on what to do then - * @param saga incoming saga - * @return saga result - */ - Saga execute(Saga saga); - - /** - * @return service name. - */ - String getName(); - - /** - * The operation executed in general case. - * @param saga incoming saga - * @return result {@link Saga} - */ - Saga process(Saga saga); - - /** - * The operation executed in rollback case. - * @param saga incoming saga - * @return result {@link Saga} - */ - Saga rollback(Saga saga); + */ +public interface ChoreographyChapter { + + /** + * In that case, every method is responsible to make a decision on what to do then + * + * @param saga incoming saga + * @return saga result + */ + Saga execute(Saga saga); + + /** + * @return service name. + */ + String getName(); + + /** + * The operation executed in general case. + * + * @param saga incoming saga + * @return result {@link Saga} + */ + Saga process(Saga saga); + + /** + * The operation executed in rollback case. + * + * @param saga incoming saga + * @return result {@link Saga} + */ + Saga rollback(Saga saga); } diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/FlyBookingService.java b/saga/src/main/java/com/iluwatar/saga/choreography/FlyBookingService.java index 591324c52848..60b183be36f1 100644 --- a/saga/src/main/java/com/iluwatar/saga/choreography/FlyBookingService.java +++ b/saga/src/main/java/com/iluwatar/saga/choreography/FlyBookingService.java @@ -27,12 +27,12 @@ * Class representing a service to book a fly */ public class FlyBookingService extends Service { - public FlyBookingService(ServiceDiscoveryService service) { - super(service); - } + public FlyBookingService(ServiceDiscoveryService service) { + super(service); + } - @Override - public String getName() { - return "booking a Fly"; - } + @Override + public String getName() { + return "booking a Fly"; + } } diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/HotelBookingService.java b/saga/src/main/java/com/iluwatar/saga/choreography/HotelBookingService.java index e822a35682cf..0bbf1d3e3118 100644 --- a/saga/src/main/java/com/iluwatar/saga/choreography/HotelBookingService.java +++ b/saga/src/main/java/com/iluwatar/saga/choreography/HotelBookingService.java @@ -27,14 +27,14 @@ * Class representing a service to book a hotel */ public class HotelBookingService extends Service { - public HotelBookingService(ServiceDiscoveryService service) { - super(service); - } + public HotelBookingService(ServiceDiscoveryService service) { + super(service); + } - @Override - public String getName() { - return "booking a Hotel"; - } + @Override + public String getName() { + return "booking a Hotel"; + } - } +} diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/OrderService.java b/saga/src/main/java/com/iluwatar/saga/choreography/OrderService.java index 6c8b9912ec10..3a2c002b1796 100644 --- a/saga/src/main/java/com/iluwatar/saga/choreography/OrderService.java +++ b/saga/src/main/java/com/iluwatar/saga/choreography/OrderService.java @@ -26,14 +26,14 @@ /** * Class representing a service to init a new order. */ -public class OrderService extends Service{ +public class OrderService extends Service { - public OrderService(ServiceDiscoveryService service) { - super(service); - } + public OrderService(ServiceDiscoveryService service) { + super(service); + } - @Override - public String getName() { - return "init an order"; - } + @Override + public String getName() { + return "init an order"; + } } diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/Saga.java b/saga/src/main/java/com/iluwatar/saga/choreography/Saga.java index 34a8d6a0f39d..35069b80f9db 100644 --- a/saga/src/main/java/com/iluwatar/saga/choreography/Saga.java +++ b/saga/src/main/java/com/iluwatar/saga/choreography/Saga.java @@ -29,131 +29,187 @@ /** * Saga representation. * Saga consists of chapters. - * Every Chapter is executed a certain service. + * Every ChoreographyChapter is executed a certain service. */ public class Saga { - private List chapters; - private int pos; - private boolean forward; - private boolean finished; - - - public static Saga create() { - return new Saga(); - } - public SagaResult getResult() { - return !finished ? - SagaResult.PROGRESS : - forward ? - SagaResult.FINISHED : - SagaResult.ROLLBACKED; - } - public Saga chapter(String name) { - this.chapters.add(new Chapter(name)); - return this; - } - public Saga setInValue(Object value){ - if(chapters.isEmpty()){ - return this; - } - chapters.get(chapters.size()-1).setInValue(value); - return this; - } - public Object getCurrentValue(){ - return chapters.get(pos).getInValue(); - } - public void setCurrentValue(Object value){ - chapters.get(pos).setInValue(value); - } - public void setCurrentStatus(ChapterResult result){ - chapters.get(pos).setResult(result); + private List chapters; + private int pos; + private boolean forward; + private boolean finished; + + + public static Saga create() { + return new Saga(); + } + + /** + * get resuzlt of saga + * + * @return result of saga @see {@link SagaResult} + */ + public SagaResult getResult() { + if (finished) { + return forward + ? SagaResult.FINISHED + : SagaResult.ROLLBACKED; + } + + return SagaResult.PROGRESS; + } + + /** + * add chapter to saga + * @param name chapter name + * @return this + */ + public Saga chapter(String name) { + this.chapters.add(new Chapter(name)); + return this; + } + + /** + * set value to last chapter + * @param value invalue + * @return this + */ + public Saga setInValue(Object value) { + if (chapters.isEmpty()) { + return this; + } + chapters.get(chapters.size() - 1).setInValue(value); + return this; + } + + /** + * get value from current chapter + * @return value + */ + public Object getCurrentValue() { + return chapters.get(pos).getInValue(); + } + + /** + * set value to current chapter + * @param value to set + */ + public void setCurrentValue(Object value) { + chapters.get(pos).setInValue(value); + } + + /** + * set status for current chapter + * @param result to set + */ + public void setCurrentStatus(ChapterResult result) { + chapters.get(pos).setResult(result); + } + + void setFinished(boolean finished) { + this.finished = finished; + } + + boolean isForward() { + return forward; + } + + int forward() { + return ++pos; + } + + int back() { + this.forward = false; + return --pos; + } + + + private Saga() { + this.chapters = new ArrayList<>(); + this.pos = 0; + this.forward = true; + this.finished = false; + } + + Chapter getCurrent() { + return chapters.get(pos); + } + + + boolean isPresent() { + return pos >= 0 && pos < chapters.size(); + } + + boolean isCurrentSuccess() { + return chapters.get(pos).isSuccess(); + } + + /*** + * Class presents a chapter status and incoming parameters(incoming parameter transforms to outcoming parameter) + */ + public static class Chapter { + private String name; + private ChapterResult result; + private Object inValue; + + + public Chapter(String name) { + this.name = name; + this.result = ChapterResult.INIT; + } + + public Object getInValue() { + return inValue; + } + + public void setInValue(Object object) { + this.inValue = object; + } + + public String getName() { + return name; } - - void setFinished(boolean finished) { - this.finished = finished; - } - boolean isForward() { - return forward; - } - int forward() { - return ++pos; - } - - int back() { - this.forward = false; - return --pos; - } - - - public Saga() { - this.chapters = new ArrayList<>(); - this.pos = 0; - this.forward = true; - this.finished = false; - } - - Chapter getCurrent() { - return chapters.get(pos); - } - - - boolean isPresent() { - return pos >= 0 && pos < chapters.size(); - } - boolean isCurrentSuccess(){ - return chapters.get(pos).isSuccess(); - } - - /*** - * Class presents a chapter status and incoming parameters(incoming parameter transforms to outcoming parameter) + + /** + * set result + * @param result {@link ChapterResult} */ - public static class Chapter { - private String name; - private ChapterResult result; - private Object inValue; - - - public Chapter(String name) { - this.name = name; - this.result = ChapterResult.INIT; - } - - public Object getInValue() { - return inValue; - } - - public void setInValue(Object object) { - this.inValue = object; - } - - public String getName() { - return name; - } - public void setResult(ChapterResult result){ - this.result = result; - } - - public boolean isSuccess(){ - return result == ChapterResult.SUCCESS; - } + public void setResult(ChapterResult result) { + this.result = result; } - - public enum ChapterResult { - INIT, SUCCESS, ROLLBACK - } - - public enum SagaResult { - PROGRESS, FINISHED, ROLLBACKED - } - - @Override - public String toString() { - return "Saga{" + - "chapters=" + Arrays.toString(chapters.toArray()) + - ", pos=" + pos + - ", forward=" + forward + - '}'; - } + /** + * the result for chapter is good + * @return true if is good otherwise bad + */ + public boolean isSuccess() { + return result == ChapterResult.SUCCESS; + } + } + + + /** + * result for chapter + */ + public enum ChapterResult { + INIT, SUCCESS, ROLLBACK + } + + /** + * result for saga + */ + public enum SagaResult { + PROGRESS, FINISHED, ROLLBACKED + } + + @Override + public String toString() { + return "Saga{" + + "chapters=" + + Arrays.toString(chapters.toArray()) + + ", pos=" + + pos + + ", forward=" + + forward + + '}'; + } } diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/SagaApplication.java b/saga/src/main/java/com/iluwatar/saga/choreography/SagaApplication.java index 46792adac113..3aeb8672c534 100644 --- a/saga/src/main/java/com/iluwatar/saga/choreography/SagaApplication.java +++ b/saga/src/main/java/com/iluwatar/saga/choreography/SagaApplication.java @@ -44,34 +44,37 @@ * @see Service */ public class SagaApplication { - private static final Logger logger = LoggerFactory.getLogger(SagaApplication.class); + private static final Logger LOGGER = LoggerFactory.getLogger(SagaApplication.class); - public static void main(String[] args) { - ServiceDiscoveryService sd = serviceDiscovery(); - Chapter service = sd.findAny(); - Saga goodOrderSaga = service.execute(newSaga("good_order")); - Saga badOrderSaga = service.execute(newSaga("bad_order")); - logger.info("orders: goodOrder is {}, badOrder is {}", - goodOrderSaga.getResult(), badOrderSaga.getResult()); + /** + * main method + */ + public static void main(String[] args) { + ServiceDiscoveryService sd = serviceDiscovery(); + ChoreographyChapter service = sd.findAny(); + Saga goodOrderSaga = service.execute(newSaga("good_order")); + Saga badOrderSaga = service.execute(newSaga("bad_order")); + LOGGER.info("orders: goodOrder is {}, badOrder is {}", + goodOrderSaga.getResult(), badOrderSaga.getResult()); - } + } - private static Saga newSaga(Object value) { - return Saga - .create() - .chapter("init an order").setInValue(value) - .chapter("booking a Fly") - .chapter("booking a Hotel") - .chapter("withdrawing Money"); - } + private static Saga newSaga(Object value) { + return Saga + .create() + .chapter("init an order").setInValue(value) + .chapter("booking a Fly") + .chapter("booking a Hotel") + .chapter("withdrawing Money"); + } - private static ServiceDiscoveryService serviceDiscovery() { - ServiceDiscoveryService sd = new ServiceDiscoveryService(); - return sd - .discover(new OrderService(sd)) - .discover(new FlyBookingService(sd)) - .discover(new HotelBookingService(sd)) - .discover(new WithdrawMoneyService(sd)); - } + private static ServiceDiscoveryService serviceDiscovery() { + ServiceDiscoveryService sd = new ServiceDiscoveryService(); + return sd + .discover(new OrderService(sd)) + .discover(new FlyBookingService(sd)) + .discover(new HotelBookingService(sd)) + .discover(new WithdrawMoneyService(sd)); + } } diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/Service.java b/saga/src/main/java/com/iluwatar/saga/choreography/Service.java index 0f182e570927..a602b1147ba7 100644 --- a/saga/src/main/java/com/iluwatar/saga/choreography/Service.java +++ b/saga/src/main/java/com/iluwatar/saga/choreography/Service.java @@ -25,79 +25,85 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.function.Supplier; + /** * Common abstraction class representing services - * implementing a general contract @see {@link Chapter} + * implementing a general contract @see {@link ChoreographyChapter} */ -public abstract class Service implements Chapter { - protected static final Logger logger = LoggerFactory.getLogger(Service.class); - - private final ServiceDiscoveryService sd; +public abstract class Service implements ChoreographyChapter { + protected static final Logger LOGGER = LoggerFactory.getLogger(Service.class); - public Service(ServiceDiscoveryService service) { - this.sd = service; - } + private final ServiceDiscoveryService sd; - @Override - public Saga execute(Saga saga) { - Saga nextSaga = saga; - Object nextVal; - String chapterName = saga.getCurrent().getName(); - if (chapterName.equals(getName())) { - if (saga.isForward()) { - nextSaga = process(saga); - nextVal = nextSaga.getCurrentValue(); - if (nextSaga.isCurrentSuccess()) { - nextSaga.forward(); - } else { - nextSaga.back(); - } - } else { - nextSaga = rollback(saga); - nextVal = nextSaga.getCurrentValue(); - nextSaga.back(); - } + public Service(ServiceDiscoveryService service) { + this.sd = service; + } - if (isSagaFinished(nextSaga)) { - return nextSaga; - } - - nextSaga.setCurrentValue(nextVal); + @Override + public Saga execute(Saga saga) { + Saga nextSaga = saga; + Object nextVal; + String chapterName = saga.getCurrent().getName(); + if (chapterName.equals(getName())) { + if (saga.isForward()) { + nextSaga = process(saga); + nextVal = nextSaga.getCurrentValue(); + if (nextSaga.isCurrentSuccess()) { + nextSaga.forward(); + } else { + nextSaga.back(); } - Saga finalNextSaga = nextSaga; + } else { + nextSaga = rollback(saga); + nextVal = nextSaga.getCurrentValue(); + nextSaga.back(); + } - return sd.find(chapterName).map(ch -> ch.execute(finalNextSaga)) - .orElseThrow(RuntimeException::new); - } + if (isSagaFinished(nextSaga)) { + return nextSaga; + } - @Override - public Saga process(Saga saga) { - Object inValue = saga.getCurrentValue(); - logger.info("The chapter '{}' has been started. The data {} has been stored or calculated successfully", - getName(), inValue); - saga.setCurrentStatus(Saga.ChapterResult.SUCCESS); - saga.setCurrentValue(inValue); - return saga; + nextSaga.setCurrentValue(nextVal); } + Saga finalNextSaga = nextSaga; - @Override - public Saga rollback(Saga saga) { - Object inValue = saga.getCurrentValue(); - logger.info("The Rollback for a chapter '{}' has been started. The data {} has been rollbacked successfully", - getName(), inValue); + return sd.find(chapterName).map(ch -> ch.execute(finalNextSaga)) + .orElseThrow(serviceNotFoundException(chapterName)); + } - saga.setCurrentStatus(Saga.ChapterResult.ROLLBACK); - saga.setCurrentValue(inValue); - return saga; - } + private Supplier serviceNotFoundException(String chServiceName) { + return () -> new RuntimeException(String.format("the service %s has not been found", chServiceName)); + } - private boolean isSagaFinished(Saga saga) { - if (!saga.isPresent()) { - saga.setFinished(true); - logger.info(" the saga has been finished with {} status", saga.getResult()); - return true; - } - return false; + @Override + public Saga process(Saga saga) { + Object inValue = saga.getCurrentValue(); + LOGGER.info("The chapter '{}' has been started. The data {} has been stored or calculated successfully", + getName(), inValue); + saga.setCurrentStatus(Saga.ChapterResult.SUCCESS); + saga.setCurrentValue(inValue); + return saga; + } + + @Override + public Saga rollback(Saga saga) { + Object inValue = saga.getCurrentValue(); + LOGGER.info("The Rollback for a chapter '{}' has been started. The data {} has been rollbacked successfully", + getName(), inValue); + + saga.setCurrentStatus(Saga.ChapterResult.ROLLBACK); + saga.setCurrentValue(inValue); + return saga; + } + + private boolean isSagaFinished(Saga saga) { + if (!saga.isPresent()) { + saga.setFinished(true); + LOGGER.info(" the saga has been finished with {} status", saga.getResult()); + return true; } + return false; + } } diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/ServiceDiscoveryService.java b/saga/src/main/java/com/iluwatar/saga/choreography/ServiceDiscoveryService.java index 11512d112ea5..919c99f02ede 100644 --- a/saga/src/main/java/com/iluwatar/saga/choreography/ServiceDiscoveryService.java +++ b/saga/src/main/java/com/iluwatar/saga/choreography/ServiceDiscoveryService.java @@ -32,29 +32,30 @@ * The class representing a service discovery pattern. */ public class ServiceDiscoveryService { - private Map services; - - /** - * find any service - * @return any service - * @throws NoSuchElementException if no elements further - */ - public Chapter findAny(){ - return services.values().iterator().next(); - } - - public Optional find(String service) { - return Optional.ofNullable(services.getOrDefault(service, null)); - } - - public ServiceDiscoveryService discover(Chapter chapterService) { - services.put(chapterService.getName(), chapterService); - return this; - } - - public ServiceDiscoveryService() { - this.services = new HashMap<>(); - } + private Map services; + + /** + * find any service + * + * @return any service + * @throws NoSuchElementException if no elements further + */ + public ChoreographyChapter findAny() { + return services.values().iterator().next(); + } + + public Optional find(String service) { + return Optional.ofNullable(services.getOrDefault(service, null)); + } + + public ServiceDiscoveryService discover(ChoreographyChapter chapterService) { + services.put(chapterService.getName(), chapterService); + return this; + } + + public ServiceDiscoveryService() { + this.services = new HashMap<>(); + } } diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/WithdrawMoneyService.java b/saga/src/main/java/com/iluwatar/saga/choreography/WithdrawMoneyService.java index c13b1b1f8891..b30a05e9576c 100644 --- a/saga/src/main/java/com/iluwatar/saga/choreography/WithdrawMoneyService.java +++ b/saga/src/main/java/com/iluwatar/saga/choreography/WithdrawMoneyService.java @@ -28,26 +28,26 @@ */ public class WithdrawMoneyService extends Service { - public WithdrawMoneyService(ServiceDiscoveryService service) { - super(service); - } + public WithdrawMoneyService(ServiceDiscoveryService service) { + super(service); + } - @Override - public String getName() { - return "withdrawing Money"; - } + @Override + public String getName() { + return "withdrawing Money"; + } - @Override - public Saga process(Saga saga) { - Object inValue = saga.getCurrentValue(); + @Override + public Saga process(Saga saga) { + Object inValue = saga.getCurrentValue(); - if (inValue.equals("bad_order") ) { - logger.info("The chapter '{}' has been started. But the exception has been raised." + - "The rollback is about to start", - getName(), inValue); - saga.setCurrentStatus(Saga.ChapterResult.ROLLBACK); - return saga; - } - return super.process(saga); + if (inValue.equals("bad_order")) { + LOGGER.info("The chapter '{}' has been started. But the exception has been raised." + + "The rollback is about to start", + getName(), inValue); + saga.setCurrentStatus(Saga.ChapterResult.ROLLBACK); + return saga; } + return super.process(saga); + } } diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/ChapterResult.java b/saga/src/main/java/com/iluwatar/saga/orchestration/ChapterResult.java index eae95b3391f8..a8a1e7b5e869 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/ChapterResult.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/ChapterResult.java @@ -24,34 +24,38 @@ /** * Executing result for chapter + * * @param incoming value */ public class ChapterResult { - private K value; - private State state; + private K value; + private State state; - public K getValue() { - return value; - } + public K getValue() { + return value; + } - ChapterResult(K value, State state) { - this.value = value; - this.state = state; - } + ChapterResult(K value, State state) { + this.value = value; + this.state = state; + } - public boolean isSuccess(){ - return state == State.SUCCESS; - } + public boolean isSuccess() { + return state == State.SUCCESS; + } - public static ChapterResult success(K val) { - return new ChapterResult<>(val, State.SUCCESS); - } + public static ChapterResult success(K val) { + return new ChapterResult<>(val, State.SUCCESS); + } - public static ChapterResult failure(K val) { - return new ChapterResult<>(val, State.FAILURE); - } + public static ChapterResult failure(K val) { + return new ChapterResult<>(val, State.FAILURE); + } - public enum State { - SUCCESS, FAILURE - } + /** + * state for chapter + */ + public enum State { + SUCCESS, FAILURE + } } diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/FlyBookingService.java b/saga/src/main/java/com/iluwatar/saga/orchestration/FlyBookingService.java index 6cb8479c07b2..5dc0577bc35d 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/FlyBookingService.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/FlyBookingService.java @@ -26,8 +26,8 @@ * Class representing a service to book a fly */ public class FlyBookingService extends Service { - @Override - public String getName() { - return "booking a Fly"; - } + @Override + public String getName() { + return "booking a Fly"; + } } diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/HotelBookingService.java b/saga/src/main/java/com/iluwatar/saga/orchestration/HotelBookingService.java index e21046328918..51d8d5aad8f9 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/HotelBookingService.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/HotelBookingService.java @@ -26,25 +26,25 @@ * Class representing a service to book a hotel */ public class HotelBookingService extends Service { - @Override - public String getName() { - return "booking a Hotel"; - } + @Override + public String getName() { + return "booking a Hotel"; + } - @Override - public ChapterResult rollback(String value) { - if(value.equals("crashed_order")){ - logger.info("The Rollback for a chapter '{}' has been started. " + - "The data {} has been failed.The saga has been crashed.", - getName(), value); + @Override + public ChapterResult rollback(String value) { + if (value.equals("crashed_order")) { + LOGGER.info("The Rollback for a chapter '{}' has been started. " + + "The data {} has been failed.The saga has been crashed.", + getName(), value); - return ChapterResult.failure(value); - } + return ChapterResult.failure(value); + } - logger.info("The Rollback for a chapter '{}' has been started. The data {} has been rollbacked successfully", - getName(), value); + LOGGER.info("The Rollback for a chapter '{}' has been started. The data {} has been rollbacked successfully", + getName(), value); - return super.rollback(value); - } + return super.rollback(value); + } } diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/Chapter.java b/saga/src/main/java/com/iluwatar/saga/orchestration/OrchestrationChapter.java similarity index 69% rename from saga/src/main/java/com/iluwatar/saga/orchestration/Chapter.java rename to saga/src/main/java/com/iluwatar/saga/orchestration/OrchestrationChapter.java index 961a8893733a..861382a00ee8 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/Chapter.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/OrchestrationChapter.java @@ -23,28 +23,31 @@ package com.iluwatar.saga.orchestration; /** - * Chapter is an interface representing a contract for an external service. + * ChoreographyChapter is an interface representing a contract for an external service. + * * @param is type for passing params */ -public interface Chapter { +public interface OrchestrationChapter { - /** - * @return service name. - */ - String getName(); + /** + * @return service name. + */ + String getName(); - /** - * The operation executed in general case. - * @param value incoming value - * @return result {@link ChapterResult} - */ - ChapterResult process(K value); + /** + * The operation executed in general case. + * + * @param value incoming value + * @return result {@link ChapterResult} + */ + ChapterResult process(K value); - /** - * The operation executed in rollback case. - * @param value incoming value - * @return result {@link ChapterResult} - */ - ChapterResult rollback(K value); + /** + * The operation executed in rollback case. + * + * @param value incoming value + * @return result {@link ChapterResult} + */ + ChapterResult rollback(K value); } diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/OrderService.java b/saga/src/main/java/com/iluwatar/saga/orchestration/OrderService.java index 6edd94ace40a..32b9ce90b2c6 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/OrderService.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/OrderService.java @@ -26,8 +26,8 @@ * Class representing a service to init a new order. */ public class OrderService extends Service { - @Override - public String getName() { - return "init an order"; - } + @Override + public String getName() { + return "init an order"; + } } diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/Saga.java b/saga/src/main/java/com/iluwatar/saga/orchestration/Saga.java index f24a8366c56f..e42b06f9a955 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/Saga.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/Saga.java @@ -28,49 +28,56 @@ /** * Saga representation. * Saga consists of chapters. - * Every Chapter is executed by a certain service. + * Every ChoreographyChapter is executed by a certain service. */ public class Saga { - private List chapters; + private List chapters; - public Saga() { - this.chapters = new ArrayList<>(); - } + private Saga() { + this.chapters = new ArrayList<>(); + } - public Saga chapter(String name) { - this.chapters.add(new Chapter(name)); - return this; - } + public Saga chapter(String name) { + this.chapters.add(new Chapter(name)); + return this; + } - public Chapter get(int idx) { - return chapters.get(idx); - } - public boolean isPresent(int idx) { - return idx >= 0 && idx < chapters.size(); - } + public Chapter get(int idx) { + return chapters.get(idx); + } + public boolean isPresent(int idx) { + return idx >= 0 && idx < chapters.size(); + } - public static Saga create() { - return new Saga(); - } - public enum Result { - FINISHED, ROLLBACK, CRASHED - } + public static Saga create() { + return new Saga(); + } - public static class Chapter { - String name; + /** + * result for saga + */ + public enum Result { + FINISHED, ROLLBACK, CRASHED + } - public Chapter(String name) { - this.name = name; - } + /** + * class represents chapter name + */ + public static class Chapter { + String name; + + public Chapter(String name) { + this.name = name; + } - public String getName() { - return name; - } + public String getName() { + return name; } + } } diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/SagaApplication.java b/saga/src/main/java/com/iluwatar/saga/orchestration/SagaApplication.java index bbeca62bb039..6d7e9fd8d794 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/SagaApplication.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/SagaApplication.java @@ -31,11 +31,12 @@ * This pattern is used in distributed services to perform a group of operations atomically. * This is an analog of transaction in a database but in terms of microservices architecture this is executed * in a distributed environment - * + *

* A saga is a sequence of local transactions in a certain context. If one transaction fails for some reason, * the saga executes compensating transactions(rollbacks) to undo the impact of the preceding transactions. - * - * In this approach, there is an orchestrator @see {@link SagaOrchestrator} that manages all the transactions and directs + *

+ * In this approach, there is an orchestrator @see {@link SagaOrchestrator} + * that manages all the transactions and directs * the participant services to execute local transactions based on events. * The major difference with choreography saga is an ability to handle crashed services * (otherwise in choreography services very hard to prevent a saga if one of them has been crashed) @@ -45,34 +46,37 @@ * @see Service */ public class SagaApplication { - private static final Logger logger = LoggerFactory.getLogger(SagaApplication.class); + private static final Logger LOGGER = LoggerFactory.getLogger(SagaApplication.class); - public static void main(String[] args) { - SagaOrchestrator sagaOrchestrator = new SagaOrchestrator(newSaga(), serviceDiscovery()); + /** + * method to show common saga logic + */ + public static void main(String[] args) { + SagaOrchestrator sagaOrchestrator = new SagaOrchestrator(newSaga(), serviceDiscovery()); - Saga.Result goodOrder = sagaOrchestrator.execute("good_order"); - Saga.Result badOrder = sagaOrchestrator.execute("bad_order"); - Saga.Result crashedOrder = sagaOrchestrator.execute("crashed_order"); + Saga.Result goodOrder = sagaOrchestrator.execute("good_order"); + Saga.Result badOrder = sagaOrchestrator.execute("bad_order"); + Saga.Result crashedOrder = sagaOrchestrator.execute("crashed_order"); - logger.info("orders: goodOrder is {}, badOrder is {},crashedOrder is {}",goodOrder,badOrder,crashedOrder); - } + LOGGER.info("orders: goodOrder is {}, badOrder is {},crashedOrder is {}", goodOrder, badOrder, crashedOrder); + } - private static Saga newSaga() { - return Saga - .create() - .chapter("init an order") - .chapter("booking a Fly") - .chapter("booking a Hotel") - .chapter("withdrawing Money"); - } + private static Saga newSaga() { + return Saga + .create() + .chapter("init an order") + .chapter("booking a Fly") + .chapter("booking a Hotel") + .chapter("withdrawing Money"); + } - private static ServiceDiscoveryService serviceDiscovery() { - return - new ServiceDiscoveryService() - .discover(new OrderService()) - .discover(new FlyBookingService()) - .discover(new HotelBookingService()) - .discover(new WithdrawMoneyService()); - } + private static ServiceDiscoveryService serviceDiscovery() { + return + new ServiceDiscoveryService() + .discover(new OrderService()) + .discover(new FlyBookingService()) + .discover(new HotelBookingService()) + .discover(new WithdrawMoneyService()); + } } diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/SagaOrchestrator.java b/saga/src/main/java/com/iluwatar/saga/orchestration/SagaOrchestrator.java index c005d70df187..2f25ebd462e7 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/SagaOrchestrator.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/SagaOrchestrator.java @@ -34,107 +34,112 @@ * the participant services to execute local transactions based on events. */ public class SagaOrchestrator { - private static final Logger logger = LoggerFactory.getLogger(SagaOrchestrator.class); - private final Saga saga; - private final ServiceDiscoveryService sd; - private final CurrentState state; + private static final Logger LOGGER = LoggerFactory.getLogger(SagaOrchestrator.class); + private final Saga saga; + private final ServiceDiscoveryService sd; + private final CurrentState state; + + + /** + * Create a new service to orchetrate sagas + * @param saga saga to process + * @param sd service discovery @see {@link ServiceDiscoveryService} + */ + public SagaOrchestrator(Saga saga, ServiceDiscoveryService sd) { + this.saga = saga; + this.sd = sd; + this.state = new CurrentState(); + } + + /** + * pipeline to execute saga process/story + * + * @param value incoming value + * @param type for incoming value + * @return result @see {@link Saga.Result} + */ + @SuppressWarnings("unchecked") + public Saga.Result execute(K value) { + state.cleanUp(); + LOGGER.info(" The new saga is about to start"); + Saga.Result result = FINISHED; + K tempVal = value; + + while (true) { + int next = state.current(); + Saga.Chapter ch = saga.get(next); + Optional srvOpt = sd.find(ch.name); + + if (!srvOpt.isPresent()) { + state.directionToBack(); + state.back(); + continue; + } + + OrchestrationChapter srv = srvOpt.get(); + + if (state.isForward()) { + ChapterResult processRes = srv.process(tempVal); + if (processRes.isSuccess()) { + next = state.forward(); + tempVal = (K) processRes.getValue(); + } else { + state.directionToBack(); + } + } else { + ChapterResult rlRes = srv.rollback(tempVal); + if (rlRes.isSuccess()) { + next = state.back(); + tempVal = (K) rlRes.getValue(); + } else { + result = CRASHED; + next = state.back(); + } + } - public SagaOrchestrator(Saga saga, ServiceDiscoveryService sd) { - this.saga = saga; - this.sd = sd; - this.state = new CurrentState(); + if (!saga.isPresent(next)) { + return state.isForward() ? FINISHED : result == CRASHED ? CRASHED : ROLLBACK; + } } - /** - * pipeline to execute saga process/story - * - * @param value incoming value - * @param type for incoming value - * @return result @see {@link Saga.Result} - */ - @SuppressWarnings("unchecked") - public Saga.Result execute(K value) { - state.cleanUp(); - logger.info(" The new saga is about to start"); - Saga.Result result = FINISHED; - K tempVal = value; - - while (true) { - int next = state.current(); - Saga.Chapter ch = saga.get(next); - Optional srvOpt = sd.find(ch.name); - - if (!srvOpt.isPresent()) { - state.directionToBack(); - state.back(); - continue; - } - - Chapter srv = srvOpt.get(); - - if (state.isForward()) { - ChapterResult processRes = srv.process(tempVal); - if (processRes.isSuccess()) { - next = state.forward(); - tempVal = (K) processRes.getValue(); - } else { - state.directionToBack(); - } - } else { - ChapterResult rlRes = srv.rollback(tempVal); - if (rlRes.isSuccess()) { - next = state.back(); - tempVal = (K) rlRes.getValue(); - } else { - result = CRASHED; - next = state.back(); - } - } - - - if (!saga.isPresent(next)) { - return state.isForward() ? FINISHED : result == CRASHED ? CRASHED : ROLLBACK; - } - } - - } + } - private static class CurrentState { - int currentNumber; - boolean isForward; + private static class CurrentState { + int currentNumber; + boolean isForward; - void cleanUp() { - currentNumber = 0; - isForward = true; - } + void cleanUp() { + currentNumber = 0; + isForward = true; + } - CurrentState() { - this.currentNumber = 0; - this.isForward = true; - } + CurrentState() { + this.currentNumber = 0; + this.isForward = true; + } - boolean isForward() { - return isForward; - } + boolean isForward() { + return isForward; + } - void directionToBack() { - isForward = false; - } + void directionToBack() { + isForward = false; + } - int forward() { - return ++currentNumber; - } + int forward() { + return ++currentNumber; + } - int back() { - return --currentNumber; - } + int back() { + return --currentNumber; + } - int current() { - return currentNumber; - } + int current() { + return currentNumber; } + } } diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/Service.java b/saga/src/main/java/com/iluwatar/saga/orchestration/Service.java index 20b34f55aa95..c4ba2a9e198e 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/Service.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/Service.java @@ -27,29 +27,30 @@ /** * Common abstraction class representing services - * implementing a general contract @see {@link Chapter} + * implementing a general contract @see {@link OrchestrationChapter} + * * @param type of incoming param */ -public abstract class Service implements Chapter { - protected static final Logger logger = LoggerFactory.getLogger(Service.class); - - @Override - public abstract String getName(); - - - @Override - public ChapterResult process(K value) { - logger.info("The chapter '{}' has been started. The data {} has been stored or calculated successfully", - getName(),value); - return ChapterResult.success(value); - } - - @Override - public ChapterResult rollback(K value) { - logger.info("The Rollback for a chapter '{}' has been started. The data {} has been rollbacked successfully", - getName(),value); - return ChapterResult.success(value); - } +public abstract class Service implements OrchestrationChapter { + protected static final Logger LOGGER = LoggerFactory.getLogger(Service.class); + + @Override + public abstract String getName(); + + + @Override + public ChapterResult process(K value) { + LOGGER.info("The chapter '{}' has been started. The data {} has been stored or calculated successfully", + getName(), value); + return ChapterResult.success(value); + } + + @Override + public ChapterResult rollback(K value) { + LOGGER.info("The Rollback for a chapter '{}' has been started. The data {} has been rollbacked successfully", + getName(), value); + return ChapterResult.success(value); + } } diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/ServiceDiscoveryService.java b/saga/src/main/java/com/iluwatar/saga/orchestration/ServiceDiscoveryService.java index 652740051b5e..4831730a72db 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/ServiceDiscoveryService.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/ServiceDiscoveryService.java @@ -30,20 +30,20 @@ * The class representing a service discovery pattern. */ public class ServiceDiscoveryService { - private Map> services; + private Map> services; - public Optional find(String service) { - return Optional.ofNullable(services.getOrDefault(service, null)); - } + public Optional find(String service) { + return Optional.ofNullable(services.getOrDefault(service, null)); + } - public ServiceDiscoveryService discover(Chapter chapterService) { - services.put(chapterService.getName(), chapterService); - return this; - } + public ServiceDiscoveryService discover(OrchestrationChapter orchestrationChapterService) { + services.put(orchestrationChapterService.getName(), orchestrationChapterService); + return this; + } - public ServiceDiscoveryService() { - this.services = new HashMap<>(); - } + public ServiceDiscoveryService() { + this.services = new HashMap<>(); + } } diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/WithdrawMoneyService.java b/saga/src/main/java/com/iluwatar/saga/orchestration/WithdrawMoneyService.java index dad15cec3864..f5a0c90f3707 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/WithdrawMoneyService.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/WithdrawMoneyService.java @@ -26,19 +26,19 @@ * Class representing a service to withdraw a money */ public class WithdrawMoneyService extends Service { - @Override - public String getName() { - return "withdrawing Money"; - } + @Override + public String getName() { + return "withdrawing Money"; + } - @Override - public ChapterResult process(String value) { - if (value.equals("bad_order") || value.equals("crashed_order")) { - logger.info("The chapter '{}' has been started. But the exception has been raised." + - "The rollback is about to start", - getName(), value); - return ChapterResult.failure(value); - } - return super.process(value); + @Override + public ChapterResult process(String value) { + if (value.equals("bad_order") || value.equals("crashed_order")) { + LOGGER.info("The chapter '{}' has been started. But the exception has been raised." + + "The rollback is about to start", + getName(), value); + return ChapterResult.failure(value); } + return super.process(value); + } } diff --git a/saga/src/test/java/com/iluwatar/saga/choreography/SagaApplicationTest.java b/saga/src/test/java/com/iluwatar/saga/choreography/SagaApplicationTest.java index 5802f54ec6c5..d7a2a34b2787 100644 --- a/saga/src/test/java/com/iluwatar/saga/choreography/SagaApplicationTest.java +++ b/saga/src/test/java/com/iluwatar/saga/choreography/SagaApplicationTest.java @@ -25,11 +25,13 @@ import com.iluwatar.saga.orchestration.SagaApplication; import org.junit.Test; -import static org.junit.Assert.*; +/*** + * empty test + */ public class SagaApplicationTest { - @Test - public void mainTest() { - SagaApplication.main(new String[]{}); - } + @Test + public void mainTest() { + SagaApplication.main(new String[]{}); + } } \ No newline at end of file diff --git a/saga/src/test/java/com/iluwatar/saga/choreography/SagaChoreographyTest.java b/saga/src/test/java/com/iluwatar/saga/choreography/SagaChoreographyTest.java index 8c8daa7c991f..4300d4057780 100644 --- a/saga/src/test/java/com/iluwatar/saga/choreography/SagaChoreographyTest.java +++ b/saga/src/test/java/com/iluwatar/saga/choreography/SagaChoreographyTest.java @@ -25,35 +25,38 @@ import org.junit.Assert; import org.junit.Test; +/** + * test to check choreography saga + */ public class SagaChoreographyTest { - @Test - public void executeTest() { - ServiceDiscoveryService sd = serviceDiscovery(); - Chapter service = sd.findAny(); - Saga badOrderSaga = service.execute(newSaga("bad_order")); - Saga goodOrderSaga = service.execute(newSaga("good_order")); + @Test + public void executeTest() { + ServiceDiscoveryService sd = serviceDiscovery(); + ChoreographyChapter service = sd.findAny(); + Saga badOrderSaga = service.execute(newSaga("bad_order")); + Saga goodOrderSaga = service.execute(newSaga("good_order")); - Assert.assertEquals(badOrderSaga.getResult(), Saga.SagaResult.ROLLBACKED); - Assert.assertEquals(goodOrderSaga.getResult(), Saga.SagaResult.FINISHED); - } + Assert.assertEquals(badOrderSaga.getResult(), Saga.SagaResult.ROLLBACKED); + Assert.assertEquals(goodOrderSaga.getResult(), Saga.SagaResult.FINISHED); + } - private static Saga newSaga(Object value) { - return Saga - .create() - .chapter("init an order").setInValue(value) - .chapter("booking a Fly") - .chapter("booking a Hotel") - .chapter("withdrawing Money"); - } + private static Saga newSaga(Object value) { + return Saga + .create() + .chapter("init an order").setInValue(value) + .chapter("booking a Fly") + .chapter("booking a Hotel") + .chapter("withdrawing Money"); + } - private static ServiceDiscoveryService serviceDiscovery() { - ServiceDiscoveryService sd = new ServiceDiscoveryService(); - return sd - .discover(new OrderService(sd)) - .discover(new FlyBookingService(sd)) - .discover(new HotelBookingService(sd)) - .discover(new WithdrawMoneyService(sd)); - } + private static ServiceDiscoveryService serviceDiscovery() { + ServiceDiscoveryService sd = new ServiceDiscoveryService(); + return sd + .discover(new OrderService(sd)) + .discover(new FlyBookingService(sd)) + .discover(new HotelBookingService(sd)) + .discover(new WithdrawMoneyService(sd)); + } } diff --git a/saga/src/test/java/com/iluwatar/saga/orchestration/SagaApplicationTest.java b/saga/src/test/java/com/iluwatar/saga/orchestration/SagaApplicationTest.java index 4e4d86644b10..aa3c8773f46a 100644 --- a/saga/src/test/java/com/iluwatar/saga/orchestration/SagaApplicationTest.java +++ b/saga/src/test/java/com/iluwatar/saga/orchestration/SagaApplicationTest.java @@ -26,10 +26,13 @@ import static org.junit.Assert.*; +/** + * empty test + */ public class SagaApplicationTest { - @Test - public void mainTest() { - SagaApplication.main(new String[]{}); - } + @Test + public void mainTest() { + SagaApplication.main(new String[]{}); + } } \ No newline at end of file diff --git a/saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorInternallyTest.java b/saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorInternallyTest.java index ce3b926a3775..a93bf5280cb6 100644 --- a/saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorInternallyTest.java +++ b/saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorInternallyTest.java @@ -28,112 +28,118 @@ import java.util.ArrayList; import java.util.List; +/** + * test to test orchestration logic + */ public class SagaOrchestratorInternallyTest { - private List records = new ArrayList<>(); + private List records = new ArrayList<>(); + + @Test + public void executeTest() { + SagaOrchestrator sagaOrchestrator = new SagaOrchestrator(newSaga(), serviceDiscovery()); + Saga.Result result = sagaOrchestrator.execute(1); + Assert.assertEquals(result, Saga.Result.ROLLBACK); + Assert.assertArrayEquals( + records.toArray(new String[]{}), + new String[]{"+1", "+2", "+3", "+4", "-4", "-3", "-2", "-1"}); + } + + private static Saga newSaga() { + return Saga + .create() + .chapter("1") + .chapter("2") + .chapter("3") + .chapter("4"); + } + + private ServiceDiscoveryService serviceDiscovery() { + return + new ServiceDiscoveryService() + .discover(new Service1()) + .discover(new Service2()) + .discover(new Service3()) + .discover(new Service4()); + } + + class Service1 extends Service { + + @Override + public String getName() { + return "1"; + } + + @Override + public ChapterResult process(Integer value) { + records.add("+1"); + return ChapterResult.success(value); + } + + @Override + public ChapterResult rollback(Integer value) { + records.add("-1"); + return ChapterResult.success(value); + } + } + + class Service2 extends Service { - @Test - public void executeTest() { - SagaOrchestrator sagaOrchestrator = new SagaOrchestrator(newSaga(), serviceDiscovery()); - Saga.Result result = sagaOrchestrator.execute(1); - Assert.assertEquals(result, Saga.Result.ROLLBACK); - Assert.assertArrayEquals( - records.toArray(new String[]{}), - new String[]{"+1","+2","+3","+4","-4","-3","-2","-1"}); + @Override + public String getName() { + return "2"; } - private static Saga newSaga() { - return Saga - .create() - .chapter("1") - .chapter("2") - .chapter("3") - .chapter("4"); + @Override + public ChapterResult process(Integer value) { + records.add("+2"); + return ChapterResult.success(value); } - private ServiceDiscoveryService serviceDiscovery() { - return - new ServiceDiscoveryService() - .discover(new Service1()) - .discover(new Service2()) - .discover(new Service3()) - .discover(new Service4()); + @Override + public ChapterResult rollback(Integer value) { + records.add("-2"); + return ChapterResult.success(value); } + } - class Service1 extends Service { + class Service3 extends Service { - @Override - public String getName() { - return "1"; - } + @Override + public String getName() { + return "3"; + } - @Override - public ChapterResult process(Integer value) { - records.add("+1"); - return ChapterResult.success(value); - } + @Override + public ChapterResult process(Integer value) { + records.add("+3"); + return ChapterResult.success(value); + } - @Override - public ChapterResult rollback(Integer value) { - records.add("-1"); - return ChapterResult.success(value); - } + @Override + public ChapterResult rollback(Integer value) { + records.add("-3"); + return ChapterResult.success(value); } + } + + class Service4 extends Service { - class Service2 extends Service { - - @Override - public String getName() { - return "2"; - } - @Override - public ChapterResult process(Integer value) { - records.add("+2"); - return ChapterResult.success(value); - } - - @Override - public ChapterResult rollback(Integer value) { - records.add("-2"); - return ChapterResult.success(value); - } + @Override + public String getName() { + return "4"; } - class Service3 extends Service { - - @Override - public String getName() { - return "3"; - } - @Override - public ChapterResult process(Integer value) { - records.add("+3"); - return ChapterResult.success(value); - } - - @Override - public ChapterResult rollback(Integer value) { - records.add("-3"); - return ChapterResult.success(value); - } + @Override + public ChapterResult process(Integer value) { + records.add("+4"); + return ChapterResult.failure(value); } - class Service4 extends Service { - - @Override - public String getName() { - return "4"; - } - @Override - public ChapterResult process(Integer value) { - records.add("+4"); - return ChapterResult.failure(value); - } - - @Override - public ChapterResult rollback(Integer value) { - records.add("-4"); - return ChapterResult.success(value); - } + @Override + public ChapterResult rollback(Integer value) { + records.add("-4"); + return ChapterResult.success(value); } + } } \ No newline at end of file diff --git a/saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorTest.java b/saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorTest.java index bead0343d1b9..d3522418c346 100644 --- a/saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorTest.java +++ b/saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorTest.java @@ -25,33 +25,36 @@ import org.junit.Assert; import org.junit.Test; +/** + * test to check general logic + */ public class SagaOrchestratorTest { - @Test - public void execute() { - SagaOrchestrator sagaOrchestrator = new SagaOrchestrator(newSaga(), serviceDiscovery()); - Saga.Result badOrder = sagaOrchestrator.execute("bad_order"); - Saga.Result crashedOrder = sagaOrchestrator.execute("crashed_order"); + @Test + public void execute() { + SagaOrchestrator sagaOrchestrator = new SagaOrchestrator(newSaga(), serviceDiscovery()); + Saga.Result badOrder = sagaOrchestrator.execute("bad_order"); + Saga.Result crashedOrder = sagaOrchestrator.execute("crashed_order"); - Assert.assertEquals(badOrder, Saga.Result.ROLLBACK); - Assert.assertEquals(crashedOrder, Saga.Result.CRASHED); - } + Assert.assertEquals(badOrder, Saga.Result.ROLLBACK); + Assert.assertEquals(crashedOrder, Saga.Result.CRASHED); + } - private static Saga newSaga() { - return Saga - .create() - .chapter("init an order") - .chapter("booking a Fly") - .chapter("booking a Hotel") - .chapter("withdrawing Money"); - } + private static Saga newSaga() { + return Saga + .create() + .chapter("init an order") + .chapter("booking a Fly") + .chapter("booking a Hotel") + .chapter("withdrawing Money"); + } - private static ServiceDiscoveryService serviceDiscovery() { - return - new ServiceDiscoveryService() - .discover(new OrderService()) - .discover(new FlyBookingService()) - .discover(new HotelBookingService()) - .discover(new WithdrawMoneyService()); - } + private static ServiceDiscoveryService serviceDiscovery() { + return + new ServiceDiscoveryService() + .discover(new OrderService()) + .discover(new FlyBookingService()) + .discover(new HotelBookingService()) + .discover(new WithdrawMoneyService()); + } } \ No newline at end of file From 87af122509a4b91045a9670d317b9e5eb7d08f3b Mon Sep 17 00:00:00 2001 From: Besok Date: Wed, 13 Nov 2019 21:01:10 +0000 Subject: [PATCH 19/31] add changes according to google style --- .../choreography/ChoreographyChapter.java | 4 ++- .../saga/choreography/FlyBookingService.java | 3 ++- .../choreography/HotelBookingService.java | 3 ++- .../saga/choreography/OrderService.java | 1 + .../com/iluwatar/saga/choreography/Saga.java | 26 +++++++++--------- .../saga/choreography/SagaApplication.java | 26 ++++++++++-------- .../iluwatar/saga/choreography/Service.java | 14 ++++++---- .../choreography/ServiceDiscoveryService.java | 4 +-- .../choreography/WithdrawMoneyService.java | 4 +-- .../saga/orchestration/ChapterResult.java | 5 ++-- .../saga/orchestration/FlyBookingService.java | 3 ++- .../orchestration/HotelBookingService.java | 6 +++-- .../orchestration/OrchestrationChapter.java | 2 ++ .../saga/orchestration/OrderService.java | 1 + .../com/iluwatar/saga/orchestration/Saga.java | 5 ++-- .../saga/orchestration/SagaApplication.java | 27 +++++++++++-------- .../saga/orchestration/SagaOrchestrator.java | 13 +++++---- .../iluwatar/saga/orchestration/Service.java | 9 ++++--- .../ServiceDiscoveryService.java | 1 + .../orchestration/WithdrawMoneyService.java | 3 ++- 20 files changed, 98 insertions(+), 62 deletions(-) diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/ChoreographyChapter.java b/saga/src/main/java/com/iluwatar/saga/choreography/ChoreographyChapter.java index caa377a1e118..c79a77a9ac46 100644 --- a/saga/src/main/java/com/iluwatar/saga/choreography/ChoreographyChapter.java +++ b/saga/src/main/java/com/iluwatar/saga/choreography/ChoreographyChapter.java @@ -20,6 +20,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package com.iluwatar.saga.choreography; @@ -31,7 +32,7 @@ public interface ChoreographyChapter { /** - * In that case, every method is responsible to make a decision on what to do then + * In that case, every method is responsible to make a decision on what to do then. * * @param saga incoming saga * @return saga result @@ -39,6 +40,7 @@ public interface ChoreographyChapter { Saga execute(Saga saga); /** + * get name method. * @return service name. */ String getName(); diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/FlyBookingService.java b/saga/src/main/java/com/iluwatar/saga/choreography/FlyBookingService.java index 60b183be36f1..4a9b1e8040c0 100644 --- a/saga/src/main/java/com/iluwatar/saga/choreography/FlyBookingService.java +++ b/saga/src/main/java/com/iluwatar/saga/choreography/FlyBookingService.java @@ -20,11 +20,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package com.iluwatar.saga.choreography; /** - * Class representing a service to book a fly + * Class representing a service to book a fly. */ public class FlyBookingService extends Service { public FlyBookingService(ServiceDiscoveryService service) { diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/HotelBookingService.java b/saga/src/main/java/com/iluwatar/saga/choreography/HotelBookingService.java index 0bbf1d3e3118..ee623482e72d 100644 --- a/saga/src/main/java/com/iluwatar/saga/choreography/HotelBookingService.java +++ b/saga/src/main/java/com/iluwatar/saga/choreography/HotelBookingService.java @@ -20,11 +20,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package com.iluwatar.saga.choreography; /** - * Class representing a service to book a hotel + * Class representing a service to book a hotel. */ public class HotelBookingService extends Service { public HotelBookingService(ServiceDiscoveryService service) { diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/OrderService.java b/saga/src/main/java/com/iluwatar/saga/choreography/OrderService.java index 3a2c002b1796..19586a5a3de7 100644 --- a/saga/src/main/java/com/iluwatar/saga/choreography/OrderService.java +++ b/saga/src/main/java/com/iluwatar/saga/choreography/OrderService.java @@ -20,6 +20,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package com.iluwatar.saga.choreography; diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/Saga.java b/saga/src/main/java/com/iluwatar/saga/choreography/Saga.java index 35069b80f9db..b591adaf278a 100644 --- a/saga/src/main/java/com/iluwatar/saga/choreography/Saga.java +++ b/saga/src/main/java/com/iluwatar/saga/choreography/Saga.java @@ -20,6 +20,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package com.iluwatar.saga.choreography; import java.util.ArrayList; @@ -44,7 +45,7 @@ public static Saga create() { } /** - * get resuzlt of saga + * get resuzlt of saga. * * @return result of saga @see {@link SagaResult} */ @@ -59,7 +60,7 @@ public SagaResult getResult() { } /** - * add chapter to saga + * add chapter to saga. * @param name chapter name * @return this */ @@ -69,7 +70,7 @@ public Saga chapter(String name) { } /** - * set value to last chapter + * set value to last chapter. * @param value invalue * @return this */ @@ -82,7 +83,7 @@ public Saga setInValue(Object value) { } /** - * get value from current chapter + * get value from current chapter. * @return value */ public Object getCurrentValue() { @@ -90,7 +91,7 @@ public Object getCurrentValue() { } /** - * set value to current chapter + * set value to current chapter. * @param value to set */ public void setCurrentValue(Object value) { @@ -98,7 +99,7 @@ public void setCurrentValue(Object value) { } /** - * set status for current chapter + * set status for current chapter. * @param result to set */ public void setCurrentStatus(ChapterResult result) { @@ -143,8 +144,9 @@ boolean isCurrentSuccess() { return chapters.get(pos).isSuccess(); } - /*** - * Class presents a chapter status and incoming parameters(incoming parameter transforms to outcoming parameter) + /** + * Class presents a chapter status and incoming + * parameters(incoming parameter transforms to outcoming parameter). */ public static class Chapter { private String name; @@ -170,7 +172,7 @@ public String getName() { } /** - * set result + * set result. * @param result {@link ChapterResult} */ public void setResult(ChapterResult result) { @@ -178,7 +180,7 @@ public void setResult(ChapterResult result) { } /** - * the result for chapter is good + * the result for chapter is good. * @return true if is good otherwise bad */ public boolean isSuccess() { @@ -188,14 +190,14 @@ public boolean isSuccess() { /** - * result for chapter + * result for chapter. */ public enum ChapterResult { INIT, SUCCESS, ROLLBACK } /** - * result for saga + * result for saga. */ public enum SagaResult { PROGRESS, FINISHED, ROLLBACKED diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/SagaApplication.java b/saga/src/main/java/com/iluwatar/saga/choreography/SagaApplication.java index 3aeb8672c534..d8844c864ae4 100644 --- a/saga/src/main/java/com/iluwatar/saga/choreography/SagaApplication.java +++ b/saga/src/main/java/com/iluwatar/saga/choreography/SagaApplication.java @@ -20,25 +20,29 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package com.iluwatar.saga.choreography; +package com.iluwatar.saga.choreography; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * This pattern is used in distributed services to perform a group of operations atomically. - * This is an analog of transaction in a database but in terms of microservices architecture this is executed + * This is an analog of transaction in a database but in terms + * of microservices architecture this is executed * in a distributed environment - *

- * A saga is a sequence of local transactions in a certain context. If one transaction fails for some reason, - * the saga executes compensating transactions(rollbacks) to undo the impact of the preceding transactions. - *

- * In this approach, there are no mediators or orchestrators services. + * + *

A saga is a sequence of local transactions in a certain context. + * If one transaction fails for some reason, + * the saga executes compensating transactions(rollbacks) + * to undo the impact of the preceding transactions. + * + *

In this approach, there are no mediators or orchestrators services. * All chapters are handled and moved by services manually. - *

- * The major difference with choreography saga is an ability to handle crashed services - * (otherwise in choreography services very hard to prevent a saga if one of them has been crashed) + * + *

The major difference with choreography saga is an ability to handle crashed services + * (otherwise in choreography services very hard to prevent a saga + * if one of them has been crashed) * * @see com.iluwatar.saga.choreography.Saga * @see Service @@ -47,7 +51,7 @@ public class SagaApplication { private static final Logger LOGGER = LoggerFactory.getLogger(SagaApplication.class); /** - * main method + * main method. */ public static void main(String[] args) { ServiceDiscoveryService sd = serviceDiscovery(); diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/Service.java b/saga/src/main/java/com/iluwatar/saga/choreography/Service.java index a602b1147ba7..2e932b5288c0 100644 --- a/saga/src/main/java/com/iluwatar/saga/choreography/Service.java +++ b/saga/src/main/java/com/iluwatar/saga/choreography/Service.java @@ -20,15 +20,16 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package com.iluwatar.saga.choreography; +import java.util.function.Supplier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.function.Supplier; /** - * Common abstraction class representing services + * Common abstraction class representing services. * implementing a general contract @see {@link ChoreographyChapter} */ public abstract class Service implements ChoreographyChapter { @@ -73,13 +74,15 @@ public Saga execute(Saga saga) { } private Supplier serviceNotFoundException(String chServiceName) { - return () -> new RuntimeException(String.format("the service %s has not been found", chServiceName)); + return () -> new RuntimeException( + String.format("the service %s has not been found", chServiceName)); } @Override public Saga process(Saga saga) { Object inValue = saga.getCurrentValue(); - LOGGER.info("The chapter '{}' has been started. The data {} has been stored or calculated successfully", + LOGGER.info("The chapter '{}' has been started. " + + "The data {} has been stored or calculated successfully", getName(), inValue); saga.setCurrentStatus(Saga.ChapterResult.SUCCESS); saga.setCurrentValue(inValue); @@ -89,7 +92,8 @@ public Saga process(Saga saga) { @Override public Saga rollback(Saga saga) { Object inValue = saga.getCurrentValue(); - LOGGER.info("The Rollback for a chapter '{}' has been started. The data {} has been rollbacked successfully", + LOGGER.info("The Rollback for a chapter '{}' has been started. " + + "The data {} has been rollbacked successfully", getName(), inValue); saga.setCurrentStatus(Saga.ChapterResult.ROLLBACK); diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/ServiceDiscoveryService.java b/saga/src/main/java/com/iluwatar/saga/choreography/ServiceDiscoveryService.java index 919c99f02ede..a616ff4a53b7 100644 --- a/saga/src/main/java/com/iluwatar/saga/choreography/ServiceDiscoveryService.java +++ b/saga/src/main/java/com/iluwatar/saga/choreography/ServiceDiscoveryService.java @@ -20,8 +20,8 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package com.iluwatar.saga.choreography; +package com.iluwatar.saga.choreography; import java.util.HashMap; import java.util.Map; @@ -35,7 +35,7 @@ public class ServiceDiscoveryService { private Map services; /** - * find any service + * find any service. * * @return any service * @throws NoSuchElementException if no elements further diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/WithdrawMoneyService.java b/saga/src/main/java/com/iluwatar/saga/choreography/WithdrawMoneyService.java index b30a05e9576c..637e8ac1bbf4 100644 --- a/saga/src/main/java/com/iluwatar/saga/choreography/WithdrawMoneyService.java +++ b/saga/src/main/java/com/iluwatar/saga/choreography/WithdrawMoneyService.java @@ -20,11 +20,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package com.iluwatar.saga.choreography; +package com.iluwatar.saga.choreography; /** - * Class representing a service to withdraw a money + * Class representing a service to withdraw a money. */ public class WithdrawMoneyService extends Service { diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/ChapterResult.java b/saga/src/main/java/com/iluwatar/saga/orchestration/ChapterResult.java index a8a1e7b5e869..ef34ddb987a5 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/ChapterResult.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/ChapterResult.java @@ -20,10 +20,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package com.iluwatar.saga.orchestration; /** - * Executing result for chapter + * Executing result for chapter. * * @param incoming value */ @@ -53,7 +54,7 @@ public static ChapterResult failure(K val) { } /** - * state for chapter + * state for chapter. */ public enum State { SUCCESS, FAILURE diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/FlyBookingService.java b/saga/src/main/java/com/iluwatar/saga/orchestration/FlyBookingService.java index 5dc0577bc35d..23b612957af3 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/FlyBookingService.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/FlyBookingService.java @@ -20,10 +20,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package com.iluwatar.saga.orchestration; /** - * Class representing a service to book a fly + * Class representing a service to book a fly. */ public class FlyBookingService extends Service { @Override diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/HotelBookingService.java b/saga/src/main/java/com/iluwatar/saga/orchestration/HotelBookingService.java index 51d8d5aad8f9..2d6ba13899c3 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/HotelBookingService.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/HotelBookingService.java @@ -20,10 +20,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package com.iluwatar.saga.orchestration; /** - * Class representing a service to book a hotel + * Class representing a service to book a hotel. */ public class HotelBookingService extends Service { @Override @@ -42,7 +43,8 @@ public ChapterResult rollback(String value) { return ChapterResult.failure(value); } - LOGGER.info("The Rollback for a chapter '{}' has been started. The data {} has been rollbacked successfully", + LOGGER.info("The Rollback for a chapter '{}' has been started. " + + "The data {} has been rollbacked successfully", getName(), value); return super.rollback(value); diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/OrchestrationChapter.java b/saga/src/main/java/com/iluwatar/saga/orchestration/OrchestrationChapter.java index 861382a00ee8..7e9e3581f54d 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/OrchestrationChapter.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/OrchestrationChapter.java @@ -20,6 +20,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package com.iluwatar.saga.orchestration; /** @@ -30,6 +31,7 @@ public interface OrchestrationChapter { /** + * method get name. * @return service name. */ String getName(); diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/OrderService.java b/saga/src/main/java/com/iluwatar/saga/orchestration/OrderService.java index 32b9ce90b2c6..c42a9d7a1c6c 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/OrderService.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/OrderService.java @@ -20,6 +20,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package com.iluwatar.saga.orchestration; /** diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/Saga.java b/saga/src/main/java/com/iluwatar/saga/orchestration/Saga.java index e42b06f9a955..0d53362aa8e2 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/Saga.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/Saga.java @@ -20,6 +20,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package com.iluwatar.saga.orchestration; import java.util.ArrayList; @@ -60,14 +61,14 @@ public static Saga create() { } /** - * result for saga + * result for saga. */ public enum Result { FINISHED, ROLLBACK, CRASHED } /** - * class represents chapter name + * class represents chapter name. */ public static class Chapter { String name; diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/SagaApplication.java b/saga/src/main/java/com/iluwatar/saga/orchestration/SagaApplication.java index 6d7e9fd8d794..830f5e653cce 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/SagaApplication.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/SagaApplication.java @@ -23,23 +23,27 @@ package com.iluwatar.saga.orchestration; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * This pattern is used in distributed services to perform a group of operations atomically. - * This is an analog of transaction in a database but in terms of microservices architecture this is executed + * This pattern is used in distributed services to perform + * a group of operations atomically. + * This is an analog of transaction in a database but in terms + * of microservices architecture this is executed * in a distributed environment - *

- * A saga is a sequence of local transactions in a certain context. If one transaction fails for some reason, - * the saga executes compensating transactions(rollbacks) to undo the impact of the preceding transactions. - *

- * In this approach, there is an orchestrator @see {@link SagaOrchestrator} + * + *

A saga is a sequence of local transactions in a certain context. + * If one transaction fails for some reason, + * the saga executes compensating transactions(rollbacks) + * to undo the impact of the preceding transactions. + * + *

In this approach, there is an orchestrator @see {@link SagaOrchestrator} * that manages all the transactions and directs * the participant services to execute local transactions based on events. * The major difference with choreography saga is an ability to handle crashed services - * (otherwise in choreography services very hard to prevent a saga if one of them has been crashed) + * (otherwise in choreography services very hard to prevent a saga + * if one of them has been crashed) * * @see Saga * @see SagaOrchestrator @@ -49,7 +53,7 @@ public class SagaApplication { private static final Logger LOGGER = LoggerFactory.getLogger(SagaApplication.class); /** - * method to show common saga logic + * method to show common saga logic. */ public static void main(String[] args) { SagaOrchestrator sagaOrchestrator = new SagaOrchestrator(newSaga(), serviceDiscovery()); @@ -58,7 +62,8 @@ public static void main(String[] args) { Saga.Result badOrder = sagaOrchestrator.execute("bad_order"); Saga.Result crashedOrder = sagaOrchestrator.execute("crashed_order"); - LOGGER.info("orders: goodOrder is {}, badOrder is {},crashedOrder is {}", goodOrder, badOrder, crashedOrder); + LOGGER.info("orders: goodOrder is {}, badOrder is {},crashedOrder is {}", + goodOrder, badOrder, crashedOrder); } diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/SagaOrchestrator.java b/saga/src/main/java/com/iluwatar/saga/orchestration/SagaOrchestrator.java index 2f25ebd462e7..beec37655534 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/SagaOrchestrator.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/SagaOrchestrator.java @@ -20,14 +20,17 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package com.iluwatar.saga.orchestration; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import static com.iluwatar.saga.orchestration.Saga.Result.CRASHED; +import static com.iluwatar.saga.orchestration.Saga.Result.FINISHED; +import static com.iluwatar.saga.orchestration.Saga.Result.ROLLBACK; import java.util.Optional; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import static com.iluwatar.saga.orchestration.Saga.Result.*; /** * The orchestrator that manages all the transactions and directs @@ -41,7 +44,7 @@ public class SagaOrchestrator { /** - * Create a new service to orchetrate sagas + * Create a new service to orchetrate sagas. * @param saga saga to process * @param sd service discovery @see {@link ServiceDiscoveryService} */ @@ -52,7 +55,7 @@ public SagaOrchestrator(Saga saga, ServiceDiscoveryService sd) { } /** - * pipeline to execute saga process/story + * pipeline to execute saga process/story. * * @param value incoming value * @param type for incoming value diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/Service.java b/saga/src/main/java/com/iluwatar/saga/orchestration/Service.java index c4ba2a9e198e..d2b0652015c1 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/Service.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/Service.java @@ -20,13 +20,14 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package com.iluwatar.saga.orchestration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * Common abstraction class representing services + * Common abstraction class representing services. * implementing a general contract @see {@link OrchestrationChapter} * * @param type of incoming param @@ -40,14 +41,16 @@ public abstract class Service implements OrchestrationChapter { @Override public ChapterResult process(K value) { - LOGGER.info("The chapter '{}' has been started. The data {} has been stored or calculated successfully", + LOGGER.info("The chapter '{}' has been started. " + + "The data {} has been stored or calculated successfully", getName(), value); return ChapterResult.success(value); } @Override public ChapterResult rollback(K value) { - LOGGER.info("The Rollback for a chapter '{}' has been started. The data {} has been rollbacked successfully", + LOGGER.info("The Rollback for a chapter '{}' has been started. " + + "The data {} has been rollbacked successfully", getName(), value); return ChapterResult.success(value); } diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/ServiceDiscoveryService.java b/saga/src/main/java/com/iluwatar/saga/orchestration/ServiceDiscoveryService.java index 4831730a72db..dbc6e7eb5ac9 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/ServiceDiscoveryService.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/ServiceDiscoveryService.java @@ -20,6 +20,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package com.iluwatar.saga.orchestration; import java.util.HashMap; diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/WithdrawMoneyService.java b/saga/src/main/java/com/iluwatar/saga/orchestration/WithdrawMoneyService.java index f5a0c90f3707..7eb5634efece 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/WithdrawMoneyService.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/WithdrawMoneyService.java @@ -20,10 +20,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package com.iluwatar.saga.orchestration; /** - * Class representing a service to withdraw a money + * Class representing a service to withdraw a money. */ public class WithdrawMoneyService extends Service { @Override From df8a4e3b47fa1b5a28c8581e687455eaba892496 Mon Sep 17 00:00:00 2001 From: Martin Vandenbussche Date: Sat, 16 Nov 2019 13:24:46 +0100 Subject: [PATCH 20/31] Adding parameterized specification (Issue#1055) (#1088) * Resolution proposition to Issue#1055 (UML diagram left to do) * Deciding not to modify the UML diagram for now --- specification/README.md | 33 +++++++++- specification/etc/specification.ucls | 18 ++--- .../com/iluwatar/specification/app/App.java | 21 +++++- .../creature/AbstractCreature.java | 13 +++- .../specification/creature/Creature.java | 3 + .../specification/creature/Dragon.java | 7 +- .../specification/creature/Goblin.java | 7 +- .../specification/creature/KillerBee.java | 7 +- .../specification/creature/Octopus.java | 7 +- .../specification/creature/Shark.java | 7 +- .../specification/creature/Troll.java | 7 +- .../specification/property/Color.java | 2 +- .../iluwatar/specification/property/Mass.java | 65 +++++++++++++++++++ .../selector/MassGreaterThanSelector.java | 44 +++++++++++++ .../selector/MassSmallerThanOrEqSelector.java | 44 +++++++++++++ .../specification/creature/CreatureTest.java | 23 ++++--- .../selector/MassSelectorTest.java | 50 ++++++++++++++ 17 files changed, 328 insertions(+), 30 deletions(-) create mode 100644 specification/src/main/java/com/iluwatar/specification/property/Mass.java create mode 100644 specification/src/main/java/com/iluwatar/specification/selector/MassGreaterThanSelector.java create mode 100644 specification/src/main/java/com/iluwatar/specification/selector/MassSmallerThanOrEqSelector.java create mode 100644 specification/src/test/java/com/iluwatar/specification/selector/MassSelectorTest.java diff --git a/specification/README.md b/specification/README.md index a72e253d7e9b..bb95097e3cc7 100644 --- a/specification/README.md +++ b/specification/README.md @@ -31,7 +31,7 @@ Use the Specification pattern when Real world example -> There is a pool of different creatures and we often need to select some subset of them. We can write our search specification such as "creatures that can fly" and give it to the party that will perform the filtering. +> There is a pool of different creatures and we often need to select some subset of them. We can write our search specification such as "creatures that can fly" or "creatures heavier than 500 kilograms" and give it to the party that will perform the filtering. In Plain Words @@ -43,7 +43,8 @@ Wikipedia says **Programmatic Example** -If we look at our creature pool example from above, we have a set of creatures with certain properties. +If we look at our creature pool example from above, we have a set of creatures with certain properties.\ +Those properties can be part of a pre-defined, limited set (represented here by the enums Size, Movement and Color); but they can also be discrete (e.g. the mass of a Creature). In this case, it is more appropriate to use what we call "parameterized specification", where the property value can be given as an argument when the Creature is created, allowing for more flexibility. ```java public interface Creature { @@ -51,6 +52,7 @@ public interface Creature { Size getSize(); Movement getMovement(); Color getColor(); + Mass getMass(); } ``` @@ -60,7 +62,7 @@ And dragon implementation looks like this. public class Dragon extends AbstractCreature { public Dragon() { - super("Dragon", Size.LARGE, Movement.FLYING, Color.RED); + super("Dragon", Size.LARGE, Movement.FLYING, Color.RED, new Mass(39300.0)); } } ``` @@ -83,6 +85,24 @@ public class MovementSelector implements Predicate { } ``` +On the other hand, we selecting creatures heavier than a chosen amount, we use MassGreaterThanSelector. + +```java +public class MassGreaterThanSelector implements Predicate { + + private final Mass mass; + + public MassGreaterThanSelector(double mass) { + this.mass = new Mass(mass); + } + + @Override + public boolean test(Creature t) { + return t.getMass().greaterThan(mass); + } +} +``` + With these building blocks in place, we can perform a search for red and flying creatures like this. ```java @@ -90,6 +110,13 @@ With these building blocks in place, we can perform a search for red and flying .filter(new ColorSelector(Color.RED).and(new MovementSelector(Movement.FLYING))).collect(Collectors.toList()); ``` +But we could also use our paramterized selector like this. + +```java + List heavyCreatures = creatures.stream() + .filter(new MassGreaterThanSelector(500.0).collect(Collectors.toList()); +``` + ## Related patterns * Repository diff --git a/specification/etc/specification.ucls b/specification/etc/specification.ucls index 2edbbed0c9cd..54b08cc41d57 100644 --- a/specification/etc/specification.ucls +++ b/specification/etc/specification.ucls @@ -117,7 +117,7 @@ - + @@ -126,7 +126,7 @@ - + @@ -186,13 +186,13 @@ - - + + - - - - + + + + @@ -202,7 +202,7 @@ - + diff --git a/specification/src/main/java/com/iluwatar/specification/app/App.java b/specification/src/main/java/com/iluwatar/specification/app/App.java index 8ca7283c9216..c1ff8211e9a5 100644 --- a/specification/src/main/java/com/iluwatar/specification/app/App.java +++ b/specification/src/main/java/com/iluwatar/specification/app/App.java @@ -31,8 +31,11 @@ import com.iluwatar.specification.creature.Shark; import com.iluwatar.specification.creature.Troll; import com.iluwatar.specification.property.Color; +import com.iluwatar.specification.property.Mass; import com.iluwatar.specification.property.Movement; import com.iluwatar.specification.selector.ColorSelector; +import com.iluwatar.specification.selector.MassGreaterThanSelector; +import com.iluwatar.specification.selector.MassSmallerThanOrEqSelector; import com.iluwatar.specification.selector.MovementSelector; import java.util.List; import java.util.stream.Collectors; @@ -51,7 +54,7 @@ *

http://martinfowler.com/apsupp/spec.pdf

*/ public class App { - + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); /** @@ -61,6 +64,8 @@ public static void main(String[] args) { // initialize creatures list List creatures = List.of(new Goblin(), new Octopus(), new Dragon(), new Shark(), new Troll(), new KillerBee()); + // so-called "hard-coded" specification + LOGGER.info("Demonstrating hard-coded specification :"); // find all walking creatures LOGGER.info("Find all walking creatures"); List walkingCreatures = @@ -79,5 +84,19 @@ public static void main(String[] args) { .filter(new ColorSelector(Color.RED).and(new MovementSelector(Movement.FLYING))) .collect(Collectors.toList()); redAndFlyingCreatures.forEach(c -> LOGGER.info(c.toString())); + // so-called "parameterized" specification + LOGGER.info("Demonstrating parameterized specification :"); + // find all creatures heavier than 500kg + LOGGER.info("Find all creatures heavier than 600kg"); + List heavyCreatures = + creatures.stream().filter(new MassGreaterThanSelector(600.0)) + .collect(Collectors.toList()); + heavyCreatures.forEach(c -> LOGGER.info(c.toString())); + // find all creatures heavier than 500kg + LOGGER.info("Find all creatures lighter than or weighing exactly 500kg"); + List lightCreatures = + creatures.stream().filter(new MassSmallerThanOrEqSelector(500.0)) + .collect(Collectors.toList()); + lightCreatures.forEach(c -> LOGGER.info(c.toString())); } } diff --git a/specification/src/main/java/com/iluwatar/specification/creature/AbstractCreature.java b/specification/src/main/java/com/iluwatar/specification/creature/AbstractCreature.java index de7a41417efa..6b359d8ac2b1 100644 --- a/specification/src/main/java/com/iluwatar/specification/creature/AbstractCreature.java +++ b/specification/src/main/java/com/iluwatar/specification/creature/AbstractCreature.java @@ -24,6 +24,7 @@ package com.iluwatar.specification.creature; import com.iluwatar.specification.property.Color; +import com.iluwatar.specification.property.Mass; import com.iluwatar.specification.property.Movement; import com.iluwatar.specification.property.Size; @@ -36,20 +37,23 @@ public abstract class AbstractCreature implements Creature { private Size size; private Movement movement; private Color color; + private Mass mass; /** * Constructor. */ - public AbstractCreature(String name, Size size, Movement movement, Color color) { + public AbstractCreature(String name, Size size, Movement movement, Color color, Mass mass) { this.name = name; this.size = size; this.movement = movement; this.color = color; + this.mass = mass; } @Override public String toString() { - return String.format("%s [size=%s, movement=%s, color=%s]", name, size, movement, color); + return String.format("%s [size=%s, movement=%s, color=%s, mass=%s]", + name, size, movement, color, mass); } @Override @@ -71,4 +75,9 @@ public Movement getMovement() { public Color getColor() { return color; } + + @Override + public Mass getMass() { + return mass; + } } diff --git a/specification/src/main/java/com/iluwatar/specification/creature/Creature.java b/specification/src/main/java/com/iluwatar/specification/creature/Creature.java index 3f8ccdfdb259..2eb41a6dccf3 100644 --- a/specification/src/main/java/com/iluwatar/specification/creature/Creature.java +++ b/specification/src/main/java/com/iluwatar/specification/creature/Creature.java @@ -24,6 +24,7 @@ package com.iluwatar.specification.creature; import com.iluwatar.specification.property.Color; +import com.iluwatar.specification.property.Mass; import com.iluwatar.specification.property.Movement; import com.iluwatar.specification.property.Size; @@ -39,4 +40,6 @@ public interface Creature { Movement getMovement(); Color getColor(); + + Mass getMass(); } diff --git a/specification/src/main/java/com/iluwatar/specification/creature/Dragon.java b/specification/src/main/java/com/iluwatar/specification/creature/Dragon.java index d4f5a7f23164..937bd5497a1f 100644 --- a/specification/src/main/java/com/iluwatar/specification/creature/Dragon.java +++ b/specification/src/main/java/com/iluwatar/specification/creature/Dragon.java @@ -24,6 +24,7 @@ package com.iluwatar.specification.creature; import com.iluwatar.specification.property.Color; +import com.iluwatar.specification.property.Mass; import com.iluwatar.specification.property.Movement; import com.iluwatar.specification.property.Size; @@ -33,6 +34,10 @@ public class Dragon extends AbstractCreature { public Dragon() { - super("Dragon", Size.LARGE, Movement.FLYING, Color.RED); + this(new Mass(39300.0)); + } + + public Dragon(Mass mass) { + super("Dragon", Size.LARGE, Movement.FLYING, Color.RED, mass); } } diff --git a/specification/src/main/java/com/iluwatar/specification/creature/Goblin.java b/specification/src/main/java/com/iluwatar/specification/creature/Goblin.java index 0b145b737b87..7b173d580cd6 100644 --- a/specification/src/main/java/com/iluwatar/specification/creature/Goblin.java +++ b/specification/src/main/java/com/iluwatar/specification/creature/Goblin.java @@ -24,6 +24,7 @@ package com.iluwatar.specification.creature; import com.iluwatar.specification.property.Color; +import com.iluwatar.specification.property.Mass; import com.iluwatar.specification.property.Movement; import com.iluwatar.specification.property.Size; @@ -33,6 +34,10 @@ public class Goblin extends AbstractCreature { public Goblin() { - super("Goblin", Size.SMALL, Movement.WALKING, Color.GREEN); + this(new Mass(30.0)); + } + + public Goblin(Mass mass) { + super("Goblin", Size.SMALL, Movement.WALKING, Color.GREEN, mass); } } diff --git a/specification/src/main/java/com/iluwatar/specification/creature/KillerBee.java b/specification/src/main/java/com/iluwatar/specification/creature/KillerBee.java index 77f32c9f48ba..2b35714fc4f8 100644 --- a/specification/src/main/java/com/iluwatar/specification/creature/KillerBee.java +++ b/specification/src/main/java/com/iluwatar/specification/creature/KillerBee.java @@ -24,6 +24,7 @@ package com.iluwatar.specification.creature; import com.iluwatar.specification.property.Color; +import com.iluwatar.specification.property.Mass; import com.iluwatar.specification.property.Movement; import com.iluwatar.specification.property.Size; @@ -33,6 +34,10 @@ public class KillerBee extends AbstractCreature { public KillerBee() { - super("KillerBee", Size.SMALL, Movement.FLYING, Color.LIGHT); + this(new Mass(6.7)); + } + + public KillerBee(Mass mass) { + super("KillerBee", Size.SMALL, Movement.FLYING, Color.LIGHT, mass); } } diff --git a/specification/src/main/java/com/iluwatar/specification/creature/Octopus.java b/specification/src/main/java/com/iluwatar/specification/creature/Octopus.java index 6958f7fbd658..f516a6dc562e 100644 --- a/specification/src/main/java/com/iluwatar/specification/creature/Octopus.java +++ b/specification/src/main/java/com/iluwatar/specification/creature/Octopus.java @@ -24,6 +24,7 @@ package com.iluwatar.specification.creature; import com.iluwatar.specification.property.Color; +import com.iluwatar.specification.property.Mass; import com.iluwatar.specification.property.Movement; import com.iluwatar.specification.property.Size; @@ -33,6 +34,10 @@ public class Octopus extends AbstractCreature { public Octopus() { - super("Octopus", Size.NORMAL, Movement.SWIMMING, Color.DARK); + this(new Mass(12.0)); + } + + public Octopus(Mass mass) { + super("Octopus", Size.NORMAL, Movement.SWIMMING, Color.DARK, mass); } } diff --git a/specification/src/main/java/com/iluwatar/specification/creature/Shark.java b/specification/src/main/java/com/iluwatar/specification/creature/Shark.java index b9e161da43ee..8788e85d71bd 100644 --- a/specification/src/main/java/com/iluwatar/specification/creature/Shark.java +++ b/specification/src/main/java/com/iluwatar/specification/creature/Shark.java @@ -24,6 +24,7 @@ package com.iluwatar.specification.creature; import com.iluwatar.specification.property.Color; +import com.iluwatar.specification.property.Mass; import com.iluwatar.specification.property.Movement; import com.iluwatar.specification.property.Size; @@ -33,6 +34,10 @@ public class Shark extends AbstractCreature { public Shark() { - super("Shark", Size.NORMAL, Movement.SWIMMING, Color.LIGHT); + this(new Mass(500.0)); + } + + public Shark(Mass mass) { + super("Shark", Size.NORMAL, Movement.SWIMMING, Color.LIGHT, mass); } } diff --git a/specification/src/main/java/com/iluwatar/specification/creature/Troll.java b/specification/src/main/java/com/iluwatar/specification/creature/Troll.java index 3f416bdd1ed3..addcb94b62cd 100644 --- a/specification/src/main/java/com/iluwatar/specification/creature/Troll.java +++ b/specification/src/main/java/com/iluwatar/specification/creature/Troll.java @@ -24,6 +24,7 @@ package com.iluwatar.specification.creature; import com.iluwatar.specification.property.Color; +import com.iluwatar.specification.property.Mass; import com.iluwatar.specification.property.Movement; import com.iluwatar.specification.property.Size; @@ -33,6 +34,10 @@ public class Troll extends AbstractCreature { public Troll() { - super("Troll", Size.LARGE, Movement.WALKING, Color.DARK); + this(new Mass(4000.0)); + } + + public Troll(Mass mass) { + super("Troll", Size.LARGE, Movement.WALKING, Color.DARK, mass); } } diff --git a/specification/src/main/java/com/iluwatar/specification/property/Color.java b/specification/src/main/java/com/iluwatar/specification/property/Color.java index 00f7007ff713..6e96b5813e71 100644 --- a/specification/src/main/java/com/iluwatar/specification/property/Color.java +++ b/specification/src/main/java/com/iluwatar/specification/property/Color.java @@ -24,7 +24,7 @@ package com.iluwatar.specification.property; /** - *

Color property.

+ * Color property. */ public enum Color { diff --git a/specification/src/main/java/com/iluwatar/specification/property/Mass.java b/specification/src/main/java/com/iluwatar/specification/property/Mass.java new file mode 100644 index 000000000000..6be1edb3316f --- /dev/null +++ b/specification/src/main/java/com/iluwatar/specification/property/Mass.java @@ -0,0 +1,65 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.specification.property; + +/** Mass property. */ +public class Mass { + + private double value; + private String title; + + public Mass(double value) { + this.value = value; + this.title = value + "kg"; // Implicit call to Double.toString(value) + } + + public final boolean greaterThan(Mass other) { + return this.value > other.value; + } + + public final boolean smallerThan(Mass other) { + return this.value < other.value; + } + + public final boolean greaterThanOrEq(Mass other) { + return this.value >= other.value; + } + + public final boolean smallerThanOrEq(Mass other) { + return this.value <= other.value; + } + + @Override + public String toString() { + return title; + } + + @Override + public final boolean equals(Object obj) { + if (!(obj instanceof Mass)) { + return false; + } + return ((Mass) obj).value == this.value; + } +} diff --git a/specification/src/main/java/com/iluwatar/specification/selector/MassGreaterThanSelector.java b/specification/src/main/java/com/iluwatar/specification/selector/MassGreaterThanSelector.java new file mode 100644 index 000000000000..d613e6a08efc --- /dev/null +++ b/specification/src/main/java/com/iluwatar/specification/selector/MassGreaterThanSelector.java @@ -0,0 +1,44 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.specification.selector; + +import com.iluwatar.specification.creature.Creature; +import com.iluwatar.specification.property.Mass; +import java.util.function.Predicate; + +/** Mass selector for values greater than the parameter. */ +public class MassGreaterThanSelector implements Predicate { + + private final Mass mass; + + /** The use of a double as a parameter will spare some typing when instantiating this class. */ + public MassGreaterThanSelector(double mass) { + this.mass = new Mass(mass); + } + + @Override + public boolean test(Creature t) { + return t.getMass().greaterThan(mass); + } +} diff --git a/specification/src/main/java/com/iluwatar/specification/selector/MassSmallerThanOrEqSelector.java b/specification/src/main/java/com/iluwatar/specification/selector/MassSmallerThanOrEqSelector.java new file mode 100644 index 000000000000..8a6a9f80e2d5 --- /dev/null +++ b/specification/src/main/java/com/iluwatar/specification/selector/MassSmallerThanOrEqSelector.java @@ -0,0 +1,44 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.specification.selector; + +import com.iluwatar.specification.creature.Creature; +import com.iluwatar.specification.property.Mass; +import java.util.function.Predicate; + +/** Mass selector for values smaller or equal to the parameter. */ +public class MassSmallerThanOrEqSelector implements Predicate { + + private final Mass mass; + + /** The use of a double as a parameter will spare some typing when instantiating this class. */ + public MassSmallerThanOrEqSelector(double mass) { + this.mass = new Mass(mass); + } + + @Override + public boolean test(Creature t) { + return t.getMass().smallerThanOrEq(mass); + } +} diff --git a/specification/src/test/java/com/iluwatar/specification/creature/CreatureTest.java b/specification/src/test/java/com/iluwatar/specification/creature/CreatureTest.java index 26ff4c1ab877..ecd3de27f541 100644 --- a/specification/src/test/java/com/iluwatar/specification/creature/CreatureTest.java +++ b/specification/src/test/java/com/iluwatar/specification/creature/CreatureTest.java @@ -24,6 +24,7 @@ package com.iluwatar.specification.creature; import com.iluwatar.specification.property.Color; +import com.iluwatar.specification.property.Mass; import com.iluwatar.specification.property.Movement; import com.iluwatar.specification.property.Size; import org.junit.jupiter.params.ParameterizedTest; @@ -47,12 +48,12 @@ public class CreatureTest { */ public static Collection dataProvider() { return List.of( - new Object[]{new Dragon(), "Dragon", Size.LARGE, Movement.FLYING, Color.RED}, - new Object[]{new Goblin(), "Goblin", Size.SMALL, Movement.WALKING, Color.GREEN}, - new Object[]{new KillerBee(), "KillerBee", Size.SMALL, Movement.FLYING, Color.LIGHT}, - new Object[]{new Octopus(), "Octopus", Size.NORMAL, Movement.SWIMMING, Color.DARK}, - new Object[]{new Shark(), "Shark", Size.NORMAL, Movement.SWIMMING, Color.LIGHT}, - new Object[]{new Troll(), "Troll", Size.LARGE, Movement.WALKING, Color.DARK} + new Object[]{new Dragon(), "Dragon", Size.LARGE, Movement.FLYING, Color.RED, new Mass(39300.0)}, + new Object[]{new Goblin(), "Goblin", Size.SMALL, Movement.WALKING, Color.GREEN, new Mass(30.0)}, + new Object[]{new KillerBee(), "KillerBee", Size.SMALL, Movement.FLYING, Color.LIGHT, new Mass(6.7)}, + new Object[]{new Octopus(), "Octopus", Size.NORMAL, Movement.SWIMMING, Color.DARK, new Mass(12.0)}, + new Object[]{new Shark(), "Shark", Size.NORMAL, Movement.SWIMMING, Color.LIGHT, new Mass(500.0)}, + new Object[]{new Troll(), "Troll", Size.LARGE, Movement.WALKING, Color.DARK, new Mass(4000.0)} ); } @@ -82,11 +83,17 @@ public void testGetColor(Creature testedCreature, String name, Size size, Moveme @ParameterizedTest @MethodSource("dataProvider") - public void testToString(Creature testedCreature, String name, Size size, Movement movement, Color color) { + public void testGetMass(Creature testedCreature, String name, Size size, Movement movement, Color color, Mass mass) { + assertEquals(mass, testedCreature.getMass()); + } + + @ParameterizedTest + @MethodSource("dataProvider") + public void testToString(Creature testedCreature, String name, Size size, Movement movement, Color color, Mass mass) { final String toString = testedCreature.toString(); assertNotNull(toString); assertEquals( - String.format("%s [size=%s, movement=%s, color=%s]", name, size, movement, color), + String.format("%s [size=%s, movement=%s, color=%s, mass=%s]", name, size, movement, color, mass), toString ); } diff --git a/specification/src/test/java/com/iluwatar/specification/selector/MassSelectorTest.java b/specification/src/test/java/com/iluwatar/specification/selector/MassSelectorTest.java new file mode 100644 index 000000000000..eb2f4c5fe7ae --- /dev/null +++ b/specification/src/test/java/com/iluwatar/specification/selector/MassSelectorTest.java @@ -0,0 +1,50 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.specification.selector; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.iluwatar.specification.creature.Creature; +import com.iluwatar.specification.property.Mass; +import org.junit.jupiter.api.Test; + +public class MassSelectorTest { + + /** Verify if the mass selector gives the correct results */ + @Test + public void testMass() { + final Creature lightCreature = mock(Creature.class); + when(lightCreature.getMass()).thenReturn(new Mass(50.0)); + + final Creature heavyCreature = mock(Creature.class); + when(heavyCreature.getMass()).thenReturn(new Mass(2500.0)); + + final MassSmallerThanOrEqSelector lightSelector = new MassSmallerThanOrEqSelector(500.0); + assertTrue(lightSelector.test(lightCreature)); + assertFalse(lightSelector.test(heavyCreature)); + } +} From 3ccc9baa1a51bbab763f9fcae7cad22e2bbda8f6 Mon Sep 17 00:00:00 2001 From: Azureyjt Date: Sat, 16 Nov 2019 20:40:23 +0800 Subject: [PATCH 21/31] Game Loop Pattern (#1083) * Add game loop module * Add game loop module * Fix merge issue * Implement game loop module * Implement game loop module * Implement time based game loop * implement VariableStepGameLoop * Implement FixedStepGameLoop * Add UT * Add Unit tests * Fix checkstyle issues * Add README.md * Fix code review issues * Fix code review issues * update README.md --- game-loop/README.md | 41 +++++++ game-loop/pom.xml | 45 ++++++++ .../main/java/com/iluwatar/gameloop/App.java | 76 +++++++++++++ .../java/com/iluwatar/gameloop/Bullet.java | 44 ++++++++ .../iluwatar/gameloop/FixedStepGameLoop.java | 62 +++++++++++ .../iluwatar/gameloop/FrameBasedGameLoop.java | 53 +++++++++ .../com/iluwatar/gameloop/GameController.java | 61 ++++++++++ .../java/com/iluwatar/gameloop/GameLoop.java | 104 ++++++++++++++++++ .../com/iluwatar/gameloop/GameStatus.java | 33 ++++++ .../gameloop/VariableStepGameLoop.java | 51 +++++++++ .../java/com/iluwatar/gameloop/AppTest.java | 39 +++++++ .../gameloop/FixedStepGameLoopTest.java | 54 +++++++++ .../gameloop/FrameBasedGameLoopTest.java | 53 +++++++++ .../iluwatar/gameloop/GameControllerTest.java | 56 ++++++++++ .../com/iluwatar/gameloop/GameLoopTest.java | 71 ++++++++++++ .../gameloop/VariableStepGameLoopTest.java | 54 +++++++++ 16 files changed, 897 insertions(+) create mode 100644 game-loop/README.md create mode 100644 game-loop/pom.xml create mode 100644 game-loop/src/main/java/com/iluwatar/gameloop/App.java create mode 100644 game-loop/src/main/java/com/iluwatar/gameloop/Bullet.java create mode 100644 game-loop/src/main/java/com/iluwatar/gameloop/FixedStepGameLoop.java create mode 100644 game-loop/src/main/java/com/iluwatar/gameloop/FrameBasedGameLoop.java create mode 100644 game-loop/src/main/java/com/iluwatar/gameloop/GameController.java create mode 100644 game-loop/src/main/java/com/iluwatar/gameloop/GameLoop.java create mode 100644 game-loop/src/main/java/com/iluwatar/gameloop/GameStatus.java create mode 100644 game-loop/src/main/java/com/iluwatar/gameloop/VariableStepGameLoop.java create mode 100644 game-loop/src/test/java/com/iluwatar/gameloop/AppTest.java create mode 100644 game-loop/src/test/java/com/iluwatar/gameloop/FixedStepGameLoopTest.java create mode 100644 game-loop/src/test/java/com/iluwatar/gameloop/FrameBasedGameLoopTest.java create mode 100644 game-loop/src/test/java/com/iluwatar/gameloop/GameControllerTest.java create mode 100644 game-loop/src/test/java/com/iluwatar/gameloop/GameLoopTest.java create mode 100644 game-loop/src/test/java/com/iluwatar/gameloop/VariableStepGameLoopTest.java diff --git a/game-loop/README.md b/game-loop/README.md new file mode 100644 index 000000000000..424343271d63 --- /dev/null +++ b/game-loop/README.md @@ -0,0 +1,41 @@ + +--- +layout: pattern +title: Game Loop +folder: game-loop +permalink: /patterns/game-loop/ +categories: Other +tags: + - Java + - Difficulty-Beginner +--- + +## Intent +A game loop runs continuously during gameplay. Each turn of the loop, it processes user input without blocking, updates the game state, and renders the game. It tracks the passage of time to control the rate of gameplay. + +This pattern decouple the progression of game time from user input and processor speed. + +## Applicability +This pattern is used in every game engine. + +## Explanation +Game loop is the main process of all the game rendering threads. It drives input process, internal status update, rendering, AI and all the other processes. + +There are a lot of implementations of game loop: + +- Frame-based game loop + +Frame-based game loop is the easiest implementation. The loop always keeps spinning for the following three processes: processInput, update and render. The problem with it is you have no control over how fast the game runs. On a fast machine, that loop will spin so fast users won’t be able to see what’s going on. On a slow machine, the game will crawl. If you have a part of the game that’s content-heavy or does more AI or physics, the game will actually play slower there. + +- Variable-step game loop + +The variable-step game loop chooses a time step to advance based on how much real time passed since the last frame. The longer the frame takes, the bigger steps the game takes. It always keeps up with real time because it will take bigger and bigger steps to get there. + +- Fixed-step game loop + +For fixed-step game loop, a certain amount of real time has elapsed since the last turn of the game loop. This is how much game time need to be simulated for the game’s “now” to catch up with the player’s. + + +## Credits + +* [Game Programming Patterns - Game Loop](http://gameprogrammingpatterns.com/game-loop.html) \ No newline at end of file diff --git a/game-loop/pom.xml b/game-loop/pom.xml new file mode 100644 index 000000000000..c28ac04cd88e --- /dev/null +++ b/game-loop/pom.xml @@ -0,0 +1,45 @@ + + + + + java-design-patterns + com.iluwatar + 1.22.0-SNAPSHOT + + 4.0.0 + + game-loop + + + junit + junit + + + + + \ No newline at end of file diff --git a/game-loop/src/main/java/com/iluwatar/gameloop/App.java b/game-loop/src/main/java/com/iluwatar/gameloop/App.java new file mode 100644 index 000000000000..4d9e4c11dfde --- /dev/null +++ b/game-loop/src/main/java/com/iluwatar/gameloop/App.java @@ -0,0 +1,76 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.gameloop; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * A game loop runs continuously during gameplay. Each turn of the loop, it processes + * user input without blocking, updates the game state, and renders the game. It tracks + * the passage of time to control the rate of gameplay. + */ +public class App { + + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + + /** + * Each type of game loop will run for 2 seconds. + */ + private static final int GAME_LOOP_DURATION_TIME = 2000; + + /** + * Program entry point. + * @param args runtime arguments + */ + public static void main(String[] args) { + + try { + LOGGER.info("Start frame-based game loop:"); + var frameBasedGameLoop = new FrameBasedGameLoop(); + frameBasedGameLoop.run(); + Thread.sleep(GAME_LOOP_DURATION_TIME); + frameBasedGameLoop.stop(); + LOGGER.info("Stop frame-based game loop."); + + LOGGER.info("Start variable-step game loop:"); + var variableStepGameLoop = new VariableStepGameLoop(); + variableStepGameLoop.run(); + Thread.sleep(GAME_LOOP_DURATION_TIME); + variableStepGameLoop.stop(); + LOGGER.info("Stop variable-step game loop."); + + LOGGER.info("Start fixed-step game loop:"); + var fixedStepGameLoop = new FixedStepGameLoop(); + fixedStepGameLoop.run(); + Thread.sleep(GAME_LOOP_DURATION_TIME); + fixedStepGameLoop.stop(); + LOGGER.info("Stop variable-step game loop."); + + } catch (InterruptedException e) { + LOGGER.error(e.getMessage()); + } + } + +} diff --git a/game-loop/src/main/java/com/iluwatar/gameloop/Bullet.java b/game-loop/src/main/java/com/iluwatar/gameloop/Bullet.java new file mode 100644 index 000000000000..69b93bc74846 --- /dev/null +++ b/game-loop/src/main/java/com/iluwatar/gameloop/Bullet.java @@ -0,0 +1,44 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.gameloop; + +/** + * Bullet object class. + */ +public class Bullet { + + private float position; + + public Bullet() { + position = 0.0f; + } + + public float getPosition() { + return position; + } + + public void setPosition(float position) { + this.position = position; + } +} diff --git a/game-loop/src/main/java/com/iluwatar/gameloop/FixedStepGameLoop.java b/game-loop/src/main/java/com/iluwatar/gameloop/FixedStepGameLoop.java new file mode 100644 index 000000000000..07ad21584ea7 --- /dev/null +++ b/game-loop/src/main/java/com/iluwatar/gameloop/FixedStepGameLoop.java @@ -0,0 +1,62 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.gameloop; + +/** + * For fixed-step game loop, a certain amount of real time has elapsed since the + * last turn of the game loop. This is how much game time need to be simulated for + * the game’s “now” to catch up with the player’s. + */ +public class FixedStepGameLoop extends GameLoop { + + /** + * 20 ms per frame = 50 FPS. + */ + private static final long MS_PER_FRAME = 20; + + @Override + protected void processGameLoop() { + var previousTime = System.currentTimeMillis(); + var lag = 0L; + while (isGameRunning()) { + var currentTime = System.currentTimeMillis(); + var elapsedTime = currentTime - previousTime; + previousTime = currentTime; + lag += elapsedTime; + + processInput(); + + while (lag >= MS_PER_FRAME) { + update(); + lag -= MS_PER_FRAME; + } + + render(); + } + } + + protected void update() { + controller.moveBullet(0.5f * MS_PER_FRAME / 1000); + } +} diff --git a/game-loop/src/main/java/com/iluwatar/gameloop/FrameBasedGameLoop.java b/game-loop/src/main/java/com/iluwatar/gameloop/FrameBasedGameLoop.java new file mode 100644 index 000000000000..45c59168ffd3 --- /dev/null +++ b/game-loop/src/main/java/com/iluwatar/gameloop/FrameBasedGameLoop.java @@ -0,0 +1,53 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.gameloop; + +/** + * Frame-based game loop is the easiest implementation. The loop always keeps spinning + * for the following three processes: processInput, update and render. The problem with + * it is you have no control over how fast the game runs. On a fast machine, that loop + * will spin so fast users won’t be able to see what’s going on. On a slow machine, the + * game will crawl. If you have a part of the game that’s content-heavy or does more AI + * or physics, the game will actually play slower there. + */ +public class FrameBasedGameLoop extends GameLoop { + + @Override + protected void processGameLoop() { + while (isGameRunning()) { + processInput(); + update(); + render(); + } + } + + /** + * Each time when update() is invoked, a new frame is created, and the bullet will be + * moved 0.5f away from the current position. + */ + protected void update() { + controller.moveBullet(0.5f); + } + +} diff --git a/game-loop/src/main/java/com/iluwatar/gameloop/GameController.java b/game-loop/src/main/java/com/iluwatar/gameloop/GameController.java new file mode 100644 index 000000000000..00c65332b4ce --- /dev/null +++ b/game-loop/src/main/java/com/iluwatar/gameloop/GameController.java @@ -0,0 +1,61 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.gameloop; + +/** + * Update and render objects in the game. Here we add a Bullet object to the + * game system to show how the game loop works. + */ +public class GameController { + + protected final Bullet bullet; + + /** + * Initialize Bullet instance. + */ + public GameController() { + bullet = new Bullet(); + } + + /** + * Move bullet position by the provided offset. + * + * @param offset moving offset + */ + public void moveBullet(float offset) { + var currentPosition = bullet.getPosition(); + bullet.setPosition(currentPosition + offset); + } + + /** + * Get current position of the bullet. + * + * @return position of bullet + */ + public float getBulletPosition() { + return bullet.getPosition(); + } + +} + diff --git a/game-loop/src/main/java/com/iluwatar/gameloop/GameLoop.java b/game-loop/src/main/java/com/iluwatar/gameloop/GameLoop.java new file mode 100644 index 000000000000..47410382203e --- /dev/null +++ b/game-loop/src/main/java/com/iluwatar/gameloop/GameLoop.java @@ -0,0 +1,104 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.gameloop; + +import java.util.Random; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Abstract class for GameLoop implementation class. + */ +public abstract class GameLoop { + + protected final Logger logger = LoggerFactory.getLogger(this.getClass()); + + protected volatile GameStatus status; + + protected GameController controller; + + private Thread gameThread; + + /** + * Initialize game status to be stopped. + */ + public GameLoop() { + controller = new GameController(); + status = GameStatus.STOPPED; + } + + /** + * Run game loop. + */ + public void run() { + status = GameStatus.RUNNING; + gameThread = new Thread(() -> processGameLoop()); + gameThread.start(); + } + + /** + * Stop game loop. + */ + public void stop() { + status = GameStatus.STOPPED; + } + + /** + * Check if game is running or not. + * + * @return {@code true} if the game is running. + */ + public boolean isGameRunning() { + return status == GameStatus.RUNNING ? true : false; + } + + /** + * Handle any user input that has happened since the last call. In order to + * simulate the situation in real-life game, here we add a random time lag. + * The time lag ranges from 50 ms to 250 ms. + */ + protected void processInput() { + try { + int lag = new Random().nextInt(200) + 50; + Thread.sleep(lag); + } catch (InterruptedException e) { + logger.error(e.getMessage()); + } + } + + /** + * Render game frames to screen. Here we print bullet position to simulate + * this process. + */ + protected void render() { + var position = controller.getBulletPosition(); + logger.info("Current bullet position: " + position); + } + + /** + * execute game loop logic. + */ + protected abstract void processGameLoop(); + +} diff --git a/game-loop/src/main/java/com/iluwatar/gameloop/GameStatus.java b/game-loop/src/main/java/com/iluwatar/gameloop/GameStatus.java new file mode 100644 index 000000000000..46d90669e498 --- /dev/null +++ b/game-loop/src/main/java/com/iluwatar/gameloop/GameStatus.java @@ -0,0 +1,33 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.gameloop; + +/** + * Enum class for game status. + */ +public enum GameStatus { + + RUNNING, STOPPED + +} diff --git a/game-loop/src/main/java/com/iluwatar/gameloop/VariableStepGameLoop.java b/game-loop/src/main/java/com/iluwatar/gameloop/VariableStepGameLoop.java new file mode 100644 index 000000000000..544590c5bd98 --- /dev/null +++ b/game-loop/src/main/java/com/iluwatar/gameloop/VariableStepGameLoop.java @@ -0,0 +1,51 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.gameloop; + +/** + * The variable-step game loop chooses a time step to advance based on how much + * real time passed since the last frame. The longer the frame takes, the bigger + * steps the game takes. It always keeps up with real time because it will take + * bigger and bigger steps to get there. + */ +public class VariableStepGameLoop extends GameLoop { + + @Override + protected void processGameLoop() { + var lastFrameTime = System.currentTimeMillis(); + while (isGameRunning()) { + processInput(); + var currentFrameTime = System.currentTimeMillis(); + var elapsedTime = currentFrameTime - lastFrameTime; + update(elapsedTime); + lastFrameTime = currentFrameTime; + render(); + } + } + + protected void update(Long elapsedTime) { + controller.moveBullet(0.5f * elapsedTime / 1000); + } + +} diff --git a/game-loop/src/test/java/com/iluwatar/gameloop/AppTest.java b/game-loop/src/test/java/com/iluwatar/gameloop/AppTest.java new file mode 100644 index 000000000000..187fe1537c97 --- /dev/null +++ b/game-loop/src/test/java/com/iluwatar/gameloop/AppTest.java @@ -0,0 +1,39 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.gameloop; + +import org.junit.Test; + +/** + * App unit test class. + */ +public class AppTest { + + @Test + public void testMain() { + String[] args = {}; + new App().main(args); + } + +} diff --git a/game-loop/src/test/java/com/iluwatar/gameloop/FixedStepGameLoopTest.java b/game-loop/src/test/java/com/iluwatar/gameloop/FixedStepGameLoopTest.java new file mode 100644 index 000000000000..5c8614fa1318 --- /dev/null +++ b/game-loop/src/test/java/com/iluwatar/gameloop/FixedStepGameLoopTest.java @@ -0,0 +1,54 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.gameloop; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * FixedStepGameLoop unit test class. + */ +public class FixedStepGameLoopTest { + + private FixedStepGameLoop gameLoop; + + @Before + public void setup() { + gameLoop = new FixedStepGameLoop(); + } + + @After + public void tearDown() { + gameLoop = null; + } + + @Test + public void testUpdate() { + gameLoop.update(); + Assert.assertEquals(0.01f, gameLoop.controller.getBulletPosition(), 0); + } + +} diff --git a/game-loop/src/test/java/com/iluwatar/gameloop/FrameBasedGameLoopTest.java b/game-loop/src/test/java/com/iluwatar/gameloop/FrameBasedGameLoopTest.java new file mode 100644 index 000000000000..e8eb922dcd3d --- /dev/null +++ b/game-loop/src/test/java/com/iluwatar/gameloop/FrameBasedGameLoopTest.java @@ -0,0 +1,53 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.gameloop; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * FrameBasedGameLoop unit test class. + */ +public class FrameBasedGameLoopTest { + + private FrameBasedGameLoop gameLoop; + + @Before + public void setup() { + gameLoop = new FrameBasedGameLoop(); + } + + @After + public void tearDown() { + gameLoop = null; + } + + @Test + public void testUpdate() { + gameLoop.update(); + Assert.assertEquals(0.5f, gameLoop.controller.getBulletPosition(), 0); + } +} diff --git a/game-loop/src/test/java/com/iluwatar/gameloop/GameControllerTest.java b/game-loop/src/test/java/com/iluwatar/gameloop/GameControllerTest.java new file mode 100644 index 000000000000..3d057d830440 --- /dev/null +++ b/game-loop/src/test/java/com/iluwatar/gameloop/GameControllerTest.java @@ -0,0 +1,56 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.gameloop; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class GameControllerTest { + + private GameController controller; + + @Before + public void setup() { + controller = new GameController(); + } + + @After + public void tearDown() { + controller = null; + } + + @Test + public void testMoveBullet() { + controller.moveBullet(1.5f); + Assert.assertEquals(1.5f, controller.bullet.getPosition(), 0); + } + + @Test + public void testGetBulletPosition() { + Assert.assertEquals(controller.bullet.getPosition(), controller.getBulletPosition(), 0); + } + +} diff --git a/game-loop/src/test/java/com/iluwatar/gameloop/GameLoopTest.java b/game-loop/src/test/java/com/iluwatar/gameloop/GameLoopTest.java new file mode 100644 index 000000000000..61e2a3bb6ce0 --- /dev/null +++ b/game-loop/src/test/java/com/iluwatar/gameloop/GameLoopTest.java @@ -0,0 +1,71 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.gameloop; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * GameLoop unit test class. + */ +public class GameLoopTest { + + private GameLoop gameLoop; + + /** + * Create mock implementation of GameLoop. + */ + @Before + public void setup() { + gameLoop = new GameLoop() { + @Override + protected void processGameLoop() {} + }; + } + + @After + public void tearDown() { + gameLoop = null; + } + + @Test + public void testRun() { + gameLoop.run(); + Assert.assertEquals(GameStatus.RUNNING, gameLoop.status); + } + + @Test + public void testStop() { + gameLoop.stop(); + Assert.assertEquals(GameStatus.STOPPED, gameLoop.status); + } + + @Test + public void testIsGameRunning() { + Assert.assertEquals(false, gameLoop.isGameRunning()); + } + +} diff --git a/game-loop/src/test/java/com/iluwatar/gameloop/VariableStepGameLoopTest.java b/game-loop/src/test/java/com/iluwatar/gameloop/VariableStepGameLoopTest.java new file mode 100644 index 000000000000..43dd4f732426 --- /dev/null +++ b/game-loop/src/test/java/com/iluwatar/gameloop/VariableStepGameLoopTest.java @@ -0,0 +1,54 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.gameloop; + +import java.lang.reflect.InvocationTargetException; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * VariableStepGameLoop unit test class. + */ +public class VariableStepGameLoopTest { + + private VariableStepGameLoop gameLoop; + + @Before + public void setup() { + gameLoop = new VariableStepGameLoop(); + } + + @After + public void tearDown() { + gameLoop = null; + } + + @Test + public void testUpdate() { + gameLoop.update(20L); + Assert.assertEquals(0.01f, gameLoop.controller.getBulletPosition(), 0); + } +} From 1fdc65054598638e94e2a351873c7e63e95ed4fc Mon Sep 17 00:00:00 2001 From: Anurag Agarwal Date: Sat, 16 Nov 2019 18:18:23 +0530 Subject: [PATCH 22/31] Resolves checkstyle errors for remaining m (#1090) * Reduces checkstyle errors in marker * Reduces checkstyle errors in master-worker-pattern * Reduces checkstyle errors in mediator * Reduces checkstyle errors in memento * Reduces checkstyle errors in model-view-controller * Reduces checkstyle errors in model-view-presenter * Reduces checkstyle errors in module * Reduces checkstyle errors in monad * Reduces checkstyle errors in monostate * Reduces checkstyle errors in multiton * Reduces checkstyle errors in mute-idiom * Reduces checkstyle errors in mutex --- marker/src/main/java/App.java | 30 ++++++------- marker/src/main/java/Guard.java | 2 +- marker/src/main/java/Permission.java | 3 +- marker/src/main/java/Thief.java | 2 +- .../java/com/iluwatar/masterworker/App.java | 45 +++++++++++-------- .../com/iluwatar/masterworker/ArrayInput.java | 9 ++-- .../iluwatar/masterworker/ArrayResult.java | 3 +- .../masterworker/ArrayUtilityMethods.java | 32 ++++++------- .../java/com/iluwatar/masterworker/Input.java | 11 ++--- .../com/iluwatar/masterworker/Result.java | 6 +-- .../system/ArrayTransposeMasterWorker.java | 4 +- .../masterworker/system/MasterWorker.java | 2 +- .../systemmaster/ArrayTransposeMaster.java | 28 ++++++------ .../system/systemmaster/Master.java | 37 ++++++++------- .../systemworkers/ArrayTransposeWorker.java | 16 ++++--- .../system/systemworkers/Worker.java | 7 ++- .../java/com/iluwatar/mediator/Action.java | 10 ++--- .../main/java/com/iluwatar/mediator/App.java | 25 +++++------ .../java/com/iluwatar/mediator/Hobbit.java | 2 - .../java/com/iluwatar/mediator/Hunter.java | 2 - .../java/com/iluwatar/mediator/Party.java | 2 - .../java/com/iluwatar/mediator/PartyImpl.java | 2 - .../com/iluwatar/mediator/PartyMember.java | 2 - .../iluwatar/mediator/PartyMemberBase.java | 2 - .../java/com/iluwatar/mediator/Rogue.java | 2 - .../java/com/iluwatar/mediator/Wizard.java | 2 - .../main/java/com/iluwatar/memento/App.java | 29 ++++++------ .../main/java/com/iluwatar/memento/Star.java | 10 ++--- .../com/iluwatar/memento/StarMemento.java | 2 - .../java/com/iluwatar/memento/StarType.java | 4 +- .../iluwatar/model/view/controller/App.java | 26 +++++------ .../model/view/controller/Fatigue.java | 4 +- .../view/controller/GiantController.java | 2 - .../model/view/controller/GiantModel.java | 4 +- .../model/view/controller/GiantView.java | 4 +- .../model/view/controller/Health.java | 4 +- .../model/view/controller/Nourishment.java | 4 +- .../iluwatar/model/view/presenter/App.java | 32 +++++++------ .../model/view/presenter/FileLoader.java | 17 ++++--- .../view/presenter/FileSelectorJFrame.java | 3 +- .../view/presenter/FileSelectorPresenter.java | 14 +++--- .../view/presenter/FileSelectorStub.java | 14 +++--- .../view/presenter/FileSelectorView.java | 14 ++++-- .../main/java/com/iluwatar/module/App.java | 21 +++++---- .../iluwatar/module/ConsoleLoggerModule.java | 30 ++++++------- .../com/iluwatar/module/FileLoggerModule.java | 36 +++++++-------- .../src/main/java/com/iluwatar/monad/App.java | 28 ++++++------ .../src/main/java/com/iluwatar/monad/Sex.java | 2 +- .../main/java/com/iluwatar/monad/User.java | 4 +- .../java/com/iluwatar/monad/Validator.java | 41 +++++++++-------- .../main/java/com/iluwatar/monostate/App.java | 16 +++---- .../com/iluwatar/monostate/LoadBalancer.java | 9 ++-- .../java/com/iluwatar/monostate/Request.java | 2 - .../java/com/iluwatar/monostate/Server.java | 6 +-- .../main/java/com/iluwatar/multiton/App.java | 20 ++++----- .../java/com/iluwatar/multiton/Nazgul.java | 2 - .../com/iluwatar/multiton/NazgulEnum.java | 5 +-- .../com/iluwatar/multiton/NazgulName.java | 2 - .../src/main/java/com/iluwatar/mute/App.java | 21 ++++----- .../com/iluwatar/mute/CheckedRunnable.java | 2 +- .../src/main/java/com/iluwatar/mute/Mute.java | 27 +++++------ .../main/java/com/iluwatar/mute/Resource.java | 5 +-- .../src/main/java/com/iluwatar/mutex/App.java | 16 +++---- .../src/main/java/com/iluwatar/mutex/Jar.java | 5 +-- .../main/java/com/iluwatar/mutex/Mutex.java | 9 ++-- .../main/java/com/iluwatar/mutex/Thief.java | 13 +++--- 66 files changed, 374 insertions(+), 423 deletions(-) diff --git a/marker/src/main/java/App.java b/marker/src/main/java/App.java index 93697e6ebf40..384c999dc52d 100644 --- a/marker/src/main/java/App.java +++ b/marker/src/main/java/App.java @@ -25,27 +25,23 @@ import org.slf4j.LoggerFactory; /** - * Created by Alexis on 28-Apr-17. - * With Marker interface idea is to make empty interface and extend it. - * Basically it is just to identify the special objects from normal objects. - * Like in case of serialization , objects that need to be serialized must implement serializable interface - * (it is empty interface) and down the line writeObject() method must be checking - * if it is a instance of serializable or not. - *

- * Marker interface vs annotation - * Marker interfaces and marker annotations both have their uses, - * neither of them is obsolete or always better then the other one. - * If you want to define a type that does not have any new methods associated with it, - * a marker interface is the way to go. - * If you want to mark program elements other than classes and interfaces, - * to allow for the possibility of adding more information to the marker in the future, - * or to fit the marker into a framework that already makes heavy use of annotation types, - * then a marker annotation is the correct choice + * Created by Alexis on 28-Apr-17. With Marker interface idea is to make empty interface and extend + * it. Basically it is just to identify the special objects from normal objects. Like in case of + * serialization , objects that need to be serialized must implement serializable interface (it is + * empty interface) and down the line writeObject() method must be checking if it is a instance of + * serializable or not. + * + *

Marker interface vs annotation Marker interfaces and marker annotations both have their uses, + * neither of them is obsolete or always better then the other one. If you want to define a type + * that does not have any new methods associated with it, a marker interface is the way to go. If + * you want to mark program elements other than classes and interfaces, to allow for the possibility + * of adding more information to the marker in the future, or to fit the marker into a framework + * that already makes heavy use of annotation types, then a marker annotation is the correct choice */ public class App { /** - * Program entry point + * Program entry point. * * @param args command line args */ diff --git a/marker/src/main/java/Guard.java b/marker/src/main/java/Guard.java index d135d54598f4..9a57e15fdfb3 100644 --- a/marker/src/main/java/Guard.java +++ b/marker/src/main/java/Guard.java @@ -25,7 +25,7 @@ import org.slf4j.LoggerFactory; /** - * Class defining Guard + * Class defining Guard. */ public class Guard implements Permission { diff --git a/marker/src/main/java/Permission.java b/marker/src/main/java/Permission.java index e1b45e99f7f4..5395ccadf9a1 100644 --- a/marker/src/main/java/Permission.java +++ b/marker/src/main/java/Permission.java @@ -22,8 +22,7 @@ */ /** - * Interface without any methods - * Marker interface is based on that assumption + * Interface without any methods Marker interface is based on that assumption. */ public interface Permission { } diff --git a/marker/src/main/java/Thief.java b/marker/src/main/java/Thief.java index 155a974c19d3..341eae3777d9 100644 --- a/marker/src/main/java/Thief.java +++ b/marker/src/main/java/Thief.java @@ -25,7 +25,7 @@ import org.slf4j.LoggerFactory; /** - * Class defining Thief + * Class defining Thief. */ public class Thief { diff --git a/master-worker-pattern/src/main/java/com/iluwatar/masterworker/App.java b/master-worker-pattern/src/main/java/com/iluwatar/masterworker/App.java index e3ffd08c4d44..b8036b91199a 100644 --- a/master-worker-pattern/src/main/java/com/iluwatar/masterworker/App.java +++ b/master-worker-pattern/src/main/java/com/iluwatar/masterworker/App.java @@ -28,30 +28,37 @@ import org.slf4j.LoggerFactory; /** - *

The Master-Worker pattern is used when the problem at hand can be solved by dividing into - * multiple parts which need to go through the same computation and may need to be aggregated to get final result. - * Parallel processing is performed using a system consisting of a master and some number of workers, where a - * master divides the work among the workers, gets the result back from them and assimilates all the results to - * give final result. The only communication is between the master and the worker - none of the workers communicate - * among one another and the user only communicates with the master to get required job done.

- *

In our example, we have generic abstract classes {@link MasterWorker}, {@link Master} and {@link Worker} which - * have to be extended by the classes which will perform the specific job at hand (in this case finding transpose of - * matrix, done by {@link ArrayTransposeMasterWorker}, {@link ArrayTransposeMaster} and {@link ArrayTransposeWorker}). - * The Master class divides the work into parts to be given to the workers, collects the results from the workers and - * aggregates it when all workers have responded before returning the solution. The Worker class extends the Thread - * class to enable parallel processing, and does the work once the data has been received from the Master. The - * MasterWorker contains a reference to the Master class, gets the input from the App and passes it on to the Master. - * These 3 classes define the system which computes the result. We also have 2 abstract classes {@link Input} and - * {@link Result}, which contain the input data and result data respectively. The Input class also has an abstract - * method divideData which defines how the data is to be divided into segments. These classes are extended by - * {@link ArrayInput} and {@link ArrayResult}.

+ *

The Master-Worker pattern is used when the problem at hand can be solved by + * dividing into + * multiple parts which need to go through the same computation and may need to be aggregated to get + * final result. Parallel processing is performed using a system consisting of a master and some + * number of workers, where a master divides the work among the workers, gets the result back from + * them and assimilates all the results to give final result. The only communication is between the + * master and the worker - none of the workers communicate among one another and the user only + * communicates with the master to get required job done.

+ *

In our example, we have generic abstract classes {@link MasterWorker}, {@link Master} and + * {@link Worker} which + * have to be extended by the classes which will perform the specific job at hand (in this case + * finding transpose of matrix, done by {@link ArrayTransposeMasterWorker}, {@link + * ArrayTransposeMaster} and {@link ArrayTransposeWorker}). The Master class divides the work into + * parts to be given to the workers, collects the results from the workers and aggregates it when + * all workers have responded before returning the solution. The Worker class extends the Thread + * class to enable parallel processing, and does the work once the data has been received from the + * Master. The MasterWorker contains a reference to the Master class, gets the input from the App + * and passes it on to the Master. These 3 classes define the system which computes the result. We + * also have 2 abstract classes {@link Input} and {@link Result}, which contain the input data and + * result data respectively. The Input class also has an abstract method divideData which defines + * how the data is to be divided into segments. These classes are extended by {@link ArrayInput} and + * {@link ArrayResult}.

*/ public class App { private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point. + * * @param args command line args */ @@ -59,9 +66,9 @@ public static void main(String[] args) { ArrayTransposeMasterWorker mw = new ArrayTransposeMasterWorker(); int rows = 10; int columns = 20; - int[][] inputMatrix = ArrayUtilityMethods.createRandomIntMatrix(rows,columns); + int[][] inputMatrix = ArrayUtilityMethods.createRandomIntMatrix(rows, columns); ArrayInput input = new ArrayInput(inputMatrix); - ArrayResult result = (ArrayResult) mw.getResult(input); + ArrayResult result = (ArrayResult) mw.getResult(input); if (result != null) { ArrayUtilityMethods.printMatrix(inputMatrix); ArrayUtilityMethods.printMatrix(result.data); diff --git a/master-worker-pattern/src/main/java/com/iluwatar/masterworker/ArrayInput.java b/master-worker-pattern/src/main/java/com/iluwatar/masterworker/ArrayInput.java index df2d691b26eb..cd03a0a21895 100644 --- a/master-worker-pattern/src/main/java/com/iluwatar/masterworker/ArrayInput.java +++ b/master-worker-pattern/src/main/java/com/iluwatar/masterworker/ArrayInput.java @@ -27,8 +27,7 @@ import java.util.Arrays; /** - *Class ArrayInput extends abstract class {@link Input} and contains data - *of type int[][]. + * Class ArrayInput extends abstract class {@link Input} and contains data of type int[][]. */ public class ArrayInput extends Input { @@ -36,7 +35,7 @@ public class ArrayInput extends Input { public ArrayInput(int[][] data) { super(data); } - + static int[] makeDivisions(int[][] data, int num) { int initialDivision = data.length / num; //equally dividing int[] divisions = new int[num]; @@ -81,6 +80,6 @@ public ArrayList divideData(int num) { } } return result; - } - } + } + } } diff --git a/master-worker-pattern/src/main/java/com/iluwatar/masterworker/ArrayResult.java b/master-worker-pattern/src/main/java/com/iluwatar/masterworker/ArrayResult.java index dbe4f7477c12..a26472e80445 100644 --- a/master-worker-pattern/src/main/java/com/iluwatar/masterworker/ArrayResult.java +++ b/master-worker-pattern/src/main/java/com/iluwatar/masterworker/ArrayResult.java @@ -24,8 +24,7 @@ package com.iluwatar.masterworker; /** - *Class ArrayResult extends abstract class {@link Result} and contains data - *of type int[][]. + * Class ArrayResult extends abstract class {@link Result} and contains data of type int[][]. */ public class ArrayResult extends Result { diff --git a/master-worker-pattern/src/main/java/com/iluwatar/masterworker/ArrayUtilityMethods.java b/master-worker-pattern/src/main/java/com/iluwatar/masterworker/ArrayUtilityMethods.java index 04db66492a13..525bed003e70 100644 --- a/master-worker-pattern/src/main/java/com/iluwatar/masterworker/ArrayUtilityMethods.java +++ b/master-worker-pattern/src/main/java/com/iluwatar/masterworker/ArrayUtilityMethods.java @@ -23,23 +23,23 @@ package com.iluwatar.masterworker; +import java.util.Random; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Random; - /** - *Class ArrayUtilityMethods has some utility methods for matrices and arrays. + * Class ArrayUtilityMethods has some utility methods for matrices and arrays. */ public class ArrayUtilityMethods { private static final Logger LOGGER = LoggerFactory.getLogger(ArrayUtilityMethods.class); - + private static final Random RANDOM = new Random(); + /** - * Method arraysSame compares 2 arrays @param a1 and @param a2 - * and @return whether their values are equal (boolean). + * Method arraysSame compares 2 arrays @param a1 and @param a2 and @return whether their values + * are equal (boolean). */ public static boolean arraysSame(int[] a1, int[] a2) { @@ -61,10 +61,10 @@ public static boolean arraysSame(int[] a1, int[] a2) { } /** - * Method matricesSame compares 2 matrices @param m1 and @param m2 - * and @return whether their values are equal (boolean). + * Method matricesSame compares 2 matrices @param m1 and @param m2 and @return whether their + * values are equal (boolean). */ - + public static boolean matricesSame(int[][] m1, int[][] m2) { if (m1.length != m2.length) { return false; @@ -81,12 +81,12 @@ public static boolean matricesSame(int[][] m1, int[][] m2) { return answer; } } - + /** - * Method createRandomIntMatrix creates a random matrix of size @param rows - * and @param columns @return it (int[][]). + * Method createRandomIntMatrix creates a random matrix of size @param rows and @param columns. + * + * @return it (int[][]). */ - public static int[][] createRandomIntMatrix(int rows, int columns) { int[][] matrix = new int[rows][columns]; for (int i = 0; i < rows; i++) { @@ -97,11 +97,11 @@ public static int[][] createRandomIntMatrix(int rows, int columns) { } return matrix; } - + /** * Method printMatrix prints input matrix @param matrix. */ - + public static void printMatrix(int[][] matrix) { //prints out int[][] for (int i = 0; i < matrix.length; i++) { @@ -111,5 +111,5 @@ public static void printMatrix(int[][] matrix) { LOGGER.info(""); } } - + } diff --git a/master-worker-pattern/src/main/java/com/iluwatar/masterworker/Input.java b/master-worker-pattern/src/main/java/com/iluwatar/masterworker/Input.java index d0d0c2ddeac4..6a957ae804c3 100644 --- a/master-worker-pattern/src/main/java/com/iluwatar/masterworker/Input.java +++ b/master-worker-pattern/src/main/java/com/iluwatar/masterworker/Input.java @@ -26,18 +26,19 @@ import java.util.ArrayList; /** - *The abstract Input class, having 1 public field which contains input data, - *and abstract method divideData. + * The abstract Input class, having 1 public field which contains input data, and abstract method + * divideData. + * * @param T will be type of data. */ public abstract class Input { - + public final T data; - + public Input(T data) { this.data = data; } - + public abstract ArrayList divideData(int num); } diff --git a/master-worker-pattern/src/main/java/com/iluwatar/masterworker/Result.java b/master-worker-pattern/src/main/java/com/iluwatar/masterworker/Result.java index 1bc729aa9228..79bc14604012 100644 --- a/master-worker-pattern/src/main/java/com/iluwatar/masterworker/Result.java +++ b/master-worker-pattern/src/main/java/com/iluwatar/masterworker/Result.java @@ -24,13 +24,13 @@ package com.iluwatar.masterworker; /** - *The abstract Result class, which contains 1 public field containing result - *data. + * The abstract Result class, which contains 1 public field containing result data. + * * @param T will be type of data. */ public abstract class Result { - + public final T data; public Result(T data) { diff --git a/master-worker-pattern/src/main/java/com/iluwatar/masterworker/system/ArrayTransposeMasterWorker.java b/master-worker-pattern/src/main/java/com/iluwatar/masterworker/system/ArrayTransposeMasterWorker.java index 76e9ff35ab08..86c1a5700d95 100644 --- a/master-worker-pattern/src/main/java/com/iluwatar/masterworker/system/ArrayTransposeMasterWorker.java +++ b/master-worker-pattern/src/main/java/com/iluwatar/masterworker/system/ArrayTransposeMasterWorker.java @@ -27,8 +27,8 @@ import com.iluwatar.masterworker.system.systemmaster.Master; /** - *Class ArrayTransposeMasterWorker extends abstract class {@link MasterWorker} and - *specifically solves the problem of finding transpose of input array. + * Class ArrayTransposeMasterWorker extends abstract class {@link MasterWorker} and specifically + * solves the problem of finding transpose of input array. */ public class ArrayTransposeMasterWorker extends MasterWorker { diff --git a/master-worker-pattern/src/main/java/com/iluwatar/masterworker/system/MasterWorker.java b/master-worker-pattern/src/main/java/com/iluwatar/masterworker/system/MasterWorker.java index 009faf106536..2b16cbf7628f 100644 --- a/master-worker-pattern/src/main/java/com/iluwatar/masterworker/system/MasterWorker.java +++ b/master-worker-pattern/src/main/java/com/iluwatar/masterworker/system/MasterWorker.java @@ -28,7 +28,7 @@ import com.iluwatar.masterworker.system.systemmaster.Master; /** - *The abstract MasterWorker class which contains reference to master. + * The abstract MasterWorker class which contains reference to master. */ public abstract class MasterWorker { diff --git a/master-worker-pattern/src/main/java/com/iluwatar/masterworker/system/systemmaster/ArrayTransposeMaster.java b/master-worker-pattern/src/main/java/com/iluwatar/masterworker/system/systemmaster/ArrayTransposeMaster.java index 0a3ab79b7cc1..ffa64572ce64 100644 --- a/master-worker-pattern/src/main/java/com/iluwatar/masterworker/system/systemmaster/ArrayTransposeMaster.java +++ b/master-worker-pattern/src/main/java/com/iluwatar/masterworker/system/systemmaster/ArrayTransposeMaster.java @@ -23,16 +23,15 @@ package com.iluwatar.masterworker.system.systemmaster; -import java.util.ArrayList; -import java.util.Enumeration; import com.iluwatar.masterworker.ArrayResult; import com.iluwatar.masterworker.system.systemworkers.ArrayTransposeWorker; import com.iluwatar.masterworker.system.systemworkers.Worker; +import java.util.ArrayList; +import java.util.Enumeration; /** - *Class ArrayTransposeMaster extends abstract class {@link Master} and contains - *definition of aggregateData, which will obtain final result from all - *data obtained and for setWorkers. + * Class ArrayTransposeMaster extends abstract class {@link Master} and contains definition of + * aggregateData, which will obtain final result from all data obtained and for setWorkers. */ public class ArrayTransposeMaster extends Master { @@ -43,26 +42,29 @@ public ArrayTransposeMaster(int numOfWorkers) { @Override ArrayList setWorkers(int num) { ArrayList ws = new ArrayList(num); - for (int i = 0; i < num ; i++) { + for (int i = 0; i < num; i++) { ws.add(new ArrayTransposeWorker(this, i + 1)); //i+1 will be id } return ws; } - + @Override ArrayResult aggregateData() { - //number of rows in final result is number of rows in any of obtained results obtained from workers - int rows = ((ArrayResult) this.getAllResultData().get(this.getAllResultData().keys().nextElement())).data.length; - int columns = 0; //number of columns is sum of number of columns in all results obtained from workers - for (Enumeration e = this.getAllResultData().keys(); e.hasMoreElements();) { + // number of rows in final result is number of rows in any of obtained results from workers + int rows = ((ArrayResult) this.getAllResultData() + .get(this.getAllResultData().keys().nextElement())).data.length; + int columns = + 0; //number of columns is sum of number of columns in all results obtained from workers + for (Enumeration e = this.getAllResultData().keys(); e.hasMoreElements(); ) { columns += ((ArrayResult) this.getAllResultData().get(e.nextElement())).data[0].length; } int[][] resultData = new int[rows][columns]; int columnsDone = 0; //columns aggregated so far for (int i = 0; i < this.getExpectedNumResults(); i++) { //result obtained from ith worker - int[][] work = ((ArrayResult) this.getAllResultData().get(this.getWorkers().get(i).getWorkerId())).data; + int[][] work = + ((ArrayResult) this.getAllResultData().get(this.getWorkers().get(i).getWorkerId())).data; for (int m = 0; m < work.length; m++) { //m = row number, n = columns number for (int n = 0; n < work[0].length; n++) { @@ -73,5 +75,5 @@ ArrayResult aggregateData() { } return new ArrayResult(resultData); } - + } diff --git a/master-worker-pattern/src/main/java/com/iluwatar/masterworker/system/systemmaster/Master.java b/master-worker-pattern/src/main/java/com/iluwatar/masterworker/system/systemmaster/Master.java index 7e7d796eb718..2466df256f0c 100644 --- a/master-worker-pattern/src/main/java/com/iluwatar/masterworker/system/systemmaster/Master.java +++ b/master-worker-pattern/src/main/java/com/iluwatar/masterworker/system/systemmaster/Master.java @@ -23,18 +23,17 @@ package com.iluwatar.masterworker.system.systemmaster; -import java.util.ArrayList; -import java.util.Hashtable; import com.iluwatar.masterworker.Input; import com.iluwatar.masterworker.Result; import com.iluwatar.masterworker.system.systemworkers.Worker; +import java.util.ArrayList; +import java.util.Hashtable; /** - *The abstract Master class which contains private fields numOfWorkers - *(number of workers), workers (arraylist of workers), expectedNumResults - *(number of divisions of input data, same as expected number of results), - *allResultData (hashtable of results obtained from workers, mapped by - *their ids) and finalResult (aggregated from allResultData). + * The abstract Master class which contains private fields numOfWorkers (number of workers), workers + * (arraylist of workers), expectedNumResults (number of divisions of input data, same as expected + * number of results), allResultData (hashtable of results obtained from workers, mapped by their + * ids) and finalResult (aggregated from allResultData). */ public abstract class Master { @@ -43,7 +42,7 @@ public abstract class Master { private int expectedNumResults; private Hashtable allResultData; private Result finalResult; - + Master(int numOfWorkers) { this.numOfWorkers = numOfWorkers; this.workers = setWorkers(numOfWorkers); @@ -51,46 +50,46 @@ public abstract class Master { this.allResultData = new Hashtable(numOfWorkers); this.finalResult = null; } - + public Result getFinalResult() { return this.finalResult; } - + Hashtable getAllResultData() { return this.allResultData; } - + int getExpectedNumResults() { return this.expectedNumResults; } - + ArrayList getWorkers() { return this.workers; } - + abstract ArrayList setWorkers(int num); - + public void doWork(Input input) { divideWork(input); } - + private void divideWork(Input input) { ArrayList dividedInput = input.divideData(numOfWorkers); if (dividedInput != null) { this.expectedNumResults = dividedInput.size(); - for (int i = 0; i < this.expectedNumResults; i++) { + for (int i = 0; i < this.expectedNumResults; i++) { //ith division given to ith worker in this.workers this.workers.get(i).setReceivedData(this, dividedInput.get(i)); this.workers.get(i).run(); } } } - + public void receiveData(Result data, Worker w) { //check if can receive..if yes: collectResult(data, w.getWorkerId()); } - + private void collectResult(Result data, int workerId) { this.allResultData.put(workerId, data); if (this.allResultData.size() == this.expectedNumResults) { @@ -98,6 +97,6 @@ private void collectResult(Result data, int workerId) { this.finalResult = aggregateData(); } } - + abstract Result aggregateData(); } diff --git a/master-worker-pattern/src/main/java/com/iluwatar/masterworker/system/systemworkers/ArrayTransposeWorker.java b/master-worker-pattern/src/main/java/com/iluwatar/masterworker/system/systemworkers/ArrayTransposeWorker.java index 1d06fcc875da..37d8ba005699 100644 --- a/master-worker-pattern/src/main/java/com/iluwatar/masterworker/system/systemworkers/ArrayTransposeWorker.java +++ b/master-worker-pattern/src/main/java/com/iluwatar/masterworker/system/systemworkers/ArrayTransposeWorker.java @@ -28,8 +28,8 @@ import com.iluwatar.masterworker.system.systemmaster.Master; /** - *Class ArrayTransposeWorker extends abstract class {@link Worker} and defines method - *executeOperation(), to be performed on data received from master. + * Class ArrayTransposeWorker extends abstract class {@link Worker} and defines method + * executeOperation(), to be performed on data received from master. */ public class ArrayTransposeWorker extends Worker { @@ -41,12 +41,14 @@ public ArrayTransposeWorker(Master master, int id) { @Override ArrayResult executeOperation() { //number of rows in result matrix is equal to number of columns in input matrix and vice versa - int[][] resultData = new int[((ArrayInput) this.getReceivedData()).data[0].length] - [((ArrayInput) this.getReceivedData()).data.length]; - for (int i = 0; i < ((ArrayInput) this.getReceivedData()).data.length; i++) { - for (int j = 0; j < ((ArrayInput) this.getReceivedData()).data[0].length; j++) { + ArrayInput arrayInput = (ArrayInput) this.getReceivedData(); + final int rows = arrayInput.data[0].length; + final int cols = arrayInput.data.length; + int[][] resultData = new int[rows][cols]; + for (int i = 0; i < cols; i++) { + for (int j = 0; j < rows; j++) { //flipping element positions along diagonal - resultData[j][i] = ((ArrayInput) this.getReceivedData()).data[i][j]; + resultData[j][i] = arrayInput.data[i][j]; } } return new ArrayResult(resultData); diff --git a/master-worker-pattern/src/main/java/com/iluwatar/masterworker/system/systemworkers/Worker.java b/master-worker-pattern/src/main/java/com/iluwatar/masterworker/system/systemworkers/Worker.java index fff38e953216..bfe226ee0211 100644 --- a/master-worker-pattern/src/main/java/com/iluwatar/masterworker/system/systemworkers/Worker.java +++ b/master-worker-pattern/src/main/java/com/iluwatar/masterworker/system/systemworkers/Worker.java @@ -28,9 +28,8 @@ import com.iluwatar.masterworker.system.systemmaster.Master; /** - *The abstract Worker class which extends Thread class to enable parallel - *processing. Contains fields master(holding reference to master), workerId - *(unique id) and receivedData(from master). + * The abstract Worker class which extends Thread class to enable parallel processing. Contains + * fields master(holding reference to master), workerId (unique id) and receivedData(from master). */ public abstract class Worker extends Thread { @@ -61,7 +60,7 @@ public void setReceivedData(Master m, Input i) { private void sendToMaster(Result data) { this.master.receiveData(data, this); - } + } public void run() { //from Thread class Result work = executeOperation(); diff --git a/mediator/src/main/java/com/iluwatar/mediator/Action.java b/mediator/src/main/java/com/iluwatar/mediator/Action.java index dc89bcfdcd88..66e1f42c4672 100644 --- a/mediator/src/main/java/com/iluwatar/mediator/Action.java +++ b/mediator/src/main/java/com/iluwatar/mediator/Action.java @@ -24,15 +24,15 @@ package com.iluwatar.mediator; /** - * * Action enumeration. - * */ public enum Action { - HUNT("hunted a rabbit", "arrives for dinner"), TALE("tells a tale", "comes to listen"), GOLD( - "found gold", "takes his share of the gold"), ENEMY("spotted enemies", "runs for cover"), NONE( - "", ""); + HUNT("hunted a rabbit", "arrives for dinner"), + TALE("tells a tale", "comes to listen"), + GOLD("found gold", "takes his share of the gold"), + ENEMY("spotted enemies", "runs for cover"), + NONE("", ""); private String title; private String description; diff --git a/mediator/src/main/java/com/iluwatar/mediator/App.java b/mediator/src/main/java/com/iluwatar/mediator/App.java index 9af600f7cc5e..9dbedb4abf69 100644 --- a/mediator/src/main/java/com/iluwatar/mediator/App.java +++ b/mediator/src/main/java/com/iluwatar/mediator/App.java @@ -24,32 +24,31 @@ package com.iluwatar.mediator; /** - * * The Mediator pattern defines an object that encapsulates how a set of objects interact. This * pattern is considered to be a behavioral pattern due to the way it can alter the program's * running behavior. - *

- * Usually a program is made up of a large number of classes. So the logic and computation is + * + *

Usually a program is made up of a large number of classes. So the logic and computation is * distributed among these classes. However, as more classes are developed in a program, especially * during maintenance and/or refactoring, the problem of communication between these classes may * become more complex. This makes the program harder to read and maintain. Furthermore, it can * become difficult to change the program, since any change may affect code in several other * classes. - *

- * With the Mediator pattern, communication between objects is encapsulated with a mediator object. - * Objects no longer communicate directly with each other, but instead communicate through the - * mediator. This reduces the dependencies between communicating objects, thereby lowering the + * + *

With the Mediator pattern, communication between objects is encapsulated with a mediator + * object. Objects no longer communicate directly with each other, but instead communicate through + * the mediator. This reduces the dependencies between communicating objects, thereby lowering the * coupling. - *

- * In this example the mediator encapsulates how a set of objects ({@link PartyMember}) interact. - * Instead of referring to each other directly they use the mediator ({@link Party}) interface. - * + * + *

In this example the mediator encapsulates how a set of objects ({@link PartyMember}) + * interact. Instead of referring to each other directly they use the mediator ({@link Party}) + * interface. */ public class App { /** - * Program entry point - * + * Program entry point. + * * @param args command line args */ public static void main(String[] args) { diff --git a/mediator/src/main/java/com/iluwatar/mediator/Hobbit.java b/mediator/src/main/java/com/iluwatar/mediator/Hobbit.java index 1ddec27ab3a9..1e1d53fc30dc 100644 --- a/mediator/src/main/java/com/iluwatar/mediator/Hobbit.java +++ b/mediator/src/main/java/com/iluwatar/mediator/Hobbit.java @@ -24,9 +24,7 @@ package com.iluwatar.mediator; /** - * * Hobbit party member. - * */ public class Hobbit extends PartyMemberBase { diff --git a/mediator/src/main/java/com/iluwatar/mediator/Hunter.java b/mediator/src/main/java/com/iluwatar/mediator/Hunter.java index ed73c1684ccb..0711acf70fff 100644 --- a/mediator/src/main/java/com/iluwatar/mediator/Hunter.java +++ b/mediator/src/main/java/com/iluwatar/mediator/Hunter.java @@ -24,9 +24,7 @@ package com.iluwatar.mediator; /** - * * Hunter party member. - * */ public class Hunter extends PartyMemberBase { diff --git a/mediator/src/main/java/com/iluwatar/mediator/Party.java b/mediator/src/main/java/com/iluwatar/mediator/Party.java index c28b063f35b8..52d91e21d135 100644 --- a/mediator/src/main/java/com/iluwatar/mediator/Party.java +++ b/mediator/src/main/java/com/iluwatar/mediator/Party.java @@ -24,9 +24,7 @@ package com.iluwatar.mediator; /** - * * Party interface. - * */ public interface Party { diff --git a/mediator/src/main/java/com/iluwatar/mediator/PartyImpl.java b/mediator/src/main/java/com/iluwatar/mediator/PartyImpl.java index a2a755408620..6384a21872cf 100644 --- a/mediator/src/main/java/com/iluwatar/mediator/PartyImpl.java +++ b/mediator/src/main/java/com/iluwatar/mediator/PartyImpl.java @@ -27,9 +27,7 @@ import java.util.List; /** - * * Party implementation. - * */ public class PartyImpl implements Party { diff --git a/mediator/src/main/java/com/iluwatar/mediator/PartyMember.java b/mediator/src/main/java/com/iluwatar/mediator/PartyMember.java index a45b37b17cd3..c233a051af42 100644 --- a/mediator/src/main/java/com/iluwatar/mediator/PartyMember.java +++ b/mediator/src/main/java/com/iluwatar/mediator/PartyMember.java @@ -24,9 +24,7 @@ package com.iluwatar.mediator; /** - * * Interface for party members interacting with {@link Party}. - * */ public interface PartyMember { diff --git a/mediator/src/main/java/com/iluwatar/mediator/PartyMemberBase.java b/mediator/src/main/java/com/iluwatar/mediator/PartyMemberBase.java index 7ff3535e85d4..2d025db0c4ef 100644 --- a/mediator/src/main/java/com/iluwatar/mediator/PartyMemberBase.java +++ b/mediator/src/main/java/com/iluwatar/mediator/PartyMemberBase.java @@ -27,9 +27,7 @@ import org.slf4j.LoggerFactory; /** - * * Abstract base class for party members. - * */ public abstract class PartyMemberBase implements PartyMember { diff --git a/mediator/src/main/java/com/iluwatar/mediator/Rogue.java b/mediator/src/main/java/com/iluwatar/mediator/Rogue.java index 226bd8f04c4f..568510236d4c 100644 --- a/mediator/src/main/java/com/iluwatar/mediator/Rogue.java +++ b/mediator/src/main/java/com/iluwatar/mediator/Rogue.java @@ -24,9 +24,7 @@ package com.iluwatar.mediator; /** - * * Rogue party member. - * */ public class Rogue extends PartyMemberBase { diff --git a/mediator/src/main/java/com/iluwatar/mediator/Wizard.java b/mediator/src/main/java/com/iluwatar/mediator/Wizard.java index 33d7d6dce511..c138f0265115 100644 --- a/mediator/src/main/java/com/iluwatar/mediator/Wizard.java +++ b/mediator/src/main/java/com/iluwatar/mediator/Wizard.java @@ -24,9 +24,7 @@ package com.iluwatar.mediator; /** - * * Wizard party member. - * */ public class Wizard extends PartyMemberBase { diff --git a/memento/src/main/java/com/iluwatar/memento/App.java b/memento/src/main/java/com/iluwatar/memento/App.java index fc6dffb06cb6..af57d8d4a2b7 100644 --- a/memento/src/main/java/com/iluwatar/memento/App.java +++ b/memento/src/main/java/com/iluwatar/memento/App.java @@ -23,36 +23,33 @@ package com.iluwatar.memento; +import java.util.Stack; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Stack; - /** - * * The Memento pattern is a software design pattern that provides the ability to restore an object * to its previous state (undo via rollback). - *

- * The Memento pattern is implemented with three objects: the originator, a caretaker and a memento. - * The originator is some object that has an internal state. The caretaker is going to do something - * to the originator, but wants to be able to undo the change. The caretaker first asks the - * originator for a memento object. Then it does whatever operation (or sequence of operations) it - * was going to do. To roll back to the state before the operations, it returns the memento object - * to the originator. The memento object itself is an opaque object (one which the caretaker cannot, - * or should not, change). When using this pattern, care should be taken if the originator may - * change other objects or resources - the memento pattern operates on a single object. - *

- * In this example the object ({@link Star}) gives out a "memento" ({@link StarMemento}) that + * + *

The Memento pattern is implemented with three objects: the originator, a caretaker and a + * memento. The originator is some object that has an internal state. The caretaker is going to do + * something to the originator, but wants to be able to undo the change. The caretaker first asks + * the originator for a memento object. Then it does whatever operation (or sequence of operations) + * it was going to do. To roll back to the state before the operations, it returns the memento + * object to the originator. The memento object itself is an opaque object (one which the caretaker + * cannot, or should not, change). When using this pattern, care should be taken if the originator + * may change other objects or resources - the memento pattern operates on a single object. + * + *

In this example the object ({@link Star}) gives out a "memento" ({@link StarMemento}) that * contains the state of the object. Later on the memento can be set back to the object restoring * the state. - * */ public class App { private static final Logger LOGGER = LoggerFactory.getLogger(App.class); /** - * Program entry point + * Program entry point. */ public static void main(String[] args) { Stack states = new Stack<>(); diff --git a/memento/src/main/java/com/iluwatar/memento/Star.java b/memento/src/main/java/com/iluwatar/memento/Star.java index 0e235752ec4e..ebeea28f291b 100644 --- a/memento/src/main/java/com/iluwatar/memento/Star.java +++ b/memento/src/main/java/com/iluwatar/memento/Star.java @@ -24,9 +24,7 @@ package com.iluwatar.memento; /** - * * Star uses "mementos" to store and restore state. - * */ public class Star { @@ -35,7 +33,7 @@ public class Star { private int massTons; /** - * Constructor + * Constructor. */ public Star(StarType startType, int startAge, int startMass) { this.type = startType; @@ -44,7 +42,7 @@ public Star(StarType startType, int startAge, int startMass) { } /** - * Makes time pass for the star + * Makes time pass for the star. */ public void timePasses() { ageYears *= 2; @@ -96,9 +94,7 @@ public String toString() { } /** - * - * StarMemento implementation - * + * StarMemento implementation. */ private static class StarMementoInternal implements StarMemento { diff --git a/memento/src/main/java/com/iluwatar/memento/StarMemento.java b/memento/src/main/java/com/iluwatar/memento/StarMemento.java index b94f5996a9db..7b7ccd3ec304 100644 --- a/memento/src/main/java/com/iluwatar/memento/StarMemento.java +++ b/memento/src/main/java/com/iluwatar/memento/StarMemento.java @@ -24,9 +24,7 @@ package com.iluwatar.memento; /** - * * External interface to memento. - * */ public interface StarMemento { diff --git a/memento/src/main/java/com/iluwatar/memento/StarType.java b/memento/src/main/java/com/iluwatar/memento/StarType.java index 29da625799ce..507cd506b60a 100644 --- a/memento/src/main/java/com/iluwatar/memento/StarType.java +++ b/memento/src/main/java/com/iluwatar/memento/StarType.java @@ -24,9 +24,7 @@ package com.iluwatar.memento; /** - * - * StarType enumeration - * + * StarType enumeration. */ public enum StarType { diff --git a/model-view-controller/src/main/java/com/iluwatar/model/view/controller/App.java b/model-view-controller/src/main/java/com/iluwatar/model/view/controller/App.java index b4bc8f6ca4a6..4607f009df61 100644 --- a/model-view-controller/src/main/java/com/iluwatar/model/view/controller/App.java +++ b/model-view-controller/src/main/java/com/iluwatar/model/view/controller/App.java @@ -24,27 +24,25 @@ package com.iluwatar.model.view.controller; /** - * * Model-View-Controller is a pattern for implementing user interfaces. It divides the application * into three interconnected parts namely the model, the view and the controller. - *

- * The central component of MVC, the model, captures the behavior of the application in terms of its - * problem domain, independent of the user interface. The model directly manages the data, logic and - * rules of the application. A view can be any output representation of information, such as a chart - * or a diagram The third part, the controller, accepts input and converts it to commands for the - * model or view. - *

- * In this example we have a giant ({@link GiantModel}) with statuses for health, fatigue and - * nourishment. {@link GiantView} can display the giant with its current status. - * {@link GiantController} receives input affecting the model and delegates redrawing the giant to - * the view. * + *

The central component of MVC, the model, captures the behavior of the application in terms of + * its problem domain, independent of the user interface. The model directly manages the data, logic + * and rules of the application. A view can be any output representation of information, such as a + * chart or a diagram The third part, the controller, accepts input and converts it to commands for + * the model or view. + * + *

In this example we have a giant ({@link GiantModel}) with statuses for health, fatigue and + * nourishment. {@link GiantView} can display the giant with its current status. {@link + * GiantController} receives input affecting the model and delegates redrawing the giant to the + * view. */ public class App { /** - * Program entry point - * + * Program entry point. + * * @param args command line args */ public static void main(String[] args) { diff --git a/model-view-controller/src/main/java/com/iluwatar/model/view/controller/Fatigue.java b/model-view-controller/src/main/java/com/iluwatar/model/view/controller/Fatigue.java index 7f0fd293741c..b1663df1f3c1 100644 --- a/model-view-controller/src/main/java/com/iluwatar/model/view/controller/Fatigue.java +++ b/model-view-controller/src/main/java/com/iluwatar/model/view/controller/Fatigue.java @@ -24,9 +24,7 @@ package com.iluwatar.model.view.controller; /** - * - * Fatigue enumeration - * + * Fatigue enumeration. */ public enum Fatigue { diff --git a/model-view-controller/src/main/java/com/iluwatar/model/view/controller/GiantController.java b/model-view-controller/src/main/java/com/iluwatar/model/view/controller/GiantController.java index e420ec890870..e66608117479 100644 --- a/model-view-controller/src/main/java/com/iluwatar/model/view/controller/GiantController.java +++ b/model-view-controller/src/main/java/com/iluwatar/model/view/controller/GiantController.java @@ -24,9 +24,7 @@ package com.iluwatar.model.view.controller; /** - * * GiantController can update the giant data and redraw it using the view. - * */ public class GiantController { diff --git a/model-view-controller/src/main/java/com/iluwatar/model/view/controller/GiantModel.java b/model-view-controller/src/main/java/com/iluwatar/model/view/controller/GiantModel.java index 4ae2c4c195ba..c80d0dba028d 100644 --- a/model-view-controller/src/main/java/com/iluwatar/model/view/controller/GiantModel.java +++ b/model-view-controller/src/main/java/com/iluwatar/model/view/controller/GiantModel.java @@ -24,9 +24,7 @@ package com.iluwatar.model.view.controller; /** - * - * GiantModel contains the giant data - * + * GiantModel contains the giant data. */ public class GiantModel { diff --git a/model-view-controller/src/main/java/com/iluwatar/model/view/controller/GiantView.java b/model-view-controller/src/main/java/com/iluwatar/model/view/controller/GiantView.java index 9590d609d61f..da14b7c08b60 100644 --- a/model-view-controller/src/main/java/com/iluwatar/model/view/controller/GiantView.java +++ b/model-view-controller/src/main/java/com/iluwatar/model/view/controller/GiantView.java @@ -27,9 +27,7 @@ import org.slf4j.LoggerFactory; /** - * - * GiantView displays the giant - * + * GiantView displays the giant. */ public class GiantView { diff --git a/model-view-controller/src/main/java/com/iluwatar/model/view/controller/Health.java b/model-view-controller/src/main/java/com/iluwatar/model/view/controller/Health.java index c8b9374bf43b..30b3b2b90aeb 100644 --- a/model-view-controller/src/main/java/com/iluwatar/model/view/controller/Health.java +++ b/model-view-controller/src/main/java/com/iluwatar/model/view/controller/Health.java @@ -24,9 +24,7 @@ package com.iluwatar.model.view.controller; /** - * - * Health enumeration - * + * Health enumeration. */ public enum Health { diff --git a/model-view-controller/src/main/java/com/iluwatar/model/view/controller/Nourishment.java b/model-view-controller/src/main/java/com/iluwatar/model/view/controller/Nourishment.java index 9810b201565b..3ced564cc15a 100644 --- a/model-view-controller/src/main/java/com/iluwatar/model/view/controller/Nourishment.java +++ b/model-view-controller/src/main/java/com/iluwatar/model/view/controller/Nourishment.java @@ -24,9 +24,7 @@ package com.iluwatar.model.view.controller; /** - * - * Nourishment enumeration - * + * Nourishment enumeration. */ public enum Nourishment { diff --git a/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/App.java b/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/App.java index 9b6e6cde833f..43984e8475f8 100644 --- a/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/App.java +++ b/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/App.java @@ -24,31 +24,29 @@ package com.iluwatar.model.view.presenter; /** - * - * The Model-View-Presenter(MVP) architectural pattern, helps us achieve what is called - * "The separation of concerns" principle. This is accomplished by separating the application's - * logic (Model), GUIs (View), and finally the way that the user's actions update the application's - * logic (Presenter). - *

- * In the following example, The {@link FileLoader} class represents the app's logic, the - * {@link FileSelectorJFrame} is the GUI and the {@link FileSelectorPresenter} is responsible to - * respond to users' actions. - *

- * Finally, please notice the wiring between the Presenter and the View and between the Presenter - * and the Model. - * + * The Model-View-Presenter(MVP) architectural pattern, helps us achieve what is called "The + * separation of concerns" principle. This is accomplished by separating the application's logic + * (Model), GUIs (View), and finally the way that the user's actions update the application's logic + * (Presenter). + * + *

In the following example, The {@link FileLoader} class represents the app's logic, the {@link + * FileSelectorJFrame} is the GUI and the {@link FileSelectorPresenter} is responsible to respond to + * users' actions. + * + *

Finally, please notice the wiring between the Presenter and the View and between the + * Presenter and the Model. */ public class App { /** - * Program entry point - * + * Program entry point. + * * @param args command line args */ public static void main(String[] args) { FileLoader loader = new FileLoader(); - FileSelectorJFrame jFrame = new FileSelectorJFrame(); - FileSelectorPresenter presenter = new FileSelectorPresenter(jFrame); + FileSelectorJFrame frame = new FileSelectorJFrame(); + FileSelectorPresenter presenter = new FileSelectorPresenter(frame); presenter.setLoader(loader); presenter.start(); } diff --git a/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileLoader.java b/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileLoader.java index 980c0b56c2e9..9c01b2044f2d 100644 --- a/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileLoader.java +++ b/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileLoader.java @@ -27,23 +27,22 @@ import java.io.File; import java.io.FileReader; import java.io.Serializable; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Every instance of this class represents the Model component in the Model-View-Presenter * architectural pattern. - *

- * It is responsible for reading and loading the contents of a given file. + * + *

It is responsible for reading and loading the contents of a given file. */ public class FileLoader implements Serializable { /** - * Generated serial version UID + * Generated serial version UID. */ private static final long serialVersionUID = -4745803872902019069L; - + private static final Logger LOGGER = LoggerFactory.getLogger(FileLoader.class); /** @@ -81,7 +80,7 @@ public String loadData() { /** * Sets the path of the file to be loaded, to the given value. - * + * * @param fileName The path of the file to be loaded. */ public void setFileName(String fileName) { @@ -89,6 +88,8 @@ public void setFileName(String fileName) { } /** + * Gets the path of the file to be loaded. + * * @return fileName The path of the file to be loaded. */ public String getFileName() { @@ -96,6 +97,8 @@ public String getFileName() { } /** + * Returns true if the given file exists. + * * @return True, if the file given exists, false otherwise. */ public boolean fileExists() { @@ -103,6 +106,8 @@ public boolean fileExists() { } /** + * Returns true if the given file is loaded. + * * @return True, if the file is loaded, false otherwise. */ public boolean isLoaded() { diff --git a/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorJFrame.java b/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorJFrame.java index 3d9bc035a5ad..77523ccaa7be 100644 --- a/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorJFrame.java +++ b/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorJFrame.java @@ -26,7 +26,6 @@ import java.awt.Color; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; - import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; @@ -82,7 +81,7 @@ public class FileSelectorJFrame extends JFrame implements FileSelectorView, Acti private JPanel panel; /** - * The Presenter component that the frame will interact with + * The Presenter component that the frame will interact with. */ private FileSelectorPresenter presenter; diff --git a/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorPresenter.java b/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorPresenter.java index a9cf1ba80a4c..35e1c0076712 100644 --- a/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorPresenter.java +++ b/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorPresenter.java @@ -28,13 +28,13 @@ /** * Every instance of this class represents the Presenter component in the Model-View-Presenter * architectural pattern. - *

- * It is responsible for reacting to the user's actions and update the View component. + * + *

It is responsible for reacting to the user's actions and update the View component. */ public class FileSelectorPresenter implements Serializable { /** - * Generated serial version UID + * Generated serial version UID. */ private static final long serialVersionUID = 1210314339075855074L; @@ -49,8 +49,8 @@ public class FileSelectorPresenter implements Serializable { private FileLoader loader; /** - * Constructor - * + * Constructor. + * * @param view The view component that the presenter will interact with. */ public FileSelectorPresenter(FileSelectorView view) { @@ -59,7 +59,7 @@ public FileSelectorPresenter(FileSelectorView view) { /** * Sets the {@link FileLoader} object, to the value given as parameter. - * + * * @param loader The new {@link FileLoader} object(the Model component). */ public void setLoader(FileLoader loader) { @@ -82,7 +82,7 @@ public void fileNameChanged() { } /** - * Ok button handler + * Ok button handler. */ public void confirmed() { if (loader.getFileName() == null || loader.getFileName().equals("")) { diff --git a/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorStub.java b/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorStub.java index d034bcb04563..1d3aa07fbfcf 100644 --- a/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorStub.java +++ b/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorStub.java @@ -26,12 +26,12 @@ /** * Every instance of this class represents the Stub component in the Model-View-Presenter * architectural pattern. - *

- * The stub implements the View interface and it is useful when we want the test the reaction to + * + *

The stub implements the View interface and it is useful when we want the test the reaction to * user events, such as mouse clicks. - *

- * Since we can not test the GUI directly, the MVP pattern provides this functionality through the - * View's dummy implementation, the Stub. + * + *

Since we can not test the GUI directly, the MVP pattern provides this functionality through + * the View's dummy implementation, the Stub. */ public class FileSelectorStub implements FileSelectorView { @@ -61,7 +61,7 @@ public class FileSelectorStub implements FileSelectorView { private boolean dataDisplayed; /** - * Constructor + * Constructor. */ public FileSelectorStub() { this.opened = false; @@ -124,6 +124,8 @@ public int getMessagesSent() { } /** + * Returns true, if the data were displayed. + * * @return True if the data where displayed, false otherwise. */ public boolean dataDisplayed() { diff --git a/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorView.java b/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorView.java index 3deec63d9692..e381784c53b4 100644 --- a/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorView.java +++ b/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorView.java @@ -42,44 +42,50 @@ public interface FileSelectorView extends Serializable { void close(); /** + * Returns true if view is opened. + * * @return True, if the view is opened, false otherwise. */ boolean isOpened(); /** * Sets the presenter component, to the one given as parameter. - * + * * @param presenter The new presenter component. */ void setPresenter(FileSelectorPresenter presenter); /** + * Gets presenter component. + * * @return The presenter Component. */ FileSelectorPresenter getPresenter(); /** * Sets the file's name, to the value given as parameter. - * + * * @param name The new name of the file. */ void setFileName(String name); /** + * Gets the name of file. + * * @return The name of the file. */ String getFileName(); /** * Displays a message to the users. - * + * * @param message The message to be displayed. */ void showMessage(String message); /** * Displays the data to the view. - * + * * @param data The data to be written. */ void displayData(String data); diff --git a/module/src/main/java/com/iluwatar/module/App.java b/module/src/main/java/com/iluwatar/module/App.java index af0432afb9af..1b6cbbd23aa2 100644 --- a/module/src/main/java/com/iluwatar/module/App.java +++ b/module/src/main/java/com/iluwatar/module/App.java @@ -31,10 +31,9 @@ * An object that applies this pattern can provide the equivalent of a namespace, providing the * initialization and finalization process of a static class or a class with static members with * cleaner, more concise syntax and semantics. - *

- * The below example demonstrates a use case for testing two different modules: File Logger and + * + *

The below example demonstrates a use case for testing two different modules: File Logger and * Console Logger - * */ public class App { @@ -42,10 +41,10 @@ public class App { public static ConsoleLoggerModule consoleLoggerModule; /** - * Following method performs the initialization - * + * Following method performs the initialization. + * * @throws FileNotFoundException if program is not able to find log files (output.txt and - * error.txt) + * error.txt) */ public static void prepare() throws FileNotFoundException { @@ -55,7 +54,7 @@ public static void prepare() throws FileNotFoundException { } /** - * Following method performs the finalization + * Following method performs the finalization. */ public static void unprepare() { @@ -65,8 +64,8 @@ public static void unprepare() { } /** - * Following method is main executor - * + * Following method is main executor. + * * @param args for providing default program arguments */ public static void execute(final String... args) { @@ -82,10 +81,10 @@ public static void execute(final String... args) { /** * Program entry point. - * + * * @param args command line args. * @throws FileNotFoundException if program is not able to find log files (output.txt and - * error.txt) + * error.txt) */ public static void main(final String... args) throws FileNotFoundException { prepare(); diff --git a/module/src/main/java/com/iluwatar/module/ConsoleLoggerModule.java b/module/src/main/java/com/iluwatar/module/ConsoleLoggerModule.java index 6e6d0539d0ba..7ca0d873d46d 100644 --- a/module/src/main/java/com/iluwatar/module/ConsoleLoggerModule.java +++ b/module/src/main/java/com/iluwatar/module/ConsoleLoggerModule.java @@ -23,16 +23,15 @@ package com.iluwatar.module; +import java.io.PrintStream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.PrintStream; - /** - * The ConsoleLoggerModule is responsible for showing logs on System Console - *

- * The below example demonstrates a Console logger module, which can print simple and error messages - * in two designated formats + * The ConsoleLoggerModule is responsible for showing logs on System Console. + * + *

The below example demonstrates a Console logger module, which can print simple and error + * messages in two designated formats */ public final class ConsoleLoggerModule { @@ -43,11 +42,12 @@ public final class ConsoleLoggerModule { public PrintStream output = null; public PrintStream error = null; - private ConsoleLoggerModule() {} + private ConsoleLoggerModule() { + } /** - * Static method to get single instance of class - * + * Static method to get single instance of class. + * * @return singleton instance of ConsoleLoggerModule */ public static ConsoleLoggerModule getSingleton() { @@ -60,7 +60,7 @@ public static ConsoleLoggerModule getSingleton() { } /** - * Following method performs the initialization + * Following method performs the initialization. */ public ConsoleLoggerModule prepare() { @@ -73,7 +73,7 @@ public ConsoleLoggerModule prepare() { } /** - * Following method performs the finalization + * Following method performs the finalization. */ public void unprepare() { @@ -93,8 +93,8 @@ public void unprepare() { } /** - * Used to print a message - * + * Used to print a message. + * * @param value will be printed on console */ public void printString(final String value) { @@ -102,8 +102,8 @@ public void printString(final String value) { } /** - * Used to print a error message - * + * Used to print a error message. + * * @param value will be printed on error console */ public void printErrorString(final String value) { diff --git a/module/src/main/java/com/iluwatar/module/FileLoggerModule.java b/module/src/main/java/com/iluwatar/module/FileLoggerModule.java index e461b31d7572..185bd0ae267d 100644 --- a/module/src/main/java/com/iluwatar/module/FileLoggerModule.java +++ b/module/src/main/java/com/iluwatar/module/FileLoggerModule.java @@ -23,18 +23,17 @@ package com.iluwatar.module; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.PrintStream; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** - * The FileLoggerModule is responsible for showing logs on File System - *

- * The below example demonstrates a File logger module, which can print simple and error messages in - * two designated files + * The FileLoggerModule is responsible for showing logs on File System. + * + *

The below example demonstrates a File logger module, which can print simple and error + * messages in two designated files */ public final class FileLoggerModule { @@ -48,11 +47,12 @@ public final class FileLoggerModule { public PrintStream output = null; public PrintStream error = null; - private FileLoggerModule() {} + private FileLoggerModule() { + } /** - * Static method to get single instance of class - * + * Static method to get single instance of class. + * * @return singleton instance of FileLoggerModule */ public static FileLoggerModule getSingleton() { @@ -65,10 +65,10 @@ public static FileLoggerModule getSingleton() { } /** - * Following method performs the initialization - * + * Following method performs the initialization. + * * @throws FileNotFoundException if program is not able to find log files (output.txt and - * error.txt) + * error.txt) */ public FileLoggerModule prepare() throws FileNotFoundException { @@ -81,7 +81,7 @@ public FileLoggerModule prepare() throws FileNotFoundException { } /** - * Following method performs the finalization + * Following method performs the finalization. */ public void unprepare() { @@ -101,8 +101,8 @@ public void unprepare() { } /** - * Used to print a message - * + * Used to print a message. + * * @param value will be printed in file */ public void printString(final String value) { @@ -110,8 +110,8 @@ public void printString(final String value) { } /** - * Used to print a error message - * + * Used to print a error message. + * * @param value will be printed on error file */ public void printErrorString(final String value) { diff --git a/monad/src/main/java/com/iluwatar/monad/App.java b/monad/src/main/java/com/iluwatar/monad/App.java index 94e46548744c..ccb42edd027e 100644 --- a/monad/src/main/java/com/iluwatar/monad/App.java +++ b/monad/src/main/java/com/iluwatar/monad/App.java @@ -23,26 +23,27 @@ package com.iluwatar.monad; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.util.Objects; import java.util.function.Function; import java.util.function.Predicate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** - * The Monad pattern defines a monad structure, that enables chaining operations - * in pipelines and processing data step by step. - * Formally, monad consists of a type constructor M and two operations: + * The Monad pattern defines a monad structure, that enables chaining operations in pipelines and + * processing data step by step. Formally, monad consists of a type constructor M and two + * operations: *
bind - that takes monadic object and a function from plain object to the * monadic value and returns monadic value. *
return - that takes plain type object and returns this object wrapped in a monadic value. - *

- * In the given example, the Monad pattern is represented as a {@link Validator} that takes an instance - * of a plain object with {@link Validator#of(Object)} - * and validates it {@link Validator#validate(Function, Predicate, String)} against given predicates. - *

As a validation result {@link Validator#get()} it either returns valid object {@link Validator#t} - * or throws a list of exceptions {@link Validator#exceptions} collected during validation. + * + *

In the given example, the Monad pattern is represented as a {@link Validator} that takes an + * instance of a plain object with {@link Validator#of(Object)} and validates it {@link + * Validator#validate(Function, Predicate, String)} against given predicates. + * + *

As a validation result {@link Validator#get()} it either returns valid object {@link + * Validator#t} or throws a list of exceptions {@link Validator#exceptions} collected during + * validation. */ public class App { @@ -58,6 +59,7 @@ public static void main(String[] args) { LOGGER.info(Validator.of(user).validate(User::getName, Objects::nonNull, "name is null") .validate(User::getName, name -> !name.isEmpty(), "name is empty") .validate(User::getEmail, email -> !email.contains("@"), "email doesn't containt '@'") - .validate(User::getAge, age -> age > 20 && age < 30, "age isn't between...").get().toString()); + .validate(User::getAge, age -> age > 20 && age < 30, "age isn't between...").get() + .toString()); } } diff --git a/monad/src/main/java/com/iluwatar/monad/Sex.java b/monad/src/main/java/com/iluwatar/monad/Sex.java index 960711656021..cc772c340009 100644 --- a/monad/src/main/java/com/iluwatar/monad/Sex.java +++ b/monad/src/main/java/com/iluwatar/monad/Sex.java @@ -24,7 +24,7 @@ package com.iluwatar.monad; /** - * Enumeration of Types of Sex + * Enumeration of Types of Sex. */ public enum Sex { MALE, FEMALE diff --git a/monad/src/main/java/com/iluwatar/monad/User.java b/monad/src/main/java/com/iluwatar/monad/User.java index 9ecaa527539c..77766d1aa25f 100644 --- a/monad/src/main/java/com/iluwatar/monad/User.java +++ b/monad/src/main/java/com/iluwatar/monad/User.java @@ -24,7 +24,7 @@ package com.iluwatar.monad; /** - * User Definition + * User Definition. */ public class User { @@ -34,6 +34,8 @@ public class User { private String email; /** + * Constructor. + * * @param name - name * @param age - age * @param sex - sex diff --git a/monad/src/main/java/com/iluwatar/monad/Validator.java b/monad/src/main/java/com/iluwatar/monad/Validator.java index b5618f91c390..2d1f1bdab177 100644 --- a/monad/src/main/java/com/iluwatar/monad/Validator.java +++ b/monad/src/main/java/com/iluwatar/monad/Validator.java @@ -30,18 +30,18 @@ import java.util.function.Predicate; /** - * Class representing Monad design pattern. Monad is a way of chaining operations on the - * given object together step by step. In Validator each step results in either success or - * failure indicator, giving a way of receiving each of them easily and finally getting - * validated object or list of exceptions. + * Class representing Monad design pattern. Monad is a way of chaining operations on the given + * object together step by step. In Validator each step results in either success or failure + * indicator, giving a way of receiving each of them easily and finally getting validated object or + * list of exceptions. * * @param Placeholder for an object. */ public class Validator { /** - * Object that is validated + * Object that is validated. */ - private final T t; + private final T obj; /** * List of exception thrown during validation. @@ -50,14 +50,15 @@ public class Validator { /** * Creates a monadic value of given object. - * @param t object to be validated + * + * @param obj object to be validated */ - private Validator(T t) { - this.t = t; + private Validator(T obj) { + this.obj = obj; } /** - * Creates validator against given object + * Creates validator against given object. * * @param t object to be validated * @param object's type @@ -68,25 +69,27 @@ public static Validator of(T t) { } /** - * @param validation one argument boolean-valued function that - * represents one step of validation. Adds exception to main validation exception - * list when single step validation ends with failure. + * Checks if the validation is successful. + * + * @param validation one argument boolean-valued function that represents one step of validation. + * Adds exception to main validation exception list when single step validation + * ends with failure. * @param message error message when object is invalid * @return this */ public Validator validate(Predicate validation, String message) { - if (!validation.test(t)) { + if (!validation.test(obj)) { exceptions.add(new IllegalStateException(message)); } return this; } /** - * Extension for the {@link Validator#validate(Function, Predicate, String)} method, - * dedicated for objects, that need to be projected before requested validation. + * Extension for the {@link Validator#validate(Function, Predicate, String)} method, dedicated for + * objects, that need to be projected before requested validation. * - * @param projection function that gets an objects, and returns projection representing - * element to be validated. + * @param projection function that gets an objects, and returns projection representing element to + * be validated. * @param validation see {@link Validator#validate(Function, Predicate, String)} * @param message see {@link Validator#validate(Function, Predicate, String)} * @param see {@link Validator#validate(Function, Predicate, String)} @@ -105,7 +108,7 @@ public Validator validate(Function projection, Predicate validat */ public T get() throws IllegalStateException { if (exceptions.isEmpty()) { - return t; + return obj; } IllegalStateException e = new IllegalStateException(); exceptions.forEach(e::addSuppressed); diff --git a/monostate/src/main/java/com/iluwatar/monostate/App.java b/monostate/src/main/java/com/iluwatar/monostate/App.java index 4b6f8b14b64d..64cb384612c1 100644 --- a/monostate/src/main/java/com/iluwatar/monostate/App.java +++ b/monostate/src/main/java/com/iluwatar/monostate/App.java @@ -24,28 +24,22 @@ package com.iluwatar.monostate; - /** - * * The MonoState pattern ensures that all instances of the class will have the same state. This can * be used a direct replacement of the Singleton pattern. - * - *

- * In the following example, The {@link LoadBalancer} class represents the app's logic. It contains - * a series of Servers, which can handle requests of type {@link Request}. Two instances of + * + *

In the following example, The {@link LoadBalancer} class represents the app's logic. It + * contains a series of Servers, which can handle requests of type {@link Request}. Two instances of * LoadBalacer are created. When a request is made to a server via the first LoadBalancer the state * change in the first load balancer affects the second. So if the first LoadBalancer selects the * Server 1, the second LoadBalancer on a new request will select the Second server. If a third * LoadBalancer is created and a new request is made to it, then it will select the third server as * the second load balancer has already selected the second server. - *

- * . - * */ public class App { /** - * Program entry point - * + * Program entry point. + * * @param args command line args */ public static void main(String[] args) { diff --git a/monostate/src/main/java/com/iluwatar/monostate/LoadBalancer.java b/monostate/src/main/java/com/iluwatar/monostate/LoadBalancer.java index ae590be5ee5d..8546ae1777bf 100644 --- a/monostate/src/main/java/com/iluwatar/monostate/LoadBalancer.java +++ b/monostate/src/main/java/com/iluwatar/monostate/LoadBalancer.java @@ -31,7 +31,6 @@ * receiving a new Request, it delegates the call to the servers in a Round Robin Fashion. Since all * instances of the class share the same state, all instances will delegate to the same server on * receiving a new Request. - * */ public class LoadBalancer { @@ -40,13 +39,13 @@ public class LoadBalancer { static { int id = 0; - for (int port : new int[] {8080, 8081, 8082, 8083, 8084}) { + for (int port : new int[]{8080, 8081, 8082, 8083, 8084}) { SERVERS.add(new Server("localhost", port, ++id)); } } /** - * Add new server + * Add new server. */ public final void addServer(Server server) { synchronized (SERVERS) { @@ -64,7 +63,7 @@ public int getLastServedId() { } /** - * Handle request + * Handle request. */ public synchronized void serverRequest(Request request) { if (lastServedId >= SERVERS.size()) { @@ -73,5 +72,5 @@ public synchronized void serverRequest(Request request) { Server server = SERVERS.get(lastServedId++); server.serve(request); } - + } diff --git a/monostate/src/main/java/com/iluwatar/monostate/Request.java b/monostate/src/main/java/com/iluwatar/monostate/Request.java index 5a7429998ac1..d7e4fcf8f9a5 100644 --- a/monostate/src/main/java/com/iluwatar/monostate/Request.java +++ b/monostate/src/main/java/com/iluwatar/monostate/Request.java @@ -24,9 +24,7 @@ package com.iluwatar.monostate; /** - * * The Request class. A {@link Server} can handle an instance of a Request. - * */ public class Request { diff --git a/monostate/src/main/java/com/iluwatar/monostate/Server.java b/monostate/src/main/java/com/iluwatar/monostate/Server.java index fa809864cb83..cd08b2b29613 100644 --- a/monostate/src/main/java/com/iluwatar/monostate/Server.java +++ b/monostate/src/main/java/com/iluwatar/monostate/Server.java @@ -27,10 +27,8 @@ import org.slf4j.LoggerFactory; /** - * * The Server class. Each Server sits behind a LoadBalancer which delegates the call to the servers * in a simplistic Round Robin fashion. - * */ public class Server { @@ -41,7 +39,7 @@ public class Server { public final int id; /** - * Constructor + * Constructor. */ public Server(String host, int port, int id) { this.host = host; @@ -59,6 +57,6 @@ public int getPort() { public void serve(Request request) { LOGGER.info("Server ID {} associated to host : {} and port {}. Processed request with value {}", - id, host, port, request.value); + id, host, port, request.value); } } diff --git a/multiton/src/main/java/com/iluwatar/multiton/App.java b/multiton/src/main/java/com/iluwatar/multiton/App.java index 8fb226625eae..eb3e0313fe1f 100644 --- a/multiton/src/main/java/com/iluwatar/multiton/App.java +++ b/multiton/src/main/java/com/iluwatar/multiton/App.java @@ -27,26 +27,24 @@ import org.slf4j.LoggerFactory; /** - * * Whereas Singleton design pattern introduces single globally accessible object the Multiton * pattern defines many globally accessible objects. The client asks for the correct instance from * the Multiton by passing an enumeration as parameter. - *

- * There is more than one way to implement the multiton design pattern. In the first example - * {@link Nazgul} is the Multiton and we can ask single {@link Nazgul} from it using {@link NazgulName}. - * The {@link Nazgul}s are statically initialized and stored in concurrent hash map. - *

- * In the enum implementation {@link NazgulEnum} is the multiton. It is static and mutable because - * of the way java supports enums. * + *

There is more than one way to implement the multiton design pattern. In the first example + * {@link Nazgul} is the Multiton and we can ask single {@link Nazgul} from it using {@link + * NazgulName}. The {@link Nazgul}s are statically initialized and stored in concurrent hash map. + * + *

In the enum implementation {@link NazgulEnum} is the multiton. It is static and mutable + * because of the way java supports enums. */ public class App { private static final Logger LOGGER = LoggerFactory.getLogger(App.class); /** - * Program entry point - * + * Program entry point. + * * @param args command line args */ public static void main(String[] args) { @@ -60,7 +58,7 @@ public static void main(String[] args) { LOGGER.info("ADUNAPHEL={}", Nazgul.getInstance(NazgulName.ADUNAPHEL)); LOGGER.info("REN={}", Nazgul.getInstance(NazgulName.REN)); LOGGER.info("UVATHA={}", Nazgul.getInstance(NazgulName.UVATHA)); - + // enum multiton LOGGER.info("KHAMUL={}", NazgulEnum.KHAMUL); LOGGER.info("MURAZOR={}", NazgulEnum.MURAZOR); diff --git a/multiton/src/main/java/com/iluwatar/multiton/Nazgul.java b/multiton/src/main/java/com/iluwatar/multiton/Nazgul.java index 52a25e00d665..f55f85aca722 100644 --- a/multiton/src/main/java/com/iluwatar/multiton/Nazgul.java +++ b/multiton/src/main/java/com/iluwatar/multiton/Nazgul.java @@ -27,9 +27,7 @@ import java.util.concurrent.ConcurrentHashMap; /** - * * Nazgul is a Multiton class. Nazgul instances can be queried using {@link #getInstance} method. - * */ public final class Nazgul { diff --git a/multiton/src/main/java/com/iluwatar/multiton/NazgulEnum.java b/multiton/src/main/java/com/iluwatar/multiton/NazgulEnum.java index f119ee68fb59..5b5c48d66ff1 100644 --- a/multiton/src/main/java/com/iluwatar/multiton/NazgulEnum.java +++ b/multiton/src/main/java/com/iluwatar/multiton/NazgulEnum.java @@ -24,11 +24,10 @@ package com.iluwatar.multiton; /** - * enum based multiton implementation - * + * enum based multiton implementation. */ public enum NazgulEnum { - + KHAMUL, MURAZOR, DWAR, JI_INDUR, AKHORAHIL, HOARMURATH, ADUNAPHEL, REN, UVATHA; } diff --git a/multiton/src/main/java/com/iluwatar/multiton/NazgulName.java b/multiton/src/main/java/com/iluwatar/multiton/NazgulName.java index 5fe2a5a0f427..c7865dceb0a9 100644 --- a/multiton/src/main/java/com/iluwatar/multiton/NazgulName.java +++ b/multiton/src/main/java/com/iluwatar/multiton/NazgulName.java @@ -24,9 +24,7 @@ package com.iluwatar.multiton; /** - * * Each Nazgul has different {@link NazgulName}. - * */ public enum NazgulName { diff --git a/mute-idiom/src/main/java/com/iluwatar/mute/App.java b/mute-idiom/src/main/java/com/iluwatar/mute/App.java index 28649e24990a..d4f140bf089e 100644 --- a/mute-idiom/src/main/java/com/iluwatar/mute/App.java +++ b/mute-idiom/src/main/java/com/iluwatar/mute/App.java @@ -23,19 +23,17 @@ package com.iluwatar.mute; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.io.ByteArrayOutputStream; import java.io.IOException; import java.sql.SQLException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** - * Mute pattern is utilized when we need to suppress an exception due to an API flaw or in - * situation when all we can do to handle the exception is to log it. - * This pattern should not be used everywhere. It is very important to logically handle the - * exceptions in a system, but some situations like the ones described above require this pattern, - * so that we don't need to repeat + * Mute pattern is utilized when we need to suppress an exception due to an API flaw or in situation + * when all we can do to handle the exception is to log it. This pattern should not be used + * everywhere. It is very important to logically handle the exceptions in a system, but some + * situations like the ones described above require this pattern, so that we don't need to repeat *

  * 
  *   try {
@@ -45,7 +43,6 @@
  *   }
  * 
  * 
every time we need to ignore an exception. - * */ public class App { @@ -53,7 +50,7 @@ public class App { /** * Program entry point. - * + * * @param args command line args. * @throws Exception if any exception occurs */ @@ -65,7 +62,7 @@ public static void main(String[] args) throws Exception { } /* - * Typically used when the API declares some exception but cannot do so. Usually a + * Typically used when the API declares some exception but cannot do so. Usually a * signature mistake.In this example out is not supposed to throw exception as it is a * ByteArrayOutputStream. So we utilize mute, which will throw AssertionError if unexpected * exception occurs. @@ -98,7 +95,7 @@ private static void utilizeResource(Resource resource) throws SQLException { private static Resource acquireResource() throws SQLException { return new Resource() { - + @Override public void close() throws IOException { throw new IOException("Error in closing resource: " + this); diff --git a/mute-idiom/src/main/java/com/iluwatar/mute/CheckedRunnable.java b/mute-idiom/src/main/java/com/iluwatar/mute/CheckedRunnable.java index d5fdaaec2b34..f15153d0083d 100644 --- a/mute-idiom/src/main/java/com/iluwatar/mute/CheckedRunnable.java +++ b/mute-idiom/src/main/java/com/iluwatar/mute/CheckedRunnable.java @@ -25,12 +25,12 @@ /** * A runnable which may throw exception on execution. - * */ @FunctionalInterface public interface CheckedRunnable { /** * Same as {@link Runnable#run()} with a possibility of exception in execution. + * * @throws Exception if any exception occurs. */ void run() throws Exception; diff --git a/mute-idiom/src/main/java/com/iluwatar/mute/Mute.java b/mute-idiom/src/main/java/com/iluwatar/mute/Mute.java index 87a1f651e77f..30e1698d5d1b 100644 --- a/mute-idiom/src/main/java/com/iluwatar/mute/Mute.java +++ b/mute-idiom/src/main/java/com/iluwatar/mute/Mute.java @@ -30,17 +30,18 @@ * A utility class that allows you to utilize mute idiom. */ public final class Mute { - + // The constructor is never meant to be called. - private Mute() {} + private Mute() { + } /** - * Executes the runnable and throws the exception occurred within a {@link AssertionError}. - * This method should be utilized to mute the operations that are guaranteed not to throw an exception. - * For instance {@link ByteArrayOutputStream#write(byte[])} declares in it's signature that it can throw - * an {@link IOException}, but in reality it cannot. This is because the bulk write method is not overridden - * in {@link ByteArrayOutputStream}. - * + * Executes the runnable and throws the exception occurred within a {@link + * AssertionError}. This method should be utilized to mute the operations that are guaranteed not + * to throw an exception. For instance {@link ByteArrayOutputStream#write(byte[])} declares in + * it's signature that it can throw an {@link IOException}, but in reality it cannot. This is + * because the bulk write method is not overridden in {@link ByteArrayOutputStream}. + * * @param runnable a runnable that should never throw an exception on execution. */ public static void mute(CheckedRunnable runnable) { @@ -52,11 +53,11 @@ public static void mute(CheckedRunnable runnable) { } /** - * Executes the runnable and logs the exception occurred on {@link System#err}. - * This method should be utilized to mute the operations about which most you can do is log. - * For instance while closing a connection to database, or cleaning up a resource, - * all you can do is log the exception occurred. - * + * Executes the runnable and logs the exception occurred on {@link System#err}. This + * method should be utilized to mute the operations about which most you can do is log. For + * instance while closing a connection to database, or cleaning up a resource, all you can do is + * log the exception occurred. + * * @param runnable a runnable that may throw an exception on execution. */ public static void loggedMute(CheckedRunnable runnable) { diff --git a/mute-idiom/src/main/java/com/iluwatar/mute/Resource.java b/mute-idiom/src/main/java/com/iluwatar/mute/Resource.java index a10fe4617605..e56025ce4ea8 100644 --- a/mute-idiom/src/main/java/com/iluwatar/mute/Resource.java +++ b/mute-idiom/src/main/java/com/iluwatar/mute/Resource.java @@ -26,9 +26,8 @@ import java.io.Closeable; /** - * Represents any resource that the application might acquire and that must be closed - * after it is utilized. Example of such resources can be a database connection, open - * files, sockets. + * Represents any resource that the application might acquire and that must be closed after it is + * utilized. Example of such resources can be a database connection, open files, sockets. */ public interface Resource extends Closeable { diff --git a/mutex/src/main/java/com/iluwatar/mutex/App.java b/mutex/src/main/java/com/iluwatar/mutex/App.java index 827307d0f884..e4a952ef9f46 100644 --- a/mutex/src/main/java/com/iluwatar/mutex/App.java +++ b/mutex/src/main/java/com/iluwatar/mutex/App.java @@ -25,19 +25,17 @@ /** * A Mutex prevents multiple threads from accessing a resource simultaneously. - *

- * In this example we have two thieves who are taking beans from a jar. - * Only one thief can take a bean at a time. This is ensured by a Mutex lock - * which must be acquired in order to access the jar. Each thief attempts to - * acquire the lock, take a bean and then release the lock. If the lock has - * already been acquired, the thief will be prevented from continuing (blocked) - * until the lock has been released. The thieves stop taking beans once there - * are no beans left to take. + * + *

In this example we have two thieves who are taking beans from a jar. Only one thief can take + * a bean at a time. This is ensured by a Mutex lock which must be acquired in order to access the + * jar. Each thief attempts to acquire the lock, take a bean and then release the lock. If the lock + * has already been acquired, the thief will be prevented from continuing (blocked) until the lock + * has been released. The thieves stop taking beans once there are no beans left to take. */ public class App { /** - * main method + * main method. */ public static void main(String[] args) { Mutex mutex = new Mutex(); diff --git a/mutex/src/main/java/com/iluwatar/mutex/Jar.java b/mutex/src/main/java/com/iluwatar/mutex/Jar.java index 427907f31d90..f68b266add5f 100644 --- a/mutex/src/main/java/com/iluwatar/mutex/Jar.java +++ b/mutex/src/main/java/com/iluwatar/mutex/Jar.java @@ -24,9 +24,8 @@ package com.iluwatar.mutex; /** - * A Jar has a resource of beans which can only be accessed by a single Thief - * (thread) at any one time. A Mutex lock is used to prevent more than one Thief - * taking a bean simultaneously. + * A Jar has a resource of beans which can only be accessed by a single Thief (thread) at any one + * time. A Mutex lock is used to prevent more than one Thief taking a bean simultaneously. */ public class Jar { diff --git a/mutex/src/main/java/com/iluwatar/mutex/Mutex.java b/mutex/src/main/java/com/iluwatar/mutex/Mutex.java index a2ef71f11d1f..6c62cc8ea930 100644 --- a/mutex/src/main/java/com/iluwatar/mutex/Mutex.java +++ b/mutex/src/main/java/com/iluwatar/mutex/Mutex.java @@ -34,16 +34,15 @@ public class Mutex implements Lock { private Object owner; /** - * Returns the current owner of the Mutex, or null if available + * Returns the current owner of the Mutex, or null if available. */ public Object getOwner() { return owner; } - + /** - * Method called by a thread to acquire the lock. If the lock has already - * been acquired this will wait until the lock has been released to - * re-attempt the acquire. + * Method called by a thread to acquire the lock. If the lock has already been acquired this will + * wait until the lock has been released to re-attempt the acquire. */ @Override public synchronized void acquire() throws InterruptedException { diff --git a/mutex/src/main/java/com/iluwatar/mutex/Thief.java b/mutex/src/main/java/com/iluwatar/mutex/Thief.java index f88e46d96fab..29caba540ad1 100644 --- a/mutex/src/main/java/com/iluwatar/mutex/Thief.java +++ b/mutex/src/main/java/com/iluwatar/mutex/Thief.java @@ -27,20 +27,20 @@ import org.slf4j.LoggerFactory; /** - * Thief is a class which continually tries to acquire a jar and take a bean - * from it. When the jar is empty the thief stops. + * Thief is a class which continually tries to acquire a jar and take a bean from it. When the jar + * is empty the thief stops. */ public class Thief extends Thread { private static final Logger LOGGER = LoggerFactory.getLogger(Thief.class); /** - * The name of the thief. + * The name of the thief. */ private final String name; - + /** - * The jar + * The jar. */ private final Jar jar; @@ -50,8 +50,7 @@ public Thief(String name, Jar jar) { } /** - * In the run method the thief repeatedly tries to take a bean until none - * are left. + * In the run method the thief repeatedly tries to take a bean until none are left. */ @Override public void run() { From 271d7ae9bdfc835c5b5f62c21f1d8c630cab7647 Mon Sep 17 00:00:00 2001 From: Anurag Agarwal Date: Sat, 16 Nov 2019 18:26:26 +0530 Subject: [PATCH 23/31] Resolves checkstyle errors for remaining p (#1091) * Reduces checkstyle errors in page-object * Reduces checkstyle errors in partial-response * Reduces checkstyle errors in pipeline * Reduces checkstyle errors in poison-pill * Reduces checkstyle errors in priority-queue * Reduces checkstyle errors in private-class-data * Reduces checkstyle errors in property * Reduces checkstyle errors in prototype * Reduces checkstyle errors in proxy --- .../java/com/iluwatar/pageobject/App.java | 51 +++++++++---------- .../java/com/iluwatar/pageobject/App.java | 47 ++++++++--------- .../iluwatar/pageobject/AlbumListPage.java | 8 ++- .../com/iluwatar/pageobject/AlbumPage.java | 29 +++++------ .../com/iluwatar/pageobject/LoginPage.java | 18 +++---- .../java/com/iluwatar/pageobject/Page.java | 9 ++-- .../com/iluwatar/partialresponse/App.java | 26 +++++----- .../partialresponse/FieldJsonMapper.java | 4 +- .../com/iluwatar/partialresponse/Video.java | 27 +++++----- .../partialresponse/VideoResource.java | 8 ++- .../main/java/com/iluwatar/pipeline/App.java | 19 ++++--- .../pipeline/ConvertToCharArrayHandler.java | 9 ++-- .../java/com/iluwatar/pipeline/Handler.java | 4 +- .../java/com/iluwatar/pipeline/Pipeline.java | 5 +- .../pipeline/RemoveAlphabetsHandler.java | 12 +++-- .../pipeline/RemoveDigitsHandler.java | 8 +-- .../java/com/iluwatar/poison/pill/App.java | 9 ++-- .../com/iluwatar/poison/pill/Consumer.java | 6 +-- .../com/iluwatar/poison/pill/Message.java | 2 +- .../iluwatar/poison/pill/MessageQueue.java | 2 +- .../iluwatar/poison/pill/MqPublishPoint.java | 2 +- .../poison/pill/MqSubscribePoint.java | 2 +- .../com/iluwatar/poison/pill/Producer.java | 11 ++-- .../iluwatar/poison/pill/SimpleMessage.java | 2 +- .../poison/pill/SimpleMessageQueue.java | 2 +- .../iluwatar/priority/queue/Application.java | 11 ++-- .../com/iluwatar/priority/queue/Message.java | 2 +- .../priority/queue/PriorityMessageQueue.java | 12 ++--- .../iluwatar/priority/queue/QueueManager.java | 6 +-- .../com/iluwatar/priority/queue/Worker.java | 6 +-- .../com/iluwatar/privateclassdata/App.java | 20 ++++---- .../privateclassdata/ImmutableStew.java | 11 ++-- .../com/iluwatar/privateclassdata/Stew.java | 10 ++-- .../iluwatar/privateclassdata/StewData.java | 6 +-- .../main/java/com/iluwatar/property/App.java | 22 ++++---- .../java/com/iluwatar/property/Character.java | 40 ++++++++------- .../java/com/iluwatar/property/Prototype.java | 2 +- .../java/com/iluwatar/property/Stats.java | 2 +- .../main/java/com/iluwatar/prototype/App.java | 36 ++++++------- .../java/com/iluwatar/prototype/Beast.java | 4 +- .../java/com/iluwatar/prototype/ElfBeast.java | 6 +-- .../java/com/iluwatar/prototype/ElfMage.java | 8 ++- .../com/iluwatar/prototype/ElfWarlord.java | 6 +-- .../com/iluwatar/prototype/HeroFactory.java | 2 - .../iluwatar/prototype/HeroFactoryImpl.java | 10 ++-- .../java/com/iluwatar/prototype/Mage.java | 4 +- .../java/com/iluwatar/prototype/OrcBeast.java | 10 ++-- .../java/com/iluwatar/prototype/OrcMage.java | 6 +-- .../com/iluwatar/prototype/OrcWarlord.java | 6 +-- .../com/iluwatar/prototype/Prototype.java | 4 +- .../java/com/iluwatar/prototype/Warlord.java | 4 +- .../src/main/java/com/iluwatar/proxy/App.java | 12 ++--- .../java/com/iluwatar/proxy/IvoryTower.java | 2 - .../main/java/com/iluwatar/proxy/Wizard.java | 4 +- .../java/com/iluwatar/proxy/WizardTower.java | 2 +- .../com/iluwatar/proxy/WizardTowerProxy.java | 2 - 56 files changed, 284 insertions(+), 316 deletions(-) diff --git a/page-object/sample-application/src/main/java/com/iluwatar/pageobject/App.java b/page-object/sample-application/src/main/java/com/iluwatar/pageobject/App.java index aae08c15f80e..e3a86599c3fb 100644 --- a/page-object/sample-application/src/main/java/com/iluwatar/pageobject/App.java +++ b/page-object/sample-application/src/main/java/com/iluwatar/pageobject/App.java @@ -26,63 +26,60 @@ import java.awt.Desktop; import java.io.File; import java.io.IOException; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Page Object pattern wraps an UI component with an application specific API allowing you to - * manipulate the UI elements without having to dig around with the underlying UI technology used. This is - * especially useful for testing as it means your tests will be less brittle. Your tests can concentrate on - * the actual test cases where as the manipulation of the UI can be left to the internals of the page object - * itself. + * manipulate the UI elements without having to dig around with the underlying UI technology used. + * This is especially useful for testing as it means your tests will be less brittle. Your tests can + * concentrate on the actual test cases where as the manipulation of the UI can be left to the + * internals of the page object itself. * - *

- * Due to this reason, it has become very popular within the test automation community. - * In particular, it is very common in that the page object is used to represent the html pages of a - * web application that is under test. This web application is referred to as AUT (Application Under Test). - * A web browser automation tool/framework like Selenium for instance, is then used to drive the automating - * of the browser navigation and user actions journeys through this web application. Your test class would - * therefore only be responsible for particular test cases and page object would be used by the test class - * for UI manipulation required for the tests. + *

Due to this reason, it has become very popular within the test automation community. In + * particular, it is very common in that the page object is used to represent the html pages of a + * web application that is under test. This web application is referred to as AUT (Application Under + * Test). A web browser automation tool/framework like Selenium for instance, is then used to drive + * the automating of the browser navigation and user actions journeys through this web application. + * Your test class would therefore only be responsible for particular test cases and page object + * would be used by the test class for UI manipulation required for the tests. * - *

- * In this implementation rather than using Selenium, the HtmlUnit library is used as a replacement to - * represent the specific html elements and to drive the browser. The purpose of this example is just to - * provide a simple version that showcase the intentions of this pattern and how this pattern is used - * in order to understand it. + *

In this implementation rather than using Selenium, the HtmlUnit library is used as a + * replacement to represent the specific html elements and to drive the browser. The purpose of this + * example is just to provide a simple version that showcase the intentions of this pattern and how + * this pattern is used in order to understand it. */ public final class App { private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + private App() { } /** * Application entry point * - *

- * The application under development is a web application. Normally you would probably have a - * backend that is probably implemented in an object-oriented language (e.g. Java) that serves - * the frontend which comprises of a series of HTML, CSS, JS etc... + *

The application under development is a web application. Normally you would probably have a + * backend that is probably implemented in an object-oriented language (e.g. Java) that serves the + * frontend which comprises of a series of HTML, CSS, JS etc... * - *

- * For illustrations purposes only, a very simple static html app is used here. This main method - * just fires up this simple web app in a default browser. + *

For illustrations purposes only, a very simple static html app is used here. This main + * method just fires up this simple web app in a default browser. * * @param args arguments */ public static void main(String[] args) { try { - File applicationFile = new File(App.class.getClassLoader().getResource("sample-ui/login.html").getPath()); + File applicationFile = + new File(App.class.getClassLoader().getResource("sample-ui/login.html").getPath()); // should work for unix like OS (mac, unix etc...) if (Desktop.isDesktopSupported()) { Desktop.getDesktop().open(applicationFile); } else { - // java Desktop not supported - above unlikely to work for Windows so try following instead... + // java Desktop not supported - above unlikely to work for Windows so try instead... Runtime.getRuntime().exec("cmd.exe start " + applicationFile); } diff --git a/page-object/src/main/java/com/iluwatar/pageobject/App.java b/page-object/src/main/java/com/iluwatar/pageobject/App.java index c76867e89899..9c4c21607979 100644 --- a/page-object/src/main/java/com/iluwatar/pageobject/App.java +++ b/page-object/src/main/java/com/iluwatar/pageobject/App.java @@ -29,25 +29,23 @@ /** * Page Object pattern wraps an UI component with an application specific API allowing you to - * manipulate the UI elements without having to dig around with the underlying UI technology used. This is - * especially useful for testing as it means your tests will be less brittle. Your tests can concentrate on - * the actual test cases where as the manipulation of the UI can be left to the internals of the page object - * itself. + * manipulate the UI elements without having to dig around with the underlying UI technology used. + * This is especially useful for testing as it means your tests will be less brittle. Your tests can + * concentrate on the actual test cases where as the manipulation of the UI can be left to the + * internals of the page object itself. * - *

- * Due to this reason, it has become very popular within the test automation community. - * In particular, it is very common in that the page object is used to represent the html pages of a - * web application that is under test. This web application is referred to as AUT (Application Under Test). - * A web browser automation tool/framework like Selenium for instance, is then used to drive the automating - * of the browser navigation and user actions journeys through this web application. Your test class would - * therefore only be responsible for particular test cases and page object would be used by the test class - * for UI manipulation required for the tests. + *

Due to this reason, it has become very popular within the test automation community. In + * particular, it is very common in that the page object is used to represent the html pages of a + * web application that is under test. This web application is referred to as AUT (Application Under + * Test). A web browser automation tool/framework like Selenium for instance, is then used to drive + * the automating of the browser navigation and user actions journeys through this web application. + * Your test class would therefore only be responsible for particular test cases and page object + * would be used by the test class for UI manipulation required for the tests. * - *

- * In this implementation rather than using Selenium, the HtmlUnit library is used as a replacement to - * represent the specific html elements and to drive the browser. The purpose of this example is just to - * provide a simple version that showcase the intentions of this pattern and how this pattern is used - * in order to understand it. + *

In this implementation rather than using Selenium, the HtmlUnit library is used as a + * replacement to represent the specific html elements and to drive the browser. The purpose of this + * example is just to provide a simple version that showcase the intentions of this pattern and how + * this pattern is used in order to understand it. */ public final class App { @@ -57,21 +55,20 @@ private App() { /** * Application entry point * - *

- * The application under development is a web application. Normally you would probably have a - * backend that is probably implemented in an object-oriented language (e.g. Java) that serves - * the frontend which comprises of a series of HTML, CSS, JS etc... + *

The application under development is a web application. Normally you would probably have a + * backend that is probably implemented in an object-oriented language (e.g. Java) that serves the + * frontend which comprises of a series of HTML, CSS, JS etc... * - *

- * For illustrations purposes only, a very simple static html app is used here. This main method - * just fires up this simple web app in a default browser. + *

For illustrations purposes only, a very simple static html app is used here. This main + * method just fires up this simple web app in a default browser. * * @param args arguments */ public static void main(String[] args) { try { - File applicationFile = new File(App.class.getClassLoader().getResource("sample-ui/login.html").getPath()); + File applicationFile = + new File(App.class.getClassLoader().getResource("sample-ui/login.html").getPath()); // should work for unix like OS (mac, unix etc...) if (Desktop.isDesktopSupported()) { diff --git a/page-object/test-automation/src/main/java/com/iluwatar/pageobject/AlbumListPage.java b/page-object/test-automation/src/main/java/com/iluwatar/pageobject/AlbumListPage.java index feab7838c7bd..2851d24d54c1 100644 --- a/page-object/test-automation/src/main/java/com/iluwatar/pageobject/AlbumListPage.java +++ b/page-object/test-automation/src/main/java/com/iluwatar/pageobject/AlbumListPage.java @@ -26,10 +26,8 @@ import com.gargoylesoftware.htmlunit.WebClient; import com.gargoylesoftware.htmlunit.html.HtmlAnchor; import com.gargoylesoftware.htmlunit.html.HtmlPage; - import java.io.IOException; import java.util.List; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -46,7 +44,7 @@ public class AlbumListPage extends Page { /** - * Constructor + * Constructor. */ public AlbumListPage(WebClient webClient) { super(webClient); @@ -54,7 +52,7 @@ public AlbumListPage(WebClient webClient) { /** - * Navigates to the Album List Page + * Navigates to the Album List Page. * * @return {@link AlbumListPage} */ @@ -76,7 +74,7 @@ public boolean isAt() { } /** - * Selects an album by the given album title + * Selects an album by the given album title. * * @param albumTitle the title of the album to click * @return the album page diff --git a/page-object/test-automation/src/main/java/com/iluwatar/pageobject/AlbumPage.java b/page-object/test-automation/src/main/java/com/iluwatar/pageobject/AlbumPage.java index cf8c50dd74a1..953a47ba2e39 100644 --- a/page-object/test-automation/src/main/java/com/iluwatar/pageobject/AlbumPage.java +++ b/page-object/test-automation/src/main/java/com/iluwatar/pageobject/AlbumPage.java @@ -23,11 +23,6 @@ package com.iluwatar.pageobject; -import java.io.IOException; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.gargoylesoftware.htmlunit.WebClient; import com.gargoylesoftware.htmlunit.html.HtmlNumberInput; import com.gargoylesoftware.htmlunit.html.HtmlOption; @@ -35,6 +30,9 @@ import com.gargoylesoftware.htmlunit.html.HtmlSelect; import com.gargoylesoftware.htmlunit.html.HtmlSubmitInput; import com.gargoylesoftware.htmlunit.html.HtmlTextInput; +import java.io.IOException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Page Object encapsulating the Album Page (album-page.html) @@ -49,7 +47,7 @@ public class AlbumPage extends Page { /** - * Constructor + * Constructor. */ public AlbumPage(WebClient webClient) { super(webClient); @@ -57,7 +55,7 @@ public AlbumPage(WebClient webClient) { /** - * Navigates to the album page + * Navigates to the album page. * * @return {@link AlbumPage} */ @@ -81,7 +79,7 @@ public boolean isAt() { /** - * Sets the album title input text field + * Sets the album title input text field. * * @param albumTitle the new album title value to set * @return {@link AlbumPage} @@ -94,7 +92,7 @@ public AlbumPage changeAlbumTitle(String albumTitle) { /** - * Sets the artist input text field + * Sets the artist input text field. * * @param artist the new artist value to set * @return {@link AlbumPage} @@ -107,7 +105,7 @@ public AlbumPage changeArtist(String artist) { /** - * Selects the select's option value based on the year value given + * Selects the select's option value based on the year value given. * * @param year the new year value to set * @return {@link AlbumPage} @@ -121,7 +119,7 @@ public AlbumPage changeAlbumYear(int year) { /** - * Sets the album rating input text field + * Sets the album rating input text field. * * @param albumRating the new album rating value to set * @return {@link AlbumPage} @@ -133,20 +131,21 @@ public AlbumPage changeAlbumRating(String albumRating) { } /** - * Sets the number of songs number input field + * Sets the number of songs number input field. * * @param numberOfSongs the new number of songs value to be set * @return {@link AlbumPage} */ public AlbumPage changeNumberOfSongs(int numberOfSongs) { - HtmlNumberInput numberOfSongsNumberField = (HtmlNumberInput) page.getElementById("numberOfSongs"); + HtmlNumberInput numberOfSongsNumberField = + (HtmlNumberInput) page.getElementById("numberOfSongs"); numberOfSongsNumberField.setText(Integer.toString(numberOfSongs)); return this; } /** - * Cancel changes made by clicking the cancel button + * Cancel changes made by clicking the cancel button. * * @return {@link AlbumListPage} */ @@ -162,7 +161,7 @@ public AlbumListPage cancelChanges() { /** - * Saves changes made by clicking the save button + * Saves changes made by clicking the save button. * * @return {@link AlbumPage} */ diff --git a/page-object/test-automation/src/main/java/com/iluwatar/pageobject/LoginPage.java b/page-object/test-automation/src/main/java/com/iluwatar/pageobject/LoginPage.java index b139253a77fa..78d3fa329ab5 100644 --- a/page-object/test-automation/src/main/java/com/iluwatar/pageobject/LoginPage.java +++ b/page-object/test-automation/src/main/java/com/iluwatar/pageobject/LoginPage.java @@ -29,7 +29,6 @@ import com.gargoylesoftware.htmlunit.html.HtmlSubmitInput; import com.gargoylesoftware.htmlunit.html.HtmlTextInput; import java.io.IOException; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -45,7 +44,7 @@ public class LoginPage extends Page { private HtmlPage page; /** - * Constructor + * Constructor. * * @param webClient {@link WebClient} */ @@ -54,7 +53,7 @@ public LoginPage(WebClient webClient) { } /** - * Navigates to the Login page + * Navigates to the Login page. * * @return {@link LoginPage} */ @@ -77,7 +76,7 @@ public boolean isAt() { /** - * Enters the username into the username input text field + * Enters the username into the username input text field. * * @param username the username to enter * @return {@link LoginPage} @@ -90,23 +89,24 @@ public LoginPage enterUsername(String username) { /** - * Enters the password into the password input password field + * Enters the password into the password input password field. * * @param password the password to enter * @return {@link LoginPage} */ public LoginPage enterPassword(String password) { - HtmlPasswordInput passwordInputPasswordField = (HtmlPasswordInput) page.getElementById("password"); + HtmlPasswordInput passwordInputPasswordField = + (HtmlPasswordInput) page.getElementById("password"); passwordInputPasswordField.setText(password); return this; } /** - * Clicking on the login button to 'login' + * Clicking on the login button to 'login'. * - * @return {@link AlbumListPage} - * - this is the page that user gets navigated to once successfully logged in + * @return {@link AlbumListPage} - this is the page that user gets navigated to once successfully + * logged in */ public AlbumListPage login() { HtmlSubmitInput loginButton = (HtmlSubmitInput) page.getElementById("loginButton"); diff --git a/page-object/test-automation/src/main/java/com/iluwatar/pageobject/Page.java b/page-object/test-automation/src/main/java/com/iluwatar/pageobject/Page.java index 78bc4618c407..ddf7ec63ed54 100644 --- a/page-object/test-automation/src/main/java/com/iluwatar/pageobject/Page.java +++ b/page-object/test-automation/src/main/java/com/iluwatar/pageobject/Page.java @@ -26,20 +26,19 @@ import com.gargoylesoftware.htmlunit.WebClient; /** - * Encapsulation for a generic 'Page' + * Encapsulation for a generic 'Page'. */ public abstract class Page { /** - * Application Under Test path - * This directory location is where html web pages are located + * Application Under Test path This directory location is where html web pages are located. */ public static final String AUT_PATH = "../sample-application/src/main/resources/sample-ui/"; protected final WebClient webClient; /** - * Constructor + * Constructor. * * @param webClient {@link WebClient} */ @@ -48,7 +47,7 @@ public Page(WebClient webClient) { } /** - * Checks that the current page is actually the page this page object represents + * Checks that the current page is actually the page this page object represents. * * @return true if so, otherwise false */ diff --git a/partial-response/src/main/java/com/iluwatar/partialresponse/App.java b/partial-response/src/main/java/com/iluwatar/partialresponse/App.java index 314846a3dbe5..5a3e7d950e0d 100644 --- a/partial-response/src/main/java/com/iluwatar/partialresponse/App.java +++ b/partial-response/src/main/java/com/iluwatar/partialresponse/App.java @@ -23,18 +23,16 @@ package com.iluwatar.partialresponse; +import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Map; - /** - * The Partial response pattern is a design pattern in which client specifies fields to fetch to serve. - * Here {@link App} is playing as client for {@link VideoResource} server. - * Client ask for specific fields information in video to server. - *

- *

- * {@link VideoResource} act as server to serve video information. + * The Partial response pattern is a design pattern in which client specifies fields to fetch to + * serve. Here {@link App} is playing as client for {@link VideoResource} server. Client ask for + * specific fields information in video to server. + * + *

{@link VideoResource} act as server to serve video information. */ public class App { @@ -47,12 +45,12 @@ public class App { */ public static void main(String[] args) throws Exception { Map videos = Map.of( - 1, new Video(1, "Avatar", 178, "epic science fiction film", - "James Cameron", "English"), - 2, new Video(2, "Godzilla Resurgence", 120, "Action & drama movie|", - "Hideaki Anno", "Japanese"), - 3, new Video(3, "Interstellar", 169, "Adventure & Sci-Fi", - "Christopher Nolan", "English")); + 1, new Video(1, "Avatar", 178, "epic science fiction film", + "James Cameron", "English"), + 2, new Video(2, "Godzilla Resurgence", 120, "Action & drama movie|", + "Hideaki Anno", "Japanese"), + 3, new Video(3, "Interstellar", 169, "Adventure & Sci-Fi", + "Christopher Nolan", "English")); VideoResource videoResource = new VideoResource(new FieldJsonMapper(), videos); diff --git a/partial-response/src/main/java/com/iluwatar/partialresponse/FieldJsonMapper.java b/partial-response/src/main/java/com/iluwatar/partialresponse/FieldJsonMapper.java index da1d22620c31..f735b4d2b847 100644 --- a/partial-response/src/main/java/com/iluwatar/partialresponse/FieldJsonMapper.java +++ b/partial-response/src/main/java/com/iluwatar/partialresponse/FieldJsonMapper.java @@ -26,11 +26,13 @@ import java.lang.reflect.Field; /** - * Map a video to json + * Map a video to json. */ public class FieldJsonMapper { /** + * Gets json of required fields from video. + * * @param video object containing video information * @param fields fields information to get * @return json of required fields from video diff --git a/partial-response/src/main/java/com/iluwatar/partialresponse/Video.java b/partial-response/src/main/java/com/iluwatar/partialresponse/Video.java index fcfda7497f95..9e3ad5ea3ccb 100644 --- a/partial-response/src/main/java/com/iluwatar/partialresponse/Video.java +++ b/partial-response/src/main/java/com/iluwatar/partialresponse/Video.java @@ -24,8 +24,7 @@ package com.iluwatar.partialresponse; /** - * {@link Video} is a entity to serve from server.It contains all video related information.. - *

+ * {@link Video} is a entity to serve from server.It contains all video related information. */ public class Video { private final Integer id; @@ -36,23 +35,27 @@ public class Video { private final String language; /** - * @param id video unique id - * @param title video title - * @param length video length in minutes - * @param description video description by publisher - * @param director video director name - * @param language video language {private, public} + * Constructor. + * + * @param id video unique id + * @param title video title + * @param len video length in minutes + * @param desc video description by publisher + * @param director video director name + * @param lang video language {private, public} */ - public Video(Integer id, String title, Integer length, String description, String director, String language) { + public Video(Integer id, String title, Integer len, String desc, String director, String lang) { this.id = id; this.title = title; - this.length = length; - this.description = description; + this.length = len; + this.description = desc; this.director = director; - this.language = language; + this.language = lang; } /** + * ToString. + * * @return json representaion of video */ @Override diff --git a/partial-response/src/main/java/com/iluwatar/partialresponse/VideoResource.java b/partial-response/src/main/java/com/iluwatar/partialresponse/VideoResource.java index d0d77af05151..a61a3c429e8a 100644 --- a/partial-response/src/main/java/com/iluwatar/partialresponse/VideoResource.java +++ b/partial-response/src/main/java/com/iluwatar/partialresponse/VideoResource.java @@ -26,14 +26,16 @@ import java.util.Map; /** - * The resource class which serves video information. - * This class act as server in the demo. Which has all video details. + * The resource class which serves video information. This class act as server in the demo. Which + * has all video details. */ public class VideoResource { private FieldJsonMapper fieldJsonMapper; private Map videos; /** + * Constructor. + * * @param fieldJsonMapper map object to json. * @param videos initialize resource with existing videos. Act as database. */ @@ -43,6 +45,8 @@ public VideoResource(FieldJsonMapper fieldJsonMapper, Map videos } /** + * Get Details. + * * @param id video id * @param fields fields to get information about * @return full response if no fields specified else partial response for given field. diff --git a/pipeline/src/main/java/com/iluwatar/pipeline/App.java b/pipeline/src/main/java/com/iluwatar/pipeline/App.java index 3298a6eb69b2..1b1e443e6456 100644 --- a/pipeline/src/main/java/com/iluwatar/pipeline/App.java +++ b/pipeline/src/main/java/com/iluwatar/pipeline/App.java @@ -24,21 +24,20 @@ package com.iluwatar.pipeline; /** - * The Pipeline pattern uses ordered stages to process a sequence of input values. - * Each implemented task is represented by a stage of the pipeline. You can think of - * pipelines as similar to assembly lines in a factory, where each item in the assembly - * line is constructed in stages. The partially assembled item is passed from one assembly - * stage to another. The outputs of the assembly line occur in the same order as that of the - * inputs. + * The Pipeline pattern uses ordered stages to process a sequence of input values. Each implemented + * task is represented by a stage of the pipeline. You can think of pipelines as similar to assembly + * lines in a factory, where each item in the assembly line is constructed in stages. The partially + * assembled item is passed from one assembly stage to another. The outputs of the assembly line + * occur in the same order as that of the inputs. * - * Classes used in this example are suffixed with "Handlers", and synonymously refers to the + *

Classes used in this example are suffixed with "Handlers", and synonymously refers to the * "stage". */ public class App { /** - * Specify the initial input type for the first stage handler and the expected output type - * of the last stage handler as type parameters for Pipeline. Use the fluent builder by - * calling addHandler to add more stage handlers on the pipeline. + * Specify the initial input type for the first stage handler and the expected output type of the + * last stage handler as type parameters for Pipeline. Use the fluent builder by calling + * addHandler to add more stage handlers on the pipeline. */ public static void main(String[] args) { /* diff --git a/pipeline/src/main/java/com/iluwatar/pipeline/ConvertToCharArrayHandler.java b/pipeline/src/main/java/com/iluwatar/pipeline/ConvertToCharArrayHandler.java index 104d81f40b88..365fc1cdc2e4 100644 --- a/pipeline/src/main/java/com/iluwatar/pipeline/ConvertToCharArrayHandler.java +++ b/pipeline/src/main/java/com/iluwatar/pipeline/ConvertToCharArrayHandler.java @@ -23,11 +23,10 @@ package com.iluwatar.pipeline; +import java.util.Arrays; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Arrays; - /** * Stage handler that converts an input String to its char[] array counterpart. */ @@ -38,8 +37,10 @@ class ConvertToCharArrayHandler implements Handler { @Override public char[] process(String input) { char[] characters = input.toCharArray(); - LOGGER.info(String.format("Current handler: %s, input is %s of type %s, output is %s, of type %s", - ConvertToCharArrayHandler.class, input, String.class, Arrays.toString(characters), Character[].class)); + LOGGER + .info(String.format("Current handler: %s, input is %s of type %s, output is %s, of type %s", + ConvertToCharArrayHandler.class, input, String.class, Arrays + .toString(characters), Character[].class)); return characters; } diff --git a/pipeline/src/main/java/com/iluwatar/pipeline/Handler.java b/pipeline/src/main/java/com/iluwatar/pipeline/Handler.java index 253bc22f5607..5591632e08ba 100644 --- a/pipeline/src/main/java/com/iluwatar/pipeline/Handler.java +++ b/pipeline/src/main/java/com/iluwatar/pipeline/Handler.java @@ -24,7 +24,9 @@ package com.iluwatar.pipeline; /** - * Forms a contract to all stage handlers to accept a certain type of input and return a processed output. + * Forms a contract to all stage handlers to accept a certain type of input and return a processed + * output. + * * @param the input type of the handler * @param the processed output type of the handler */ diff --git a/pipeline/src/main/java/com/iluwatar/pipeline/Pipeline.java b/pipeline/src/main/java/com/iluwatar/pipeline/Pipeline.java index af5c69b1d77c..81b63e6cfdcf 100644 --- a/pipeline/src/main/java/com/iluwatar/pipeline/Pipeline.java +++ b/pipeline/src/main/java/com/iluwatar/pipeline/Pipeline.java @@ -24,8 +24,9 @@ package com.iluwatar.pipeline; /** - * Main Pipeline class that initially sets the current handler. Processed output - * of the initial handler is then passed as the input to the next stage handlers. + * Main Pipeline class that initially sets the current handler. Processed output of the initial + * handler is then passed as the input to the next stage handlers. + * * @param the type of the input for the first stage handler * @param the final stage handler's output type */ diff --git a/pipeline/src/main/java/com/iluwatar/pipeline/RemoveAlphabetsHandler.java b/pipeline/src/main/java/com/iluwatar/pipeline/RemoveAlphabetsHandler.java index 930332671c3d..b2ed938cf100 100644 --- a/pipeline/src/main/java/com/iluwatar/pipeline/RemoveAlphabetsHandler.java +++ b/pipeline/src/main/java/com/iluwatar/pipeline/RemoveAlphabetsHandler.java @@ -27,7 +27,8 @@ import org.slf4j.LoggerFactory; /** - * Stage handler that returns a new instance of String without the alphabet characters of the input string. + * Stage handler that returns a new instance of String without the alphabet characters of the input + * string. */ class RemoveAlphabetsHandler implements Handler { @@ -47,8 +48,13 @@ public String process(String input) { } String inputWithoutAlphabetsStr = inputWithoutAlphabets.toString(); - LOGGER.info(String.format("Current handler: %s, input is %s of type %s, output is %s, of type %s", - RemoveAlphabetsHandler.class, input, String.class, inputWithoutAlphabetsStr, String.class)); + LOGGER.info( + String.format( + "Current handler: %s, input is %s of type %s, output is %s, of type %s", + RemoveAlphabetsHandler.class, input, + String.class, inputWithoutAlphabetsStr, String.class + ) + ); return inputWithoutAlphabetsStr; } diff --git a/pipeline/src/main/java/com/iluwatar/pipeline/RemoveDigitsHandler.java b/pipeline/src/main/java/com/iluwatar/pipeline/RemoveDigitsHandler.java index 6fd591006c55..450bef7177ea 100644 --- a/pipeline/src/main/java/com/iluwatar/pipeline/RemoveDigitsHandler.java +++ b/pipeline/src/main/java/com/iluwatar/pipeline/RemoveDigitsHandler.java @@ -27,7 +27,8 @@ import org.slf4j.LoggerFactory; /** - * Stage handler that returns a new instance of String without the digit characters of the input string. + * Stage handler that returns a new instance of String without the digit characters of the input + * string. */ class RemoveDigitsHandler implements Handler { @@ -47,8 +48,9 @@ public String process(String input) { } String inputWithoutDigitsStr = inputWithoutDigits.toString(); - LOGGER.info(String.format("Current handler: %s, input is %s of type %s, output is %s, of type %s", - RemoveDigitsHandler.class, input, String.class, inputWithoutDigitsStr, String.class)); + LOGGER + .info(String.format("Current handler: %s, input is %s of type %s, output is %s, of type %s", + RemoveDigitsHandler.class, input, String.class, inputWithoutDigitsStr, String.class)); return inputWithoutDigitsStr; } diff --git a/poison-pill/src/main/java/com/iluwatar/poison/pill/App.java b/poison-pill/src/main/java/com/iluwatar/poison/pill/App.java index 6d6a41eb9970..7fdf71a09b3b 100644 --- a/poison-pill/src/main/java/com/iluwatar/poison/pill/App.java +++ b/poison-pill/src/main/java/com/iluwatar/poison/pill/App.java @@ -30,16 +30,15 @@ * Pill will stop reading messages from the queue. You must also ensure that the Poison Pill will be * the last message that will be read from the queue (if you have prioritized queue then this can be * tricky). - *

- * In simple cases the Poison Pill can be just a null-reference, but holding a unique separate + * + *

In simple cases the Poison Pill can be just a null-reference, but holding a unique separate * shared object-marker (with name "Poison" or "Poison Pill") is more clear and self describing. - * */ public class App { /** - * Program entry point - * + * Program entry point. + * * @param args command line args */ public static void main(String[] args) { diff --git a/poison-pill/src/main/java/com/iluwatar/poison/pill/Consumer.java b/poison-pill/src/main/java/com/iluwatar/poison/pill/Consumer.java index 12cc246d8d28..25d2338e1226 100644 --- a/poison-pill/src/main/java/com/iluwatar/poison/pill/Consumer.java +++ b/poison-pill/src/main/java/com/iluwatar/poison/pill/Consumer.java @@ -28,10 +28,10 @@ import org.slf4j.LoggerFactory; /** - * Class responsible for receiving and handling submitted to the queue messages + * Class responsible for receiving and handling submitted to the queue messages. */ public class Consumer { - + private static final Logger LOGGER = LoggerFactory.getLogger(Consumer.class); private final MqSubscribePoint queue; @@ -43,7 +43,7 @@ public Consumer(String name, MqSubscribePoint queue) { } /** - * Consume message + * Consume message. */ public void consume() { while (true) { diff --git a/poison-pill/src/main/java/com/iluwatar/poison/pill/Message.java b/poison-pill/src/main/java/com/iluwatar/poison/pill/Message.java index 9b35bf53a569..b0298e4077cb 100644 --- a/poison-pill/src/main/java/com/iluwatar/poison/pill/Message.java +++ b/poison-pill/src/main/java/com/iluwatar/poison/pill/Message.java @@ -65,7 +65,7 @@ private RuntimeException poison() { }; /** - * Enumeration of Type of Headers + * Enumeration of Type of Headers. */ enum Headers { DATE, SENDER diff --git a/poison-pill/src/main/java/com/iluwatar/poison/pill/MessageQueue.java b/poison-pill/src/main/java/com/iluwatar/poison/pill/MessageQueue.java index ce8005fcebaf..2928e172d5d4 100644 --- a/poison-pill/src/main/java/com/iluwatar/poison/pill/MessageQueue.java +++ b/poison-pill/src/main/java/com/iluwatar/poison/pill/MessageQueue.java @@ -24,7 +24,7 @@ package com.iluwatar.poison.pill; /** - * Represents abstraction of channel (or pipe) that bounds {@link Producer} and {@link Consumer} + * Represents abstraction of channel (or pipe) that bounds {@link Producer} and {@link Consumer}. */ public interface MessageQueue extends MqPublishPoint, MqSubscribePoint { diff --git a/poison-pill/src/main/java/com/iluwatar/poison/pill/MqPublishPoint.java b/poison-pill/src/main/java/com/iluwatar/poison/pill/MqPublishPoint.java index b0e086637509..f61a579872a4 100644 --- a/poison-pill/src/main/java/com/iluwatar/poison/pill/MqPublishPoint.java +++ b/poison-pill/src/main/java/com/iluwatar/poison/pill/MqPublishPoint.java @@ -24,7 +24,7 @@ package com.iluwatar.poison.pill; /** - * Endpoint to publish {@link Message} to queue + * Endpoint to publish {@link Message} to queue. */ public interface MqPublishPoint { diff --git a/poison-pill/src/main/java/com/iluwatar/poison/pill/MqSubscribePoint.java b/poison-pill/src/main/java/com/iluwatar/poison/pill/MqSubscribePoint.java index bb01e6395f14..b7133de8c845 100644 --- a/poison-pill/src/main/java/com/iluwatar/poison/pill/MqSubscribePoint.java +++ b/poison-pill/src/main/java/com/iluwatar/poison/pill/MqSubscribePoint.java @@ -24,7 +24,7 @@ package com.iluwatar.poison.pill; /** - * Endpoint to retrieve {@link Message} from queue + * Endpoint to retrieve {@link Message} from queue. */ public interface MqSubscribePoint { diff --git a/poison-pill/src/main/java/com/iluwatar/poison/pill/Producer.java b/poison-pill/src/main/java/com/iluwatar/poison/pill/Producer.java index 0b746b31f3e7..679500e43317 100644 --- a/poison-pill/src/main/java/com/iluwatar/poison/pill/Producer.java +++ b/poison-pill/src/main/java/com/iluwatar/poison/pill/Producer.java @@ -23,15 +23,14 @@ package com.iluwatar.poison.pill; -import java.util.Date; - import com.iluwatar.poison.pill.Message.Headers; +import java.util.Date; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Class responsible for producing unit of work that can be expressed as message and submitted to - * queue + * queue. */ public class Producer { @@ -42,7 +41,7 @@ public class Producer { private boolean isStopped; /** - * Constructor + * Constructor. */ public Producer(String name, MqPublishPoint queue) { this.name = name; @@ -51,7 +50,7 @@ public Producer(String name, MqPublishPoint queue) { } /** - * Send message to queue + * Send message to queue. */ public void send(String body) { if (isStopped) { @@ -72,7 +71,7 @@ public void send(String body) { } /** - * Stop system by sending poison pill + * Stop system by sending poison pill. */ public void stop() { isStopped = true; diff --git a/poison-pill/src/main/java/com/iluwatar/poison/pill/SimpleMessage.java b/poison-pill/src/main/java/com/iluwatar/poison/pill/SimpleMessage.java index efc45fc83bef..8a7af515f7e8 100644 --- a/poison-pill/src/main/java/com/iluwatar/poison/pill/SimpleMessage.java +++ b/poison-pill/src/main/java/com/iluwatar/poison/pill/SimpleMessage.java @@ -28,7 +28,7 @@ import java.util.Map; /** - * {@link Message} basic implementation + * {@link Message} basic implementation. */ public class SimpleMessage implements Message { diff --git a/poison-pill/src/main/java/com/iluwatar/poison/pill/SimpleMessageQueue.java b/poison-pill/src/main/java/com/iluwatar/poison/pill/SimpleMessageQueue.java index 7f1b662cde71..f6a50d4ff030 100644 --- a/poison-pill/src/main/java/com/iluwatar/poison/pill/SimpleMessageQueue.java +++ b/poison-pill/src/main/java/com/iluwatar/poison/pill/SimpleMessageQueue.java @@ -27,7 +27,7 @@ import java.util.concurrent.BlockingQueue; /** - * Bounded blocking queue wrapper + * Bounded blocking queue wrapper. */ public class SimpleMessageQueue implements MessageQueue { diff --git a/priority-queue/src/main/java/com/iluwatar/priority/queue/Application.java b/priority-queue/src/main/java/com/iluwatar/priority/queue/Application.java index 1e6e44a68564..e803489b28d2 100644 --- a/priority-queue/src/main/java/com/iluwatar/priority/queue/Application.java +++ b/priority-queue/src/main/java/com/iluwatar/priority/queue/Application.java @@ -25,16 +25,15 @@ /** * Prioritize requests sent to services so that requests with a higher priority are received and - * processed more quickly than those of a lower priority. - * This pattern is useful in applications that offer different service level guarantees - * to individual clients. - * Example :Send multiple message with different priority to worker queue. - * Worker execute higher priority message first + * processed more quickly than those of a lower priority. This pattern is useful in applications + * that offer different service level guarantees to individual clients. Example :Send multiple + * message with different priority to worker queue. Worker execute higher priority message first + * * @see "https://docs.microsoft.com/en-us/previous-versions/msp-n-p/dn589794(v=pandp.10)" */ public class Application { /** - * main entry + * main entry. */ public static void main(String[] args) throws Exception { diff --git a/priority-queue/src/main/java/com/iluwatar/priority/queue/Message.java b/priority-queue/src/main/java/com/iluwatar/priority/queue/Message.java index b874bd677915..a9a3dcfa630c 100644 --- a/priority-queue/src/main/java/com/iluwatar/priority/queue/Message.java +++ b/priority-queue/src/main/java/com/iluwatar/priority/queue/Message.java @@ -24,7 +24,7 @@ package com.iluwatar.priority.queue; /** - * Message bean + * Message bean. */ public class Message implements Comparable { private final String message; diff --git a/priority-queue/src/main/java/com/iluwatar/priority/queue/PriorityMessageQueue.java b/priority-queue/src/main/java/com/iluwatar/priority/queue/PriorityMessageQueue.java index ff73a496ff58..66f4d4f591f6 100644 --- a/priority-queue/src/main/java/com/iluwatar/priority/queue/PriorityMessageQueue.java +++ b/priority-queue/src/main/java/com/iluwatar/priority/queue/PriorityMessageQueue.java @@ -23,11 +23,11 @@ package com.iluwatar.priority.queue; +import static java.util.Arrays.copyOf; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import static java.util.Arrays.copyOf; - /** * Keep high Priority message on top using maxHeap. * @@ -50,14 +50,14 @@ public PriorityMessageQueue(T[] queue) { } /** - * Remove top message from queue + * Remove top message from queue. */ public T remove() { if (isEmpty()) { return null; } - T root = queue[0]; + final T root = queue[0]; queue[0] = queue[size - 1]; size--; maxHeapifyDown(); @@ -65,7 +65,7 @@ public T remove() { } /** - * Add message to queue + * Add message to queue. */ public void add(T t) { ensureCapacity(); @@ -75,7 +75,7 @@ public void add(T t) { } /** - * Check queue size + * Check queue size. */ public boolean isEmpty() { return size == 0; diff --git a/priority-queue/src/main/java/com/iluwatar/priority/queue/QueueManager.java b/priority-queue/src/main/java/com/iluwatar/priority/queue/QueueManager.java index ade211766c3d..7eca0aca6d3d 100644 --- a/priority-queue/src/main/java/com/iluwatar/priority/queue/QueueManager.java +++ b/priority-queue/src/main/java/com/iluwatar/priority/queue/QueueManager.java @@ -24,7 +24,7 @@ package com.iluwatar.priority.queue; /** - * Manage priority queue + * Manage priority queue. */ public class QueueManager { /* @@ -37,7 +37,7 @@ public QueueManager(int initialCapacity) { } /** - * Publish message to queue + * Publish message to queue. */ public void publishMessage(Message message) { messagePriorityMessageQueue.add(message); @@ -45,7 +45,7 @@ public void publishMessage(Message message) { /** - * recive message from queue + * recive message from queue. */ public Message receiveMessage() { if (messagePriorityMessageQueue.isEmpty()) { diff --git a/priority-queue/src/main/java/com/iluwatar/priority/queue/Worker.java b/priority-queue/src/main/java/com/iluwatar/priority/queue/Worker.java index bbeb64b73a7e..18ed16199584 100644 --- a/priority-queue/src/main/java/com/iluwatar/priority/queue/Worker.java +++ b/priority-queue/src/main/java/com/iluwatar/priority/queue/Worker.java @@ -27,7 +27,7 @@ import org.slf4j.LoggerFactory; /** - * Message Worker + * Message Worker. */ public class Worker { @@ -40,7 +40,7 @@ public Worker(QueueManager queueManager) { } /** - * Keep checking queue for message + * Keep checking queue for message. */ @SuppressWarnings("squid:S2189") public void run() throws Exception { @@ -56,7 +56,7 @@ public void run() throws Exception { } /** - * Process message + * Process message. */ private void processMessage(Message message) { LOGGER.info(message.toString()); diff --git a/private-class-data/src/main/java/com/iluwatar/privateclassdata/App.java b/private-class-data/src/main/java/com/iluwatar/privateclassdata/App.java index c5b75eee4a78..367baaf8b86c 100644 --- a/private-class-data/src/main/java/com/iluwatar/privateclassdata/App.java +++ b/private-class-data/src/main/java/com/iluwatar/privateclassdata/App.java @@ -24,26 +24,24 @@ package com.iluwatar.privateclassdata; /** - * * The Private Class Data design pattern seeks to reduce exposure of attributes by limiting their * visibility. It reduces the number of class attributes by encapsulating them in single data * object. It allows the class designer to remove write privilege of attributes that are intended to * be set only during construction, even from methods of the target class. - *

- * In the example we have normal {@link Stew} class with some ingredients given in constructor. Then - * we have methods to enumerate the ingredients and to taste the stew. The method for tasting the - * stew alters the private members of the {@link Stew} class. - * - * The problem is solved with the Private Class Data pattern. We introduce {@link ImmutableStew} - * class that contains {@link StewData}. The private data members of {@link Stew} are now in - * {@link StewData} and cannot be altered by {@link ImmutableStew} methods. * + *

In the example we have normal {@link Stew} class with some ingredients given in constructor. + * Then we have methods to enumerate the ingredients and to taste the stew. The method for tasting + * the stew alters the private members of the {@link Stew} class. + * + *

The problem is solved with the Private Class Data pattern. We introduce {@link ImmutableStew} + * class that contains {@link StewData}. The private data members of {@link Stew} are now in {@link + * StewData} and cannot be altered by {@link ImmutableStew} methods. */ public class App { /** - * Program entry point - * + * Program entry point. + * * @param args command line args */ public static void main(String[] args) { diff --git a/private-class-data/src/main/java/com/iluwatar/privateclassdata/ImmutableStew.java b/private-class-data/src/main/java/com/iluwatar/privateclassdata/ImmutableStew.java index 627d744620bd..695424695822 100644 --- a/private-class-data/src/main/java/com/iluwatar/privateclassdata/ImmutableStew.java +++ b/private-class-data/src/main/java/com/iluwatar/privateclassdata/ImmutableStew.java @@ -27,9 +27,7 @@ import org.slf4j.LoggerFactory; /** - * - * Immutable stew class, protected with Private Class Data pattern - * + * Immutable stew class, protected with Private Class Data pattern. */ public class ImmutableStew { @@ -42,10 +40,11 @@ public ImmutableStew(int numPotatoes, int numCarrots, int numMeat, int numPepper } /** - * Mix the stew + * Mix the stew. */ public void mix() { - LOGGER.info("Mixing the immutable stew we find: {} potatoes, {} carrots, {} meat and {} peppers", - data.getNumPotatoes(), data.getNumCarrots(), data.getNumMeat(), data.getNumPeppers()); + LOGGER + .info("Mixing the immutable stew we find: {} potatoes, {} carrots, {} meat and {} peppers", + data.getNumPotatoes(), data.getNumCarrots(), data.getNumMeat(), data.getNumPeppers()); } } diff --git a/private-class-data/src/main/java/com/iluwatar/privateclassdata/Stew.java b/private-class-data/src/main/java/com/iluwatar/privateclassdata/Stew.java index 6618ee5dac95..65ba6c08e568 100644 --- a/private-class-data/src/main/java/com/iluwatar/privateclassdata/Stew.java +++ b/private-class-data/src/main/java/com/iluwatar/privateclassdata/Stew.java @@ -27,9 +27,7 @@ import org.slf4j.LoggerFactory; /** - * - * Mutable stew class - * + * Mutable stew class. */ public class Stew { @@ -41,7 +39,7 @@ public class Stew { private int numPeppers; /** - * Constructor + * Constructor. */ public Stew(int numPotatoes, int numCarrots, int numMeat, int numPeppers) { this.numPotatoes = numPotatoes; @@ -51,7 +49,7 @@ public Stew(int numPotatoes, int numCarrots, int numMeat, int numPeppers) { } /** - * Mix the stew + * Mix the stew. */ public void mix() { LOGGER.info("Mixing the stew we find: {} potatoes, {} carrots, {} meat and {} peppers", @@ -59,7 +57,7 @@ public void mix() { } /** - * Taste the stew + * Taste the stew. */ public void taste() { LOGGER.info("Tasting the stew"); diff --git a/private-class-data/src/main/java/com/iluwatar/privateclassdata/StewData.java b/private-class-data/src/main/java/com/iluwatar/privateclassdata/StewData.java index c170a531ef1a..bcdaba3e9ce9 100644 --- a/private-class-data/src/main/java/com/iluwatar/privateclassdata/StewData.java +++ b/private-class-data/src/main/java/com/iluwatar/privateclassdata/StewData.java @@ -24,9 +24,7 @@ package com.iluwatar.privateclassdata; /** - * - * Stew ingredients - * + * Stew ingredients. */ public class StewData { @@ -36,7 +34,7 @@ public class StewData { private int numPeppers; /** - * Constructor + * Constructor. */ public StewData(int numPotatoes, int numCarrots, int numMeat, int numPeppers) { this.numPotatoes = numPotatoes; diff --git a/property/src/main/java/com/iluwatar/property/App.java b/property/src/main/java/com/iluwatar/property/App.java index a7045e6df6db..d37dd5fd7deb 100644 --- a/property/src/main/java/com/iluwatar/property/App.java +++ b/property/src/main/java/com/iluwatar/property/App.java @@ -28,25 +28,23 @@ import org.slf4j.LoggerFactory; /** - * * The Property pattern is also known as Prototype inheritance. - *

- * In prototype inheritance instead of classes, as opposite to Java class inheritance, objects are - * used to create another objects and object hierarchies. Hierarchies are created using prototype - * chain through delegation: every object has link to parent object. Any base (parent) object can be - * amended at runtime (by adding or removal of some property), and all child objects will be - * affected as result. - *

- * In this example we demonstrate {@link Character} instantiation using the Property pattern. - * + * + *

In prototype inheritance instead of classes, as opposite to Java class inheritance, objects + * are used to create another objects and object hierarchies. Hierarchies are created using + * prototype chain through delegation: every object has link to parent object. Any base (parent) + * object can be amended at runtime (by adding or removal of some property), and all child objects + * will be affected as result. + * + *

In this example we demonstrate {@link Character} instantiation using the Property pattern. */ public class App { private static final Logger LOGGER = LoggerFactory.getLogger(App.class); /** - * Program entry point - * + * Program entry point. + * * @param args command line args */ public static void main(String[] args) { diff --git a/property/src/main/java/com/iluwatar/property/Character.java b/property/src/main/java/com/iluwatar/property/Character.java index ef19f01072e6..bbe7014599f2 100644 --- a/property/src/main/java/com/iluwatar/property/Character.java +++ b/property/src/main/java/com/iluwatar/property/Character.java @@ -32,7 +32,7 @@ public class Character implements Prototype { /** - * Enumeration of Character types + * Enumeration of Character types. */ public enum Type { WARRIOR, MAGE, ROGUE @@ -45,26 +45,28 @@ public enum Type { private Type type; /** - * Constructor + * Constructor. */ public Character() { this.prototype = new Prototype() { // Null-value object - @Override - public Integer get(Stats stat) { - return null; - } - - @Override - public boolean has(Stats stat) { - return false; - } - - @Override - public void set(Stats stat, Integer val) {} - - @Override - public void remove(Stats stat) {} - }; + @Override + public Integer get(Stats stat) { + return null; + } + + @Override + public boolean has(Stats stat) { + return false; + } + + @Override + public void set(Stats stat, Integer val) { + } + + @Override + public void remove(Stats stat) { + } + }; } public Character(Type type, Prototype prototype) { @@ -73,7 +75,7 @@ public Character(Type type, Prototype prototype) { } /** - * Constructor + * Constructor. */ public Character(String name, Character prototype) { this.name = name; diff --git a/property/src/main/java/com/iluwatar/property/Prototype.java b/property/src/main/java/com/iluwatar/property/Prototype.java index 9570f66536d8..423863522acd 100644 --- a/property/src/main/java/com/iluwatar/property/Prototype.java +++ b/property/src/main/java/com/iluwatar/property/Prototype.java @@ -24,7 +24,7 @@ package com.iluwatar.property; /** - * Interface for prototype inheritance + * Interface for prototype inheritance. */ public interface Prototype { diff --git a/property/src/main/java/com/iluwatar/property/Stats.java b/property/src/main/java/com/iluwatar/property/Stats.java index 4015e5693680..2941299d5973 100644 --- a/property/src/main/java/com/iluwatar/property/Stats.java +++ b/property/src/main/java/com/iluwatar/property/Stats.java @@ -24,7 +24,7 @@ package com.iluwatar.property; /** - * All possible attributes that Character can have + * All possible attributes that Character can have. */ public enum Stats { diff --git a/prototype/src/main/java/com/iluwatar/prototype/App.java b/prototype/src/main/java/com/iluwatar/prototype/App.java index 457f4f2a0f5a..9b1d4eb320b3 100644 --- a/prototype/src/main/java/com/iluwatar/prototype/App.java +++ b/prototype/src/main/java/com/iluwatar/prototype/App.java @@ -27,41 +27,43 @@ import org.slf4j.LoggerFactory; /** - * * The Prototype pattern is a creational design pattern in software development. It is used when the * type of objects to create is determined by a prototypical instance, which is cloned to produce * new objects. This pattern is used to: - avoid subclasses of an object creator in the client * application, like the abstract factory pattern does. - avoid the inherent cost of creating a new * object in the standard way (e.g., using the 'new' keyword) - *

- * In this example we have a factory class ({@link HeroFactoryImpl}) producing objects by cloning - * the existing ones. The factory's prototype objects are given as constructor parameters. - * + * + *

In this example we have a factory class ({@link HeroFactoryImpl}) producing objects by + * cloning the existing ones. The factory's prototype objects are given as constructor parameters. */ public class App { private static final Logger LOGGER = LoggerFactory.getLogger(App.class); /** - * Program entry point - * + * Program entry point. + * * @param args command line args */ public static void main(String[] args) { - HeroFactory factory; - Mage mage; - Warlord warlord; - Beast beast; - - factory = new HeroFactoryImpl(new ElfMage("cooking"), new ElfWarlord("cleaning"), new ElfBeast("protecting")); - mage = factory.createMage(); - warlord = factory.createWarlord(); - beast = factory.createBeast(); + HeroFactory factory = new HeroFactoryImpl( + new ElfMage("cooking"), + new ElfWarlord("cleaning"), + new ElfBeast("protecting") + ); + Mage mage = factory.createMage(); + Warlord warlord = factory.createWarlord(); + Beast beast = factory.createBeast(); LOGGER.info(mage.toString()); LOGGER.info(warlord.toString()); LOGGER.info(beast.toString()); - factory = new HeroFactoryImpl(new OrcMage("axe"), new OrcWarlord("sword"), new OrcBeast("laser")); + factory = + new HeroFactoryImpl( + new OrcMage("axe"), + new OrcWarlord("sword"), + new OrcBeast("laser") + ); mage = factory.createMage(); warlord = factory.createWarlord(); beast = factory.createBeast(); diff --git a/prototype/src/main/java/com/iluwatar/prototype/Beast.java b/prototype/src/main/java/com/iluwatar/prototype/Beast.java index 3b82cdd9dde1..e3b25b850d19 100644 --- a/prototype/src/main/java/com/iluwatar/prototype/Beast.java +++ b/prototype/src/main/java/com/iluwatar/prototype/Beast.java @@ -24,9 +24,7 @@ package com.iluwatar.prototype; /** - * - * Beast - * + * Beast. */ public abstract class Beast extends Prototype { diff --git a/prototype/src/main/java/com/iluwatar/prototype/ElfBeast.java b/prototype/src/main/java/com/iluwatar/prototype/ElfBeast.java index 9ef44b164391..50761964a4ac 100644 --- a/prototype/src/main/java/com/iluwatar/prototype/ElfBeast.java +++ b/prototype/src/main/java/com/iluwatar/prototype/ElfBeast.java @@ -24,12 +24,10 @@ package com.iluwatar.prototype; /** - * - * ElfBeast - * + * ElfBeast. */ public class ElfBeast extends Beast { - + private String helpType; public ElfBeast(String helpType) { diff --git a/prototype/src/main/java/com/iluwatar/prototype/ElfMage.java b/prototype/src/main/java/com/iluwatar/prototype/ElfMage.java index 14b6e6261ba6..014c39bac2e5 100644 --- a/prototype/src/main/java/com/iluwatar/prototype/ElfMage.java +++ b/prototype/src/main/java/com/iluwatar/prototype/ElfMage.java @@ -24,15 +24,13 @@ package com.iluwatar.prototype; /** - * - * ElfMage - * + * ElfMage. */ public class ElfMage extends Mage { - + private String helpType; - + public ElfMage(String helpType) { this.helpType = helpType; } diff --git a/prototype/src/main/java/com/iluwatar/prototype/ElfWarlord.java b/prototype/src/main/java/com/iluwatar/prototype/ElfWarlord.java index 6c5a4a4ffc0a..43cdac7e5747 100644 --- a/prototype/src/main/java/com/iluwatar/prototype/ElfWarlord.java +++ b/prototype/src/main/java/com/iluwatar/prototype/ElfWarlord.java @@ -24,14 +24,12 @@ package com.iluwatar.prototype; /** - * - * ElfWarlord - * + * ElfWarlord. */ public class ElfWarlord extends Warlord { private String helpType; - + public ElfWarlord(String helpType) { this.helpType = helpType; } diff --git a/prototype/src/main/java/com/iluwatar/prototype/HeroFactory.java b/prototype/src/main/java/com/iluwatar/prototype/HeroFactory.java index 791671289b4c..2644167971a1 100644 --- a/prototype/src/main/java/com/iluwatar/prototype/HeroFactory.java +++ b/prototype/src/main/java/com/iluwatar/prototype/HeroFactory.java @@ -24,9 +24,7 @@ package com.iluwatar.prototype; /** - * * Interface for the factory class. - * */ public interface HeroFactory { diff --git a/prototype/src/main/java/com/iluwatar/prototype/HeroFactoryImpl.java b/prototype/src/main/java/com/iluwatar/prototype/HeroFactoryImpl.java index 5803ee8efcc6..b9348a3b22b8 100644 --- a/prototype/src/main/java/com/iluwatar/prototype/HeroFactoryImpl.java +++ b/prototype/src/main/java/com/iluwatar/prototype/HeroFactoryImpl.java @@ -24,9 +24,7 @@ package com.iluwatar.prototype; /** - * * Concrete factory class. - * */ public class HeroFactoryImpl implements HeroFactory { @@ -35,7 +33,7 @@ public class HeroFactoryImpl implements HeroFactory { private Beast beast; /** - * Constructor + * Constructor. */ public HeroFactoryImpl(Mage mage, Warlord warlord, Beast beast) { this.mage = mage; @@ -44,7 +42,7 @@ public HeroFactoryImpl(Mage mage, Warlord warlord, Beast beast) { } /** - * Create mage + * Create mage. */ public Mage createMage() { try { @@ -55,7 +53,7 @@ public Mage createMage() { } /** - * Create warlord + * Create warlord. */ public Warlord createWarlord() { try { @@ -66,7 +64,7 @@ public Warlord createWarlord() { } /** - * Create beast + * Create beast. */ public Beast createBeast() { try { diff --git a/prototype/src/main/java/com/iluwatar/prototype/Mage.java b/prototype/src/main/java/com/iluwatar/prototype/Mage.java index 9da5e45baada..27c3bae7a191 100644 --- a/prototype/src/main/java/com/iluwatar/prototype/Mage.java +++ b/prototype/src/main/java/com/iluwatar/prototype/Mage.java @@ -24,9 +24,7 @@ package com.iluwatar.prototype; /** - * - * Mage - * + * Mage. */ public abstract class Mage extends Prototype { diff --git a/prototype/src/main/java/com/iluwatar/prototype/OrcBeast.java b/prototype/src/main/java/com/iluwatar/prototype/OrcBeast.java index 2b5fb51599d0..c800b3ac51e6 100644 --- a/prototype/src/main/java/com/iluwatar/prototype/OrcBeast.java +++ b/prototype/src/main/java/com/iluwatar/prototype/OrcBeast.java @@ -24,18 +24,16 @@ package com.iluwatar.prototype; /** - * - * OrcBeast - * + * OrcBeast. */ public class OrcBeast extends Beast { - + private String weapon; public OrcBeast(String weapon) { this.weapon = weapon; } - + public OrcBeast(OrcBeast orcBeast) { this.weapon = orcBeast.weapon; } @@ -49,6 +47,6 @@ public Beast copy() { public String toString() { return "Orcish wolf attacks with " + weapon; } - + } diff --git a/prototype/src/main/java/com/iluwatar/prototype/OrcMage.java b/prototype/src/main/java/com/iluwatar/prototype/OrcMage.java index de15b5e10d91..c71b59d06c54 100644 --- a/prototype/src/main/java/com/iluwatar/prototype/OrcMage.java +++ b/prototype/src/main/java/com/iluwatar/prototype/OrcMage.java @@ -24,9 +24,7 @@ package com.iluwatar.prototype; /** - * - * OrcMage - * + * OrcMage. */ public class OrcMage extends Mage { @@ -35,7 +33,7 @@ public class OrcMage extends Mage { public OrcMage(String weapon) { this.weapon = weapon; } - + public OrcMage(OrcMage orcMage) { this.weapon = orcMage.weapon; } diff --git a/prototype/src/main/java/com/iluwatar/prototype/OrcWarlord.java b/prototype/src/main/java/com/iluwatar/prototype/OrcWarlord.java index 0b117357fd82..096fd49dc9c0 100644 --- a/prototype/src/main/java/com/iluwatar/prototype/OrcWarlord.java +++ b/prototype/src/main/java/com/iluwatar/prototype/OrcWarlord.java @@ -24,9 +24,7 @@ package com.iluwatar.prototype; /** - * - * OrcWarlord - * + * OrcWarlord. */ public class OrcWarlord extends Warlord { @@ -35,7 +33,7 @@ public class OrcWarlord extends Warlord { public OrcWarlord(String weapon) { this.weapon = weapon; } - + public OrcWarlord(OrcWarlord orcWarlord) { this.weapon = orcWarlord.weapon; } diff --git a/prototype/src/main/java/com/iluwatar/prototype/Prototype.java b/prototype/src/main/java/com/iluwatar/prototype/Prototype.java index bae58b026d3e..c74c82f4ad6b 100644 --- a/prototype/src/main/java/com/iluwatar/prototype/Prototype.java +++ b/prototype/src/main/java/com/iluwatar/prototype/Prototype.java @@ -24,9 +24,7 @@ package com.iluwatar.prototype; /** - * - * Prototype - * + * Prototype. */ public abstract class Prototype implements Cloneable { diff --git a/prototype/src/main/java/com/iluwatar/prototype/Warlord.java b/prototype/src/main/java/com/iluwatar/prototype/Warlord.java index 7ce8922e909c..c270ab80bd0d 100644 --- a/prototype/src/main/java/com/iluwatar/prototype/Warlord.java +++ b/prototype/src/main/java/com/iluwatar/prototype/Warlord.java @@ -24,9 +24,7 @@ package com.iluwatar.prototype; /** - * - * Warlord - * + * Warlord. */ public abstract class Warlord extends Prototype { diff --git a/proxy/src/main/java/com/iluwatar/proxy/App.java b/proxy/src/main/java/com/iluwatar/proxy/App.java index 4c9d0efaa3f4..ff02a6074fec 100644 --- a/proxy/src/main/java/com/iluwatar/proxy/App.java +++ b/proxy/src/main/java/com/iluwatar/proxy/App.java @@ -24,25 +24,23 @@ package com.iluwatar.proxy; /** - * * A proxy, in its most general form, is a class functioning as an interface to something else. The * proxy could interface to anything: a network connection, a large object in memory, a file, or * some other resource that is expensive or impossible to duplicate. In short, a proxy is a wrapper * or agent object that is being called by the client to access the real serving object behind the * scenes. - *

- * The Proxy design pattern allows you to provide an interface to other objects by creating a + * + *

The Proxy design pattern allows you to provide an interface to other objects by creating a * wrapper class as the proxy. The wrapper class, which is the proxy, can add additional * functionality to the object of interest without changing the object's code. - *

- * In this example the proxy ({@link WizardTowerProxy}) controls access to the actual object ( + * + *

In this example the proxy ({@link WizardTowerProxy}) controls access to the actual object ( * {@link IvoryTower}). - * */ public class App { /** - * Program entry point + * Program entry point. */ public static void main(String[] args) { diff --git a/proxy/src/main/java/com/iluwatar/proxy/IvoryTower.java b/proxy/src/main/java/com/iluwatar/proxy/IvoryTower.java index 3adb96d86b6c..658b19949080 100644 --- a/proxy/src/main/java/com/iluwatar/proxy/IvoryTower.java +++ b/proxy/src/main/java/com/iluwatar/proxy/IvoryTower.java @@ -27,9 +27,7 @@ import org.slf4j.LoggerFactory; /** - * * The object to be proxyed. - * */ public class IvoryTower implements WizardTower { diff --git a/proxy/src/main/java/com/iluwatar/proxy/Wizard.java b/proxy/src/main/java/com/iluwatar/proxy/Wizard.java index 031ab8dfd2da..fc77d80df28c 100644 --- a/proxy/src/main/java/com/iluwatar/proxy/Wizard.java +++ b/proxy/src/main/java/com/iluwatar/proxy/Wizard.java @@ -24,9 +24,7 @@ package com.iluwatar.proxy; /** - * - * Wizard - * + * Wizard. */ public class Wizard { diff --git a/proxy/src/main/java/com/iluwatar/proxy/WizardTower.java b/proxy/src/main/java/com/iluwatar/proxy/WizardTower.java index ac83aa6ea54a..c08b49e7dcbb 100644 --- a/proxy/src/main/java/com/iluwatar/proxy/WizardTower.java +++ b/proxy/src/main/java/com/iluwatar/proxy/WizardTower.java @@ -24,7 +24,7 @@ package com.iluwatar.proxy; /** - * WizardTower interface + * WizardTower interface. */ public interface WizardTower { diff --git a/proxy/src/main/java/com/iluwatar/proxy/WizardTowerProxy.java b/proxy/src/main/java/com/iluwatar/proxy/WizardTowerProxy.java index 7e6b2acf06d9..e295850de876 100644 --- a/proxy/src/main/java/com/iluwatar/proxy/WizardTowerProxy.java +++ b/proxy/src/main/java/com/iluwatar/proxy/WizardTowerProxy.java @@ -27,9 +27,7 @@ import org.slf4j.LoggerFactory; /** - * * The proxy controlling access to the {@link IvoryTower}. - * */ public class WizardTowerProxy implements WizardTower { From 8747f1fd7a420353f1d0772aa682559baa177256 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilkka=20Sepp=C3=A4l=C3=A4?= Date: Sat, 16 Nov 2019 16:00:24 +0200 Subject: [PATCH 24/31] #1021 enforce Checkstyle rules in the build --- .../abstractfactory/AbstractFactoryTest.java | 2 +- .../java/com/iluwatar/composite/Word.java | 4 + .../layers/service/CakeBakingServiceImpl.java | 7 +- .../java/com/iluwatar/pageobject/App.java | 5 +- pom.xml | 6 +- .../com/iluwatar/producer/consumer/App.java | 22 ++--- .../iluwatar/producer/consumer/Consumer.java | 7 +- .../iluwatar/producer/consumer/Producer.java | 4 +- .../main/java/com/iluwatar/promise/App.java | 19 ++--- .../java/com/iluwatar/promise/Utility.java | 14 +-- .../roleobject/ApplicationRoleObject.java | 85 ++++++++++--------- .../com/iluwatar/roleobject/BorrowerRole.java | 24 +++--- .../com/iluwatar/roleobject/Customer.java | 78 ++++++++--------- .../com/iluwatar/roleobject/CustomerCore.java | 80 ++++++++--------- .../com/iluwatar/roleobject/CustomerRole.java | 6 +- .../com/iluwatar/roleobject/InvestorRole.java | 37 ++++---- .../java/com/iluwatar/roleobject/Role.java | 43 +++++----- 17 files changed, 237 insertions(+), 206 deletions(-) diff --git a/abstract-factory/src/test/java/com/iluwatar/abstractfactory/AbstractFactoryTest.java b/abstract-factory/src/test/java/com/iluwatar/abstractfactory/AbstractFactoryTest.java index cecd8a894e68..be83cc315627 100644 --- a/abstract-factory/src/test/java/com/iluwatar/abstractfactory/AbstractFactoryTest.java +++ b/abstract-factory/src/test/java/com/iluwatar/abstractfactory/AbstractFactoryTest.java @@ -32,7 +32,7 @@ import org.junit.jupiter.api.Test; /** - * Test for abstract factory + * Test for abstract factory. */ public class AbstractFactoryTest { diff --git a/composite/src/main/java/com/iluwatar/composite/Word.java b/composite/src/main/java/com/iluwatar/composite/Word.java index 933d38bde313..235d1c31f097 100644 --- a/composite/src/main/java/com/iluwatar/composite/Word.java +++ b/composite/src/main/java/com/iluwatar/composite/Word.java @@ -37,6 +37,10 @@ public Word(List letters) { letters.forEach(this::add); } + /** + * Constructor. + * @param letters to include + */ public Word(char... letters) { for (char letter : letters) { this.add(new Letter(letter)); diff --git a/layers/src/main/java/com/iluwatar/layers/service/CakeBakingServiceImpl.java b/layers/src/main/java/com/iluwatar/layers/service/CakeBakingServiceImpl.java index 403816421a4b..885852519aba 100644 --- a/layers/src/main/java/com/iluwatar/layers/service/CakeBakingServiceImpl.java +++ b/layers/src/main/java/com/iluwatar/layers/service/CakeBakingServiceImpl.java @@ -23,12 +23,12 @@ package com.iluwatar.layers.service; -import com.iluwatar.layers.dto.CakeInfo; -import com.iluwatar.layers.dto.CakeLayerInfo; -import com.iluwatar.layers.dto.CakeToppingInfo; import com.iluwatar.layers.dao.CakeDao; import com.iluwatar.layers.dao.CakeLayerDao; import com.iluwatar.layers.dao.CakeToppingDao; +import com.iluwatar.layers.dto.CakeInfo; +import com.iluwatar.layers.dto.CakeLayerInfo; +import com.iluwatar.layers.dto.CakeToppingInfo; import com.iluwatar.layers.entity.Cake; import com.iluwatar.layers.entity.CakeLayer; import com.iluwatar.layers.entity.CakeTopping; @@ -40,7 +40,6 @@ import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; - import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.stereotype.Service; diff --git a/page-object/src/main/java/com/iluwatar/pageobject/App.java b/page-object/src/main/java/com/iluwatar/pageobject/App.java index 9c4c21607979..ee9f58504a0b 100644 --- a/page-object/src/main/java/com/iluwatar/pageobject/App.java +++ b/page-object/src/main/java/com/iluwatar/pageobject/App.java @@ -70,12 +70,13 @@ public static void main(String[] args) { File applicationFile = new File(App.class.getClassLoader().getResource("sample-ui/login.html").getPath()); - // should work for unix like OS (mac, unix etc...) + // Should work for unix like OS (mac, unix etc...) if (Desktop.isDesktopSupported()) { Desktop.getDesktop().open(applicationFile); } else { - // java Desktop not supported - above unlikely to work for Windows so try following instead... + // Java Desktop not supported - above unlikely to work for Windows so try the + // following instead... Runtime.getRuntime().exec("cmd.exe start " + applicationFile); } diff --git a/pom.xml b/pom.xml index 1ab896068a6b..423a3b7052e5 100644 --- a/pom.xml +++ b/pom.xml @@ -384,9 +384,6 @@ - org.apache.maven.plugins maven-checkstyle-plugin @@ -403,7 +400,8 @@ checkstyle-suppressions.xml UTF-8 true - true + warning + false diff --git a/producer-consumer/src/main/java/com/iluwatar/producer/consumer/App.java b/producer-consumer/src/main/java/com/iluwatar/producer/consumer/App.java index 853c6fcfe51d..0ead44307b7d 100644 --- a/producer-consumer/src/main/java/com/iluwatar/producer/consumer/App.java +++ b/producer-consumer/src/main/java/com/iluwatar/producer/consumer/App.java @@ -23,20 +23,22 @@ package com.iluwatar.producer.consumer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** - * Producer Consumer Design pattern is a classic concurrency or threading pattern which reduces coupling between - * Producer and Consumer by separating Identification of work with Execution of Work. - *

- * In producer consumer design pattern a shared queue is used to control the flow and this separation allows you to code - * producer and consumer separately. It also addresses the issue of different timing require to produce item or - * consuming item. by using producer consumer pattern both Producer and Consumer Thread can work with different speed. + * Producer Consumer Design pattern is a classic concurrency or threading pattern which reduces + * coupling between Producer and Consumer by separating Identification of work with + * Execution of Work. + * + *

In producer consumer design pattern a shared queue is used to control the flow and this + * separation allows you to code producer and consumer separately. It also addresses the issue + * of different timing require to produce item or consuming item. by using producer consumer + * pattern both Producer and Consumer Thread can work with different speed. * */ public class App { @@ -44,7 +46,7 @@ public class App { private static final Logger LOGGER = LoggerFactory.getLogger(App.class); /** - * Program entry point + * Program entry point. * * @param args * command line args diff --git a/producer-consumer/src/main/java/com/iluwatar/producer/consumer/Consumer.java b/producer-consumer/src/main/java/com/iluwatar/producer/consumer/Consumer.java index 3e4e9aadb3d9..5598f3e45dca 100644 --- a/producer-consumer/src/main/java/com/iluwatar/producer/consumer/Consumer.java +++ b/producer-consumer/src/main/java/com/iluwatar/producer/consumer/Consumer.java @@ -27,7 +27,7 @@ import org.slf4j.LoggerFactory; /** - * Class responsible for consume the {@link Item} produced by {@link Producer} + * Class responsible for consume the {@link Item} produced by {@link Producer}. */ public class Consumer { @@ -43,12 +43,13 @@ public Consumer(String name, ItemQueue queue) { } /** - * Consume item from the queue + * Consume item from the queue. */ public void consume() throws InterruptedException { Item item = queue.take(); - LOGGER.info("Consumer [{}] consume item [{}] produced by [{}]", name, item.getId(), item.getProducer()); + LOGGER.info("Consumer [{}] consume item [{}] produced by [{}]", name, + item.getId(), item.getProducer()); } } diff --git a/producer-consumer/src/main/java/com/iluwatar/producer/consumer/Producer.java b/producer-consumer/src/main/java/com/iluwatar/producer/consumer/Producer.java index e8c79afd4836..6d4ca0096d6d 100644 --- a/producer-consumer/src/main/java/com/iluwatar/producer/consumer/Producer.java +++ b/producer-consumer/src/main/java/com/iluwatar/producer/consumer/Producer.java @@ -27,7 +27,7 @@ /** * Class responsible for producing unit of work that can be expressed as {@link Item} and submitted - * to queue + * to queue. */ public class Producer { @@ -45,7 +45,7 @@ public Producer(String name, ItemQueue queue) { } /** - * Put item in the queue + * Put item in the queue. */ public void produce() throws InterruptedException { diff --git a/promise/src/main/java/com/iluwatar/promise/App.java b/promise/src/main/java/com/iluwatar/promise/App.java index c201d33526c2..c016b67ff0b5 100644 --- a/promise/src/main/java/com/iluwatar/promise/App.java +++ b/promise/src/main/java/com/iluwatar/promise/App.java @@ -22,8 +22,6 @@ */ package com.iluwatar.promise; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.util.Map; import java.util.concurrent.CompletableFuture; @@ -32,10 +30,12 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** - * - * The Promise object is used for asynchronous computations. A Promise represents an operation - * that hasn't completed yet, but is expected in the future. + * The Promise object is used for asynchronous computations. A Promise represents an operation + * that hasn't completed yet, but is expected in the future. * *

A Promise represents a proxy for a value not necessarily known when the promise is created. It * allows you to associate dependent promises to an asynchronous action's eventual success value or @@ -49,15 +49,14 @@ *

  • Prevents callback hell and provides callback aggregation * * - *

    - * In this application the usage of promise is demonstrated with two examples: + *

    In this application the usage of promise is demonstrated with two examples: *

      *
    • Count Lines: In this example a file is downloaded and its line count is calculated. * The calculated line count is then consumed and printed on console. *
    • Lowest Character Frequency: In this example a file is downloaded and its lowest frequency * character is found and printed on console. This happens via a chain of promises, we start with - * a file download promise, then a promise of character frequency, then a promise of lowest frequency - * character which is finally consumed and result is printed on console. + * a file download promise, then a promise of character frequency, then a promise of lowest + * frequency character which is finally consumed and result is printed on console. *
    * * @see CompletableFuture @@ -76,7 +75,7 @@ private App() { } /** - * Program entry point + * Program entry point. * @param args arguments * @throws InterruptedException if main thread is interrupted. * @throws ExecutionException if an execution error occurs. diff --git a/promise/src/main/java/com/iluwatar/promise/Utility.java b/promise/src/main/java/com/iluwatar/promise/Utility.java index 472f7b0a5234..09c7f6ddc7b3 100644 --- a/promise/src/main/java/com/iluwatar/promise/Utility.java +++ b/promise/src/main/java/com/iluwatar/promise/Utility.java @@ -23,9 +23,6 @@ package com.iluwatar.promise; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.io.BufferedReader; import java.io.File; import java.io.FileReader; @@ -39,8 +36,11 @@ import java.util.Map; import java.util.Map.Entry; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** - * Utility to perform various operations + * Utility to perform various operations. */ public class Utility { @@ -71,7 +71,8 @@ public static Map characterFrequency(String fileLocation) { } /** - * @return the character with lowest frequency if it exists, {@code Optional.empty()} otherwise. + * Return the character with the lowest frequency, if exists. + * @return the character, {@code Optional.empty()} otherwise. */ public static Character lowestFrequencyChar(Map charFrequency) { Character lowestFrequencyChar = null; @@ -92,7 +93,8 @@ public static Character lowestFrequencyChar(Map charFrequenc } /** - * @return number of lines in the file at provided location. 0 if file does not exist. + * Count the number of lines in a file. + * @return number of lines, 0 if file does not exist. */ public static Integer countLines(String fileLocation) { int lineCount = 0; diff --git a/role-object/src/main/java/com/iluwatar/roleobject/ApplicationRoleObject.java b/role-object/src/main/java/com/iluwatar/roleobject/ApplicationRoleObject.java index b8296dabacc6..eb76ef34a522 100644 --- a/role-object/src/main/java/com/iluwatar/roleobject/ApplicationRoleObject.java +++ b/role-object/src/main/java/com/iluwatar/roleobject/ApplicationRoleObject.java @@ -20,13 +20,15 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package com.iluwatar.roleobject; +import static com.iluwatar.roleobject.Role.Borrower; +import static com.iluwatar.roleobject.Role.Investor; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import static com.iluwatar.roleobject.Role.*; - /** * The Role Object pattern suggests to model context-specific views * of an object as separate role objects which are @@ -39,55 +41,60 @@ * investor, respectively. Both roles could as well be played by a single {@link Customer} object. * The common superclass for customer-specific roles is provided by {@link CustomerRole}, * which also supports the {@link Customer} interface. - *

    - * The {@link CustomerRole} class is abstract and not meant to be instantiated. - * Concrete subclasses of {@link CustomerRole}, for example {@link BorrowerRole} or {@link InvestorRole}, - * define and implement the interface for specific roles. It is only + * + *

    The {@link CustomerRole} class is abstract and not meant to be instantiated. + * Concrete subclasses of {@link CustomerRole}, for example {@link BorrowerRole} + * or {@link InvestorRole}, define and implement the interface for specific roles. It is only * these subclasses which are instantiated at runtime. - * The {@link BorrowerRole} class defines the context-specific view of {@link Customer} objects as needed by the loan department. + * The {@link BorrowerRole} class defines the context-specific view of {@link Customer} + * objects as needed by the loan department. * It defines additional operations to manage the customer’s * credits and securities. Similarly, the {@link InvestorRole} class adds operations specific * to the investment department’s view of customers. - * A client like the loan application may either work with objects of the {@link CustomerRole} class, using the interface class - * {@link Customer}, or with objects of concrete {@link CustomerRole} subclasses. Suppose the loan application knows a particular - * {@link Customer} instance through its {@link Customer} interface. The loan application may want to check whether the {@link Customer} - * object plays the role of Borrower. - * To this end it calls {@link Customer#hasRole(Role)} with a suitable role specification. For the purpose of - * our example, let’s assume we can name roles with enum. - * If the {@link Customer} object can play the role named “Borrower,” the loan application will ask it - * to return a reference to the corresponding object. + * A client like the loan application may either work with objects of the {@link CustomerRole} + * class, using the interface class {@link Customer}, or with objects of concrete + * {@link CustomerRole} subclasses. Suppose the loan application knows a particular + * {@link Customer} instance through its {@link Customer} interface. The loan application + * may want to check whether the {@link Customer} object plays the role of Borrower. + * To this end it calls {@link Customer#hasRole(Role)} with a suitable role specification. For + * the purpose of our example, let’s assume we can name roles with enum. + * If the {@link Customer} object can play the role named “Borrower,” the loan application will + * ask it to return a reference to the corresponding object. * The loan application may now use this reference to call Borrower-specific operations. */ public class ApplicationRoleObject { - private static final Logger logger = LoggerFactory.getLogger(Role.class); - - public static void main(String[] args) { - Customer customer = Customer.newCustomer(Borrower, Investor); - - logger.info(" the new customer created : {}", customer); + private static final Logger logger = LoggerFactory.getLogger(Role.class); - boolean hasBorrowerRole = customer.hasRole(Borrower); - logger.info(" customer has a borrowed role - {}", hasBorrowerRole); - boolean hasInvestorRole = customer.hasRole(Investor); - logger.info(" customer has an investor role - {}", hasInvestorRole); + /** + * Main entry point. + * + * @param args program arguments + */ + public static void main(String[] args) { + Customer customer = Customer.newCustomer(Borrower, Investor); - customer.getRole(Investor, InvestorRole.class) - .ifPresent(inv -> { - inv.setAmountToInvest(1000); - inv.setName("Billy"); - }); - customer.getRole(Borrower, BorrowerRole.class) - .ifPresent(inv -> inv.setName("Johny")); + logger.info(" the new customer created : {}", customer); - customer.getRole(Investor, InvestorRole.class) - .map(InvestorRole::invest) - .ifPresent(logger::info); + boolean hasBorrowerRole = customer.hasRole(Borrower); + logger.info(" customer has a borrowed role - {}", hasBorrowerRole); + boolean hasInvestorRole = customer.hasRole(Investor); + logger.info(" customer has an investor role - {}", hasInvestorRole); - customer.getRole(Borrower, BorrowerRole.class) - .map(BorrowerRole::borrow) - .ifPresent(logger::info); - } + customer.getRole(Investor, InvestorRole.class) + .ifPresent(inv -> { + inv.setAmountToInvest(1000); + inv.setName("Billy"); + }); + customer.getRole(Borrower, BorrowerRole.class) + .ifPresent(inv -> inv.setName("Johny")); + customer.getRole(Investor, InvestorRole.class) + .map(InvestorRole::invest) + .ifPresent(logger::info); + customer.getRole(Borrower, BorrowerRole.class) + .map(BorrowerRole::borrow) + .ifPresent(logger::info); + } } diff --git a/role-object/src/main/java/com/iluwatar/roleobject/BorrowerRole.java b/role-object/src/main/java/com/iluwatar/roleobject/BorrowerRole.java index 425d9511d083..19db1c823a79 100644 --- a/role-object/src/main/java/com/iluwatar/roleobject/BorrowerRole.java +++ b/role-object/src/main/java/com/iluwatar/roleobject/BorrowerRole.java @@ -20,21 +20,23 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package com.iluwatar.roleobject; -public class BorrowerRole extends CustomerRole{ - private String name; +public class BorrowerRole extends CustomerRole { + + private String name; - public String getName() { - return name; - } + public String getName() { + return name; + } - public void setName(String name) { - this.name = name; - } + public void setName(String name) { + this.name = name; + } - public String borrow(){ - return String.format("Borrower %s wants to get some money.",name); - } + public String borrow() { + return String.format("Borrower %s wants to get some money.", name); + } } diff --git a/role-object/src/main/java/com/iluwatar/roleobject/Customer.java b/role-object/src/main/java/com/iluwatar/roleobject/Customer.java index ebcddff4b154..1d21c5cc80a9 100644 --- a/role-object/src/main/java/com/iluwatar/roleobject/Customer.java +++ b/role-object/src/main/java/com/iluwatar/roleobject/Customer.java @@ -20,6 +20,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package com.iluwatar.roleobject; import java.util.Optional; @@ -29,51 +30,52 @@ */ public abstract class Customer { - /** - * Add specific role @see {@link Role} - * - * @param role to add - * @return true if the operation has been successful otherwise false - */ - public abstract boolean addRole(Role role); + /** + * Add specific role @see {@link Role}. + * @param role to add + * @return true if the operation has been successful otherwise false + */ + public abstract boolean addRole(Role role); - /** - * Check specific role @see {@link Role} - * - * @param role to check - * @return true if the role exists otherwise false - */ + /** + * Check specific role @see {@link Role}. + * @param role to check + * @return true if the role exists otherwise false + */ - public abstract boolean hasRole(Role role); + public abstract boolean hasRole(Role role); - /** - * Remove specific role @see {@link Role} - * - * @param role to remove - * @return true if the operation has been successful otherwise false - */ - public abstract boolean remRole(Role role); + /** + * Remove specific role @see {@link Role}. + * @param role to remove + * @return true if the operation has been successful otherwise false + */ + public abstract boolean remRole(Role role); - /** - * Get specific instance associated with this role @see {@link Role} - * - * @param role to get - * @param expectedRole instance class expected to get - * @return optional with value if the instance exists and corresponds expected class - */ - public abstract Optional getRole(Role role, Class expectedRole); + /** + * Get specific instance associated with this role @see {@link Role}. + * @param role to get + * @param expectedRole instance class expected to get + * @return optional with value if the instance exists and corresponds expected class + */ + public abstract Optional getRole(Role role, Class expectedRole); - public static Customer newCustomer() { - return new CustomerCore(); - } + public static Customer newCustomer() { + return new CustomerCore(); + } - public static Customer newCustomer(Role... role) { - Customer customer = newCustomer(); - for (Role r : role) { - customer.addRole(r); - } - return customer; + /** + * Create {@link Customer} with given roles. + * @param role roles + * @return Customer + */ + public static Customer newCustomer(Role... role) { + Customer customer = newCustomer(); + for (Role r : role) { + customer.addRole(r); } + return customer; + } } diff --git a/role-object/src/main/java/com/iluwatar/roleobject/CustomerCore.java b/role-object/src/main/java/com/iluwatar/roleobject/CustomerCore.java index 5de27aa9295d..670a53904ef7 100644 --- a/role-object/src/main/java/com/iluwatar/roleobject/CustomerCore.java +++ b/role-object/src/main/java/com/iluwatar/roleobject/CustomerCore.java @@ -20,56 +20,60 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package com.iluwatar.roleobject; -import java.util.*; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; /** - * Core class to store different customer roles + * Core class to store different customer roles. * - * @see CustomerRole - * Note: not thread safe + * @see CustomerRole Note: not thread safe */ public class CustomerCore extends Customer { - private Map roles; + private Map roles; - public CustomerCore() { - roles = new HashMap<>(); - } + public CustomerCore() { + roles = new HashMap<>(); + } - @Override - public boolean addRole(Role role) { - return role - .instance() - .map(inst -> { - roles.put(role, inst); - return true; - }) - .orElse(false); - } + @Override + public boolean addRole(Role role) { + return role + .instance() + .map(inst -> { + roles.put(role, inst); + return true; + }) + .orElse(false); + } - @Override - public boolean hasRole(Role role) { - return roles.containsKey(role); - } + @Override + public boolean hasRole(Role role) { + return roles.containsKey(role); + } - @Override - public boolean remRole(Role role) { - return Objects.nonNull(roles.remove(role)); - } + @Override + public boolean remRole(Role role) { + return Objects.nonNull(roles.remove(role)); + } - @Override - public Optional getRole(Role role, Class expectedRole) { - return Optional - .ofNullable(roles.get(role)) - .filter(expectedRole::isInstance) - .map(expectedRole::cast); - } + @Override + public Optional getRole(Role role, Class expectedRole) { + return Optional + .ofNullable(roles.get(role)) + .filter(expectedRole::isInstance) + .map(expectedRole::cast); + } - @Override - public String toString() { - String roles = Arrays.toString(this.roles.keySet().toArray()); - return "Customer{roles=" + roles + "}"; - } + @Override + public String toString() { + String roles = Arrays.toString(this.roles.keySet().toArray()); + return "Customer{roles=" + roles + "}"; + } } diff --git a/role-object/src/main/java/com/iluwatar/roleobject/CustomerRole.java b/role-object/src/main/java/com/iluwatar/roleobject/CustomerRole.java index 40fe2341b3a9..7f1805924fdc 100644 --- a/role-object/src/main/java/com/iluwatar/roleobject/CustomerRole.java +++ b/role-object/src/main/java/com/iluwatar/roleobject/CustomerRole.java @@ -20,9 +20,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package com.iluwatar.roleobject; /** - * Key abstraction for segregated roles + * Key abstraction for segregated roles. */ -public abstract class CustomerRole extends CustomerCore{} +public abstract class CustomerRole extends CustomerCore{ +} diff --git a/role-object/src/main/java/com/iluwatar/roleobject/InvestorRole.java b/role-object/src/main/java/com/iluwatar/roleobject/InvestorRole.java index d6ec6bc42050..d95289a07140 100644 --- a/role-object/src/main/java/com/iluwatar/roleobject/InvestorRole.java +++ b/role-object/src/main/java/com/iluwatar/roleobject/InvestorRole.java @@ -20,29 +20,32 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package com.iluwatar.roleobject; public class InvestorRole extends CustomerRole { - private String name; - private long amountToInvest; - public String getName() { - return name; - } + private String name; + + private long amountToInvest; + + public String getName() { + return name; + } - public void setName(String name) { - this.name = name; - } + public void setName(String name) { + this.name = name; + } - public long getAmountToInvest() { - return amountToInvest; - } + public long getAmountToInvest() { + return amountToInvest; + } - public void setAmountToInvest(long amountToInvest) { - this.amountToInvest = amountToInvest; - } + public void setAmountToInvest(long amountToInvest) { + this.amountToInvest = amountToInvest; + } - public String invest() { - return String.format("Investor %s has invested %d dollars", name, amountToInvest); - } + public String invest() { + return String.format("Investor %s has invested %d dollars", name, amountToInvest); + } } diff --git a/role-object/src/main/java/com/iluwatar/roleobject/Role.java b/role-object/src/main/java/com/iluwatar/roleobject/Role.java index f6c739891566..74863ad84051 100644 --- a/role-object/src/main/java/com/iluwatar/roleobject/Role.java +++ b/role-object/src/main/java/com/iluwatar/roleobject/Role.java @@ -20,36 +20,41 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package com.iluwatar.roleobject; +import java.util.Optional; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Optional; - /** - * Possible roles + * Possible roles. */ public enum Role { - Borrower(BorrowerRole.class), Investor(InvestorRole.class); - private Class typeCst; + Borrower(BorrowerRole.class), Investor(InvestorRole.class); - Role(Class typeCst) { - this.typeCst = typeCst; - } + private Class typeCst; + + Role(Class typeCst) { + this.typeCst = typeCst; + } + + private static final Logger logger = LoggerFactory.getLogger(Role.class); - private static final Logger logger = LoggerFactory.getLogger(Role.class); - - @SuppressWarnings("unchecked") - public Optional instance() { - Class typeCst = this.typeCst; - try { - return (Optional) Optional.of(typeCst.newInstance()); - } catch (InstantiationException | IllegalAccessException e) { - logger.error("error creating an object", e); - } - return Optional.empty(); + /** + * Get instance. + */ + @SuppressWarnings("unchecked") + public Optional instance() { + Class typeCst = this.typeCst; + try { + return (Optional) Optional.of(typeCst.newInstance()); + } catch (InstantiationException | IllegalAccessException e) { + logger.error("error creating an object", e); } + return Optional.empty(); + } } From cc4b990ae8487049123aa48d05a364ab157f81bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilkka=20Sepp=C3=A4l=C3=A4?= Date: Sat, 16 Nov 2019 21:06:05 +0200 Subject: [PATCH 25/31] #590 Add explanation for Converter pattern --- converter/README.md | 65 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/converter/README.md b/converter/README.md index 79b539422892..5cde646eedbc 100644 --- a/converter/README.md +++ b/converter/README.md @@ -17,6 +17,71 @@ mapping, reducing a boilerplate code to minimum. ![alt text](./etc/converter.png "Converter Pattern") +## Explanation + +Real world example + +> In real world applications it is often the case that database layer consists of entities that need to be mapped into DTOs for use on the business logic layer. Similar mapping is done for potentially huge amount of classes and we need a generic way to achieve this. + +In plain words + +> Converter pattern makes it easy to map instances of one class into instances of another class. + +**Programmatic Example** + +We need a generic solution for the mapping problem. To achieve this, let's introduce a generic converter. + +```java +public class Converter { + + private final Function fromDto; + private final Function fromEntity; + + public Converter(final Function fromDto, final Function fromEntity) { + this.fromDto = fromDto; + this.fromEntity = fromEntity; + } + + public final U convertFromDto(final T dto) { + return fromDto.apply(dto); + } + + public final T convertFromEntity(final U entity) { + return fromEntity.apply(entity); + } + + public final List createFromDtos(final Collection dtos) { + return dtos.stream().map(this::convertFromDto).collect(Collectors.toList()); + } + + public final List createFromEntities(final Collection entities) { + return entities.stream().map(this::convertFromEntity).collect(Collectors.toList()); + } +} +``` + +The specialized converters inherit from this base class as follows. + +```java +public class UserConverter extends Converter { + + public UserConverter() { + super(userDto -> new User(userDto.getFirstName(), userDto.getLastName(), userDto.isActive(), + userDto.getEmail()), + user -> new UserDto(user.getFirstName(), user.getLastName(), user.isActive(), + user.getUserId())); + } +} +``` + +Now mapping between User and UserDto becomes trivial. + +```java +Converter userConverter = new UserConverter(); +UserDto dtoUser = new UserDto("John", "Doe", true, "whatever[at]wherever.com"); +User user = userConverter.convertFromDto(dtoUser); +``` + ## Applicability Use the Converter Pattern in the following situations: From 63c707fcb18d90cbe24d873cc173bbfd10612ed7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilkka=20Sepp=C3=A4l=C3=A4?= Date: Sat, 16 Nov 2019 21:17:21 +0200 Subject: [PATCH 26/31] Add game-loop to parent pom.xml --- pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/pom.xml b/pom.xml index 423a3b7052e5..201854085405 100644 --- a/pom.xml +++ b/pom.xml @@ -187,6 +187,7 @@ saga double-buffer sharding + game-loop From 19b129c28ec9f651b2f11bfbd4687a2e033a50b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilkka=20Sepp=C3=A4l=C3=A4?= Date: Sat, 16 Nov 2019 21:56:40 +0200 Subject: [PATCH 27/31] Fix several frontmatter issues --- circuit-breaker/README.md | 2 +- collection-pipeline/README.md | 2 +- commander/README.md | 2 +- double-buffer/README.md | 1 - game-loop/README.md | 1 - master-worker-pattern/README.md | 2 +- sharding/README.md | 7 +++---- spatial-partition/README.md | 2 +- subclass-sandbox/README.md | 3 +-- trampoline/README.md | 2 +- 10 files changed, 10 insertions(+), 14 deletions(-) diff --git a/circuit-breaker/README.md b/circuit-breaker/README.md index db75ca58c0d0..6a1c631c7cf7 100644 --- a/circuit-breaker/README.md +++ b/circuit-breaker/README.md @@ -1,6 +1,6 @@ --- layout: pattern -title: CircuitBreaker +title: Circuit Breaker folder: circuit-breaker permalink: /patterns/circuit-breaker/ categories: Other diff --git a/collection-pipeline/README.md b/collection-pipeline/README.md index ab13b21dbb75..9d2f2693b910 100644 --- a/collection-pipeline/README.md +++ b/collection-pipeline/README.md @@ -3,7 +3,7 @@ layout: pattern title: Collection Pipeline folder: collection-pipeline permalink: /patterns/collection-pipeline/ -categories: Functional +categories: Other tags: - Java - Difficulty-Beginner diff --git a/commander/README.md b/commander/README.md index 41e2cd587553..71ef7fe9c303 100644 --- a/commander/README.md +++ b/commander/README.md @@ -3,7 +3,7 @@ layout: pattern title: Commander folder: commander permalink: /patterns/commander/ -categories: +categories: Other tags: - Java - Difficulty-Intermediate diff --git a/double-buffer/README.md b/double-buffer/README.md index 8e8e7acf6bfd..9cd5ebfa8420 100644 --- a/double-buffer/README.md +++ b/double-buffer/README.md @@ -1,4 +1,3 @@ - --- layout: pattern title: Double Buffer diff --git a/game-loop/README.md b/game-loop/README.md index 424343271d63..5df86e045866 100644 --- a/game-loop/README.md +++ b/game-loop/README.md @@ -1,4 +1,3 @@ - --- layout: pattern title: Game Loop diff --git a/master-worker-pattern/README.md b/master-worker-pattern/README.md index 4d2aa0e38d95..f8b5509369ff 100644 --- a/master-worker-pattern/README.md +++ b/master-worker-pattern/README.md @@ -3,7 +3,7 @@ layout: pattern title: Master-Worker folder: master-worker-pattern permalink: /patterns/master-worker-pattern/ -categories: Centralised Parallel Processing +categories: Other tags: - Java - Difficulty-Intermediate diff --git a/sharding/README.md b/sharding/README.md index b40f08cfccd5..3184e405ed17 100644 --- a/sharding/README.md +++ b/sharding/README.md @@ -1,10 +1,9 @@ - ---- +--- layout: pattern title: Sharding -folder: sharding +folder: sharding permalink: /patterns/sharding/ -categories: Other +categories: Other tags: - Java - Difficulty-Beginner diff --git a/spatial-partition/README.md b/spatial-partition/README.md index e4270e50b1e0..6e55f9544ff2 100644 --- a/spatial-partition/README.md +++ b/spatial-partition/README.md @@ -3,7 +3,7 @@ layout: pattern title: Spatial Partition folder: spatial-partition permalink: /patterns/spatial-partition/ -categories: Game Programming pattern/Optimisation pattern +categories: Other tags: - Java - Difficulty-Intermediate diff --git a/subclass-sandbox/README.md b/subclass-sandbox/README.md index 674991f0895c..b4c8952b0507 100644 --- a/subclass-sandbox/README.md +++ b/subclass-sandbox/README.md @@ -1,4 +1,3 @@ - --- layout: pattern title: Subclass Sandbox @@ -9,7 +8,7 @@ tags: - Java - Difficulty-Beginner --- - + ## Intent The subclass sandbox pattern describes a basic idea, while not having a lot of detailed mechanics. You will need the pattern when you have several similar subclasses. If you have to make a tiny change, then change the base class, while all subclasses shouldn't have to be touched. So the base class has to be able to provide all of the operations a derived class needs to perform. diff --git a/trampoline/README.md b/trampoline/README.md index cae343a61df9..dc0bb270cb78 100644 --- a/trampoline/README.md +++ b/trampoline/README.md @@ -3,7 +3,7 @@ layout: pattern title: Trampoline folder: trampoline permalink: /patterns/trampoline/ -categories: Behavior +categories: Behavioral tags: - Java - Difficulty-Intermediate From 73f9b8bef1e5f9ed2c141a4252c8fce6720eedec Mon Sep 17 00:00:00 2001 From: Martin Vandenbussche Date: Sun, 17 Nov 2019 13:25:32 +0100 Subject: [PATCH 28/31] Adding composite specification (Issue#1093) (#1094) * Resolution proposition to Issue#1055 (UML diagram left to do) * Deciding not to modify the UML diagram for now * Resolution proposition to Issue#1093 * Code reformatting --- specification/README.md | 98 +++++++++++++++---- .../com/iluwatar/specification/app/App.java | 33 +++++-- .../iluwatar/specification/property/Mass.java | 4 +- .../selector/AbstractSelector.java | 44 +++++++++ .../specification/selector/ColorSelector.java | 3 +- .../selector/ConjunctionSelector.java | 47 +++++++++ .../selector/DisjunctionSelector.java | 47 +++++++++ .../selector/MassEqualSelector.java | 47 +++++++++ .../selector/MassGreaterThanSelector.java | 11 ++- .../selector/MassSmallerThanOrEqSelector.java | 11 ++- .../selector/MovementSelector.java | 3 +- .../selector/NegationSelector.java | 46 +++++++++ .../specification/selector/SizeSelector.java | 3 +- .../iluwatar/specification/app/AppTest.java | 2 - .../specification/creature/CreatureTest.java | 43 ++++---- .../selector/ColorSelectorTest.java | 8 +- .../selector/CompositeSelectorsTest.java | 93 ++++++++++++++++++ .../selector/MassSelectorTest.java | 4 +- .../selector/MovementSelectorTest.java | 10 +- .../selector/SizeSelectorTest.java | 8 +- 20 files changed, 492 insertions(+), 73 deletions(-) create mode 100644 specification/src/main/java/com/iluwatar/specification/selector/AbstractSelector.java create mode 100644 specification/src/main/java/com/iluwatar/specification/selector/ConjunctionSelector.java create mode 100644 specification/src/main/java/com/iluwatar/specification/selector/DisjunctionSelector.java create mode 100644 specification/src/main/java/com/iluwatar/specification/selector/MassEqualSelector.java create mode 100644 specification/src/main/java/com/iluwatar/specification/selector/NegationSelector.java create mode 100644 specification/src/test/java/com/iluwatar/specification/selector/CompositeSelectorsTest.java diff --git a/specification/README.md b/specification/README.md index bb95097e3cc7..e55c0b799217 100644 --- a/specification/README.md +++ b/specification/README.md @@ -31,7 +31,8 @@ Use the Specification pattern when Real world example -> There is a pool of different creatures and we often need to select some subset of them. We can write our search specification such as "creatures that can fly" or "creatures heavier than 500 kilograms" and give it to the party that will perform the filtering. +> There is a pool of different creatures and we often need to select some subset of them. +> We can write our search specification such as "creatures that can fly", "creatures heavier than 500 kilograms", or as a combination of other search specifications, and then give it to the party that will perform the filtering. In Plain Words @@ -44,8 +45,10 @@ Wikipedia says **Programmatic Example** If we look at our creature pool example from above, we have a set of creatures with certain properties.\ -Those properties can be part of a pre-defined, limited set (represented here by the enums Size, Movement and Color); but they can also be discrete (e.g. the mass of a Creature). In this case, it is more appropriate to use what we call "parameterized specification", where the property value can be given as an argument when the Creature is created, allowing for more flexibility. - +Those properties can be part of a pre-defined, limited set (represented here by the enums Size, Movement and Color); but they can also be continuous values (e.g. the mass of a Creature). +In this case, it is more appropriate to use what we call "parameterized specification", where the property value can be given as an argument when the Creature is instantiated, allowing for more flexibility. +A third option is to combine pre-defined and/or parameterized properties using boolean logic, allowing for near-endless selection possibilities (this is called Composite Specification, see below). +The pros and cons of each approach are detailed in the table at the end of this document. ```java public interface Creature { String getName(); @@ -56,8 +59,7 @@ public interface Creature { } ``` -And dragon implementation looks like this. - +And ``Dragon`` implementation looks like this. ```java public class Dragon extends AbstractCreature { @@ -67,10 +69,9 @@ public class Dragon extends AbstractCreature { } ``` -Now that we want to select some subset of them, we use selectors. To select creatures that fly, we should use MovementSelector. - +Now that we want to select some subset of them, we use selectors. To select creatures that fly, we should use ``MovementSelector``. ```java -public class MovementSelector implements Predicate { +public class MovementSelector extends AbstractSelector { private final Movement movement; @@ -85,10 +86,9 @@ public class MovementSelector implements Predicate { } ``` -On the other hand, we selecting creatures heavier than a chosen amount, we use MassGreaterThanSelector. - +On the other hand, when selecting creatures heavier than a chosen amount, we use ``MassGreaterThanSelector``. ```java -public class MassGreaterThanSelector implements Predicate { +public class MassGreaterThanSelector extends AbstractSelector { private final Mass mass; @@ -103,20 +103,84 @@ public class MassGreaterThanSelector implements Predicate { } ``` -With these building blocks in place, we can perform a search for red and flying creatures like this. +With these building blocks in place, we can perform a search for red creatures as follows : +```java + List redCreatures = creatures.stream().filter(new ColorSelector(Color.RED)) + .collect(Collectors.toList()); +``` +But we could also use our parameterized selector like this : ```java - List redAndFlyingCreatures = creatures.stream() - .filter(new ColorSelector(Color.RED).and(new MovementSelector(Movement.FLYING))).collect(Collectors.toList()); + List heavyCreatures = creatures.stream().filter(new MassGreaterThanSelector(500.0) + .collect(Collectors.toList()); ``` -But we could also use our paramterized selector like this. +Our third option is to combine multiple selectors together. Performing a search for special creatures (defined as red, flying, and not small) could be done as follows : +```java + AbstractSelector specialCreaturesSelector = + new ColorSelector(Color.RED).and(new MovementSelector(Movement.FLYING)).and(new SizeSelector(Size.SMALL).not()); + + List specialCreatures = creatures.stream().filter(specialCreaturesSelector) + .collect(Collectors.toList()); +``` + +**More on Composite Specification** + +In Composite Specification, we will create custom instances of ``AbstractSelector`` by combining other selectors (called "leaves") using the three basic logical operators. +These are implemented in ``ConjunctionSelector``, ``DisjunctionSelector`` and ``NegationSelector``. +```java +public abstract class AbstractSelector implements Predicate { + + public AbstractSelector and(AbstractSelector other) { + return new ConjunctionSelector<>(this, other); + } + + public AbstractSelector or(AbstractSelector other) { + return new DisjunctionSelector<>(this, other); + } + public AbstractSelector not() { + return new NegationSelector<>(this); + } +} +``` ```java - List heavyCreatures = creatures.stream() - .filter(new MassGreaterThanSelector(500.0).collect(Collectors.toList()); +public class ConjunctionSelector extends AbstractSelector { + + private List> leafComponents; + + @SafeVarargs + ConjunctionSelector(AbstractSelector... selectors) { + this.leafComponents = List.of(selectors); + } + + /** + * Tests if *all* selectors pass the test. + */ + @Override + public boolean test(T t) { + return leafComponents.stream().allMatch(comp -> (comp.test(t))); + } +} ``` +All that is left to do is now to create leaf selectors (be it hard-coded or parameterized ones) that are as generic as possible, +and we will be able to instantiate the ``AbstractSelector`` class by combining any amount of selectors, as exemplified above. +We should be careful though, as it is easy to make a mistake when combining many logical operators; in particular, we should pay attention to the priority of the operations.\ +In general, Composite Specification is a great way to write more reusable code, as there is no need to create a Selector class for each filtering operation. +Instead, we just create an instance of ``AbstractSelector`` "on the spot", using tour generic "leaf" selectors and some basic boolean logic. + + +**Comparison of the different approaches** + +| Pattern | Usage | Pros | Cons | +|---|---|---|---| +| Hard-Coded Specification | Selection criteria are few and known in advance | + Easy to implement | - Inflexible | +| | | + Expressive | +| Parameterized Specification | Selection criteria are a large range of values (e.g. mass, speed,...) | + Some flexibility | - Still requires special-purpose classes | +| Composite Specification | There are a lot of selection criteria that can be combined in multiple ways, hence it is not feasible to create a class for each selector | + Very flexible, without requiring many specialized classes | - Somewhat more difficult to comprehend | +| | | + Supports logical operations | - You still need to create the base classes used as leaves | + ## Related patterns * Repository diff --git a/specification/src/main/java/com/iluwatar/specification/app/App.java b/specification/src/main/java/com/iluwatar/specification/app/App.java index c1ff8211e9a5..2f9633313d83 100644 --- a/specification/src/main/java/com/iluwatar/specification/app/App.java +++ b/specification/src/main/java/com/iluwatar/specification/app/App.java @@ -31,9 +31,10 @@ import com.iluwatar.specification.creature.Shark; import com.iluwatar.specification.creature.Troll; import com.iluwatar.specification.property.Color; -import com.iluwatar.specification.property.Mass; import com.iluwatar.specification.property.Movement; +import com.iluwatar.specification.selector.AbstractSelector; import com.iluwatar.specification.selector.ColorSelector; +import com.iluwatar.specification.selector.MassEqualSelector; import com.iluwatar.specification.selector.MassGreaterThanSelector; import com.iluwatar.specification.selector.MassSmallerThanOrEqSelector; import com.iluwatar.specification.selector.MovementSelector; @@ -77,13 +78,8 @@ public static void main(String[] args) { List darkCreatures = creatures.stream().filter(new ColorSelector(Color.DARK)).collect(Collectors.toList()); darkCreatures.forEach(c -> LOGGER.info(c.toString())); - // find all red and flying creatures - LOGGER.info("Find all red and flying creatures"); - List redAndFlyingCreatures = - creatures.stream() - .filter(new ColorSelector(Color.RED).and(new MovementSelector(Movement.FLYING))) - .collect(Collectors.toList()); - redAndFlyingCreatures.forEach(c -> LOGGER.info(c.toString())); + + LOGGER.info("\n"); // so-called "parameterized" specification LOGGER.info("Demonstrating parameterized specification :"); // find all creatures heavier than 500kg @@ -98,5 +94,26 @@ public static void main(String[] args) { creatures.stream().filter(new MassSmallerThanOrEqSelector(500.0)) .collect(Collectors.toList()); lightCreatures.forEach(c -> LOGGER.info(c.toString())); + + LOGGER.info("\n"); + // so-called "composite" specification + LOGGER.info("Demonstrating composite specification :"); + // find all red and flying creatures + LOGGER.info("Find all red and flying creatures"); + List redAndFlyingCreatures = + creatures.stream() + .filter(new ColorSelector(Color.RED).and(new MovementSelector(Movement.FLYING))) + .collect(Collectors.toList()); + redAndFlyingCreatures.forEach(c -> LOGGER.info(c.toString())); + // find all creatures dark or red, non-swimming, and heavier than or equal to 400kg + LOGGER.info("Find all scary creatures"); + AbstractSelector scaryCreaturesSelector = new ColorSelector(Color.DARK) + .or(new ColorSelector(Color.RED)).and(new MovementSelector(Movement.SWIMMING).not()) + .and(new MassGreaterThanSelector(400.0).or(new MassEqualSelector(400.0))); + List scaryCreatures = + creatures.stream() + .filter(scaryCreaturesSelector) + .collect(Collectors.toList()); + scaryCreatures.forEach(c -> LOGGER.info(c.toString())); } } diff --git a/specification/src/main/java/com/iluwatar/specification/property/Mass.java b/specification/src/main/java/com/iluwatar/specification/property/Mass.java index 6be1edb3316f..b2d6ddc66f5f 100644 --- a/specification/src/main/java/com/iluwatar/specification/property/Mass.java +++ b/specification/src/main/java/com/iluwatar/specification/property/Mass.java @@ -23,7 +23,9 @@ package com.iluwatar.specification.property; -/** Mass property. */ +/** + * Mass property. + */ public class Mass { private double value; diff --git a/specification/src/main/java/com/iluwatar/specification/selector/AbstractSelector.java b/specification/src/main/java/com/iluwatar/specification/selector/AbstractSelector.java new file mode 100644 index 000000000000..2dea52271152 --- /dev/null +++ b/specification/src/main/java/com/iluwatar/specification/selector/AbstractSelector.java @@ -0,0 +1,44 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.specification.selector; + +import java.util.function.Predicate; + +/** + * Base class for selectors. + */ +public abstract class AbstractSelector implements Predicate { + + public AbstractSelector and(AbstractSelector other) { + return new ConjunctionSelector<>(this, other); + } + + public AbstractSelector or(AbstractSelector other) { + return new DisjunctionSelector<>(this, other); + } + + public AbstractSelector not() { + return new NegationSelector<>(this); + } +} diff --git a/specification/src/main/java/com/iluwatar/specification/selector/ColorSelector.java b/specification/src/main/java/com/iluwatar/specification/selector/ColorSelector.java index 93caf612ff92..cefa5f92ec2a 100644 --- a/specification/src/main/java/com/iluwatar/specification/selector/ColorSelector.java +++ b/specification/src/main/java/com/iluwatar/specification/selector/ColorSelector.java @@ -25,12 +25,11 @@ import com.iluwatar.specification.creature.Creature; import com.iluwatar.specification.property.Color; -import java.util.function.Predicate; /** * Color selector. */ -public class ColorSelector implements Predicate { +public class ColorSelector extends AbstractSelector { private final Color color; diff --git a/specification/src/main/java/com/iluwatar/specification/selector/ConjunctionSelector.java b/specification/src/main/java/com/iluwatar/specification/selector/ConjunctionSelector.java new file mode 100644 index 000000000000..bd29aa2603b7 --- /dev/null +++ b/specification/src/main/java/com/iluwatar/specification/selector/ConjunctionSelector.java @@ -0,0 +1,47 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.specification.selector; + +import java.util.List; + +/** + * A Selector defined as the conjunction (AND) of other (leaf) selectors. + */ +public class ConjunctionSelector extends AbstractSelector { + + private List> leafComponents; + + @SafeVarargs + ConjunctionSelector(AbstractSelector... selectors) { + this.leafComponents = List.of(selectors); + } + + /** + * Tests if *all* selectors pass the test. + */ + @Override + public boolean test(T t) { + return leafComponents.stream().allMatch(comp -> (comp.test(t))); + } +} diff --git a/specification/src/main/java/com/iluwatar/specification/selector/DisjunctionSelector.java b/specification/src/main/java/com/iluwatar/specification/selector/DisjunctionSelector.java new file mode 100644 index 000000000000..1fb38a43dc5b --- /dev/null +++ b/specification/src/main/java/com/iluwatar/specification/selector/DisjunctionSelector.java @@ -0,0 +1,47 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.specification.selector; + +import java.util.List; + +/** + * A Selector defined as the disjunction (OR) of other (leaf) selectors. + */ +public class DisjunctionSelector extends AbstractSelector { + + private List> leafComponents; + + @SafeVarargs + DisjunctionSelector(AbstractSelector... selectors) { + this.leafComponents = List.of(selectors); + } + + /** + * Tests if *at least one* selector passes the test. + */ + @Override + public boolean test(T t) { + return leafComponents.stream().anyMatch(comp -> comp.test(t)); + } +} diff --git a/specification/src/main/java/com/iluwatar/specification/selector/MassEqualSelector.java b/specification/src/main/java/com/iluwatar/specification/selector/MassEqualSelector.java new file mode 100644 index 000000000000..e2c0c1e7cf0a --- /dev/null +++ b/specification/src/main/java/com/iluwatar/specification/selector/MassEqualSelector.java @@ -0,0 +1,47 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.specification.selector; + +import com.iluwatar.specification.creature.Creature; +import com.iluwatar.specification.property.Mass; + +/** + * Mass selector for values exactly equal than the parameter. + */ +public class MassEqualSelector extends AbstractSelector { + + private final Mass mass; + + /** + * The use of a double as a parameter will spare some typing when instantiating this class. + */ + public MassEqualSelector(double mass) { + this.mass = new Mass(mass); + } + + @Override + public boolean test(Creature t) { + return t.getMass().equals(mass); + } +} diff --git a/specification/src/main/java/com/iluwatar/specification/selector/MassGreaterThanSelector.java b/specification/src/main/java/com/iluwatar/specification/selector/MassGreaterThanSelector.java index d613e6a08efc..56160c12ad58 100644 --- a/specification/src/main/java/com/iluwatar/specification/selector/MassGreaterThanSelector.java +++ b/specification/src/main/java/com/iluwatar/specification/selector/MassGreaterThanSelector.java @@ -25,14 +25,17 @@ import com.iluwatar.specification.creature.Creature; import com.iluwatar.specification.property.Mass; -import java.util.function.Predicate; -/** Mass selector for values greater than the parameter. */ -public class MassGreaterThanSelector implements Predicate { +/** + * Mass selector for values greater than the parameter. + */ +public class MassGreaterThanSelector extends AbstractSelector { private final Mass mass; - /** The use of a double as a parameter will spare some typing when instantiating this class. */ + /** + * The use of a double as a parameter will spare some typing when instantiating this class. + */ public MassGreaterThanSelector(double mass) { this.mass = new Mass(mass); } diff --git a/specification/src/main/java/com/iluwatar/specification/selector/MassSmallerThanOrEqSelector.java b/specification/src/main/java/com/iluwatar/specification/selector/MassSmallerThanOrEqSelector.java index 8a6a9f80e2d5..94ab3cc9a1a8 100644 --- a/specification/src/main/java/com/iluwatar/specification/selector/MassSmallerThanOrEqSelector.java +++ b/specification/src/main/java/com/iluwatar/specification/selector/MassSmallerThanOrEqSelector.java @@ -25,14 +25,17 @@ import com.iluwatar.specification.creature.Creature; import com.iluwatar.specification.property.Mass; -import java.util.function.Predicate; -/** Mass selector for values smaller or equal to the parameter. */ -public class MassSmallerThanOrEqSelector implements Predicate { +/** + * Mass selector for values smaller or equal to the parameter. + */ +public class MassSmallerThanOrEqSelector extends AbstractSelector { private final Mass mass; - /** The use of a double as a parameter will spare some typing when instantiating this class. */ + /** + * The use of a double as a parameter will spare some typing when instantiating this class. + */ public MassSmallerThanOrEqSelector(double mass) { this.mass = new Mass(mass); } diff --git a/specification/src/main/java/com/iluwatar/specification/selector/MovementSelector.java b/specification/src/main/java/com/iluwatar/specification/selector/MovementSelector.java index 1818058c15d8..e2a0bdb15fad 100644 --- a/specification/src/main/java/com/iluwatar/specification/selector/MovementSelector.java +++ b/specification/src/main/java/com/iluwatar/specification/selector/MovementSelector.java @@ -25,12 +25,11 @@ import com.iluwatar.specification.creature.Creature; import com.iluwatar.specification.property.Movement; -import java.util.function.Predicate; /** * Movement selector. */ -public class MovementSelector implements Predicate { +public class MovementSelector extends AbstractSelector { private final Movement movement; diff --git a/specification/src/main/java/com/iluwatar/specification/selector/NegationSelector.java b/specification/src/main/java/com/iluwatar/specification/selector/NegationSelector.java new file mode 100644 index 000000000000..ad3063000845 --- /dev/null +++ b/specification/src/main/java/com/iluwatar/specification/selector/NegationSelector.java @@ -0,0 +1,46 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.specification.selector; + + +/** + * A Selector defined as the negation (NOT) of a (leaf) selectors. This is of course only useful + * when used in combination with other composite selectors. + */ +public class NegationSelector extends AbstractSelector { + + private AbstractSelector component; + + NegationSelector(AbstractSelector selector) { + this.component = selector; + } + + /** + * Tests if the selector fails the test (yes). + */ + @Override + public boolean test(T t) { + return !(component.test(t)); + } +} diff --git a/specification/src/main/java/com/iluwatar/specification/selector/SizeSelector.java b/specification/src/main/java/com/iluwatar/specification/selector/SizeSelector.java index a997c034239d..6d5aa85d0bfe 100644 --- a/specification/src/main/java/com/iluwatar/specification/selector/SizeSelector.java +++ b/specification/src/main/java/com/iluwatar/specification/selector/SizeSelector.java @@ -25,12 +25,11 @@ import com.iluwatar.specification.creature.Creature; import com.iluwatar.specification.property.Size; -import java.util.function.Predicate; /** * Size selector. */ -public class SizeSelector implements Predicate { +public class SizeSelector extends AbstractSelector { private final Size size; diff --git a/specification/src/test/java/com/iluwatar/specification/app/AppTest.java b/specification/src/test/java/com/iluwatar/specification/app/AppTest.java index 5f6d950fe6f4..7585a113d34d 100644 --- a/specification/src/test/java/com/iluwatar/specification/app/AppTest.java +++ b/specification/src/test/java/com/iluwatar/specification/app/AppTest.java @@ -26,9 +26,7 @@ import org.junit.jupiter.api.Test; /** - * * Application test - * */ public class AppTest { diff --git a/specification/src/test/java/com/iluwatar/specification/creature/CreatureTest.java b/specification/src/test/java/com/iluwatar/specification/creature/CreatureTest.java index ecd3de27f541..58af7248a867 100644 --- a/specification/src/test/java/com/iluwatar/specification/creature/CreatureTest.java +++ b/specification/src/test/java/com/iluwatar/specification/creature/CreatureTest.java @@ -23,18 +23,17 @@ package com.iluwatar.specification.creature; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + import com.iluwatar.specification.property.Color; import com.iluwatar.specification.property.Mass; import com.iluwatar.specification.property.Movement; import com.iluwatar.specification.property.Size; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; - import java.util.Collection; import java.util.List; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; /** * Date: 12/29/15 - 7:47 PM @@ -48,12 +47,18 @@ public class CreatureTest { */ public static Collection dataProvider() { return List.of( - new Object[]{new Dragon(), "Dragon", Size.LARGE, Movement.FLYING, Color.RED, new Mass(39300.0)}, - new Object[]{new Goblin(), "Goblin", Size.SMALL, Movement.WALKING, Color.GREEN, new Mass(30.0)}, - new Object[]{new KillerBee(), "KillerBee", Size.SMALL, Movement.FLYING, Color.LIGHT, new Mass(6.7)}, - new Object[]{new Octopus(), "Octopus", Size.NORMAL, Movement.SWIMMING, Color.DARK, new Mass(12.0)}, - new Object[]{new Shark(), "Shark", Size.NORMAL, Movement.SWIMMING, Color.LIGHT, new Mass(500.0)}, - new Object[]{new Troll(), "Troll", Size.LARGE, Movement.WALKING, Color.DARK, new Mass(4000.0)} + new Object[]{new Dragon(), "Dragon", Size.LARGE, Movement.FLYING, Color.RED, + new Mass(39300.0)}, + new Object[]{new Goblin(), "Goblin", Size.SMALL, Movement.WALKING, Color.GREEN, + new Mass(30.0)}, + new Object[]{new KillerBee(), "KillerBee", Size.SMALL, Movement.FLYING, Color.LIGHT, + new Mass(6.7)}, + new Object[]{new Octopus(), "Octopus", Size.NORMAL, Movement.SWIMMING, Color.DARK, + new Mass(12.0)}, + new Object[]{new Shark(), "Shark", Size.NORMAL, Movement.SWIMMING, Color.LIGHT, + new Mass(500.0)}, + new Object[]{new Troll(), "Troll", Size.LARGE, Movement.WALKING, Color.DARK, + new Mass(4000.0)} ); } @@ -77,24 +82,28 @@ public void testGetMovement(Creature testedCreature, String name, Size size, Mov @ParameterizedTest @MethodSource("dataProvider") - public void testGetColor(Creature testedCreature, String name, Size size, Movement movement, Color color) { + public void testGetColor(Creature testedCreature, String name, Size size, Movement movement, + Color color) { assertEquals(color, testedCreature.getColor()); } @ParameterizedTest @MethodSource("dataProvider") - public void testGetMass(Creature testedCreature, String name, Size size, Movement movement, Color color, Mass mass) { + public void testGetMass(Creature testedCreature, String name, Size size, Movement movement, + Color color, Mass mass) { assertEquals(mass, testedCreature.getMass()); } @ParameterizedTest @MethodSource("dataProvider") - public void testToString(Creature testedCreature, String name, Size size, Movement movement, Color color, Mass mass) { + public void testToString(Creature testedCreature, String name, Size size, Movement movement, + Color color, Mass mass) { final String toString = testedCreature.toString(); assertNotNull(toString); assertEquals( - String.format("%s [size=%s, movement=%s, color=%s, mass=%s]", name, size, movement, color, mass), - toString + String.format("%s [size=%s, movement=%s, color=%s, mass=%s]", name, size, movement, color, + mass), + toString ); } } \ No newline at end of file diff --git a/specification/src/test/java/com/iluwatar/specification/selector/ColorSelectorTest.java b/specification/src/test/java/com/iluwatar/specification/selector/ColorSelectorTest.java index cc47ba5955e2..f1029063dc50 100644 --- a/specification/src/test/java/com/iluwatar/specification/selector/ColorSelectorTest.java +++ b/specification/src/test/java/com/iluwatar/specification/selector/ColorSelectorTest.java @@ -23,15 +23,15 @@ package com.iluwatar.specification.selector; -import com.iluwatar.specification.creature.Creature; -import com.iluwatar.specification.property.Color; -import org.junit.jupiter.api.Test; - import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import com.iluwatar.specification.creature.Creature; +import com.iluwatar.specification.property.Color; +import org.junit.jupiter.api.Test; + /** * Date: 12/29/15 - 7:35 PM * diff --git a/specification/src/test/java/com/iluwatar/specification/selector/CompositeSelectorsTest.java b/specification/src/test/java/com/iluwatar/specification/selector/CompositeSelectorsTest.java new file mode 100644 index 000000000000..75809c54280f --- /dev/null +++ b/specification/src/test/java/com/iluwatar/specification/selector/CompositeSelectorsTest.java @@ -0,0 +1,93 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.specification.selector; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.iluwatar.specification.creature.Creature; +import com.iluwatar.specification.property.Mass; +import com.iluwatar.specification.property.Movement; +import org.junit.jupiter.api.Test; + +public class CompositeSelectorsTest { + + /** + * Verify if the conjunction selector gives the correct results. + */ + @Test + public void testAndComposition() { + final Creature swimmingHeavyCreature = mock(Creature.class); + when(swimmingHeavyCreature.getMovement()).thenReturn(Movement.SWIMMING); + when(swimmingHeavyCreature.getMass()).thenReturn(new Mass(100.0)); + + final Creature swimmingLightCreature = mock(Creature.class); + when(swimmingLightCreature.getMovement()).thenReturn(Movement.SWIMMING); + when(swimmingLightCreature.getMass()).thenReturn(new Mass(25.0)); + + final AbstractSelector lightAndSwimmingSelector = new MassSmallerThanOrEqSelector( + 50.0).and(new MovementSelector(Movement.SWIMMING)); + assertFalse(lightAndSwimmingSelector.test(swimmingHeavyCreature)); + assertTrue(lightAndSwimmingSelector.test(swimmingLightCreature)); + } + + /** + * Verify if the disjunction selector gives the correct results. + */ + @Test + public void testOrComposition() { + final Creature swimmingHeavyCreature = mock(Creature.class); + when(swimmingHeavyCreature.getMovement()).thenReturn(Movement.SWIMMING); + when(swimmingHeavyCreature.getMass()).thenReturn(new Mass(100.0)); + + final Creature swimmingLightCreature = mock(Creature.class); + when(swimmingLightCreature.getMovement()).thenReturn(Movement.SWIMMING); + when(swimmingLightCreature.getMass()).thenReturn(new Mass(25.0)); + + final AbstractSelector lightOrSwimmingSelector = new MassSmallerThanOrEqSelector(50.0) + .or(new MovementSelector(Movement.SWIMMING)); + assertTrue(lightOrSwimmingSelector.test(swimmingHeavyCreature)); + assertTrue(lightOrSwimmingSelector.test(swimmingLightCreature)); + } + + /** + * Verify if the negation selector gives the correct results. + */ + @Test + public void testNotComposition() { + final Creature swimmingHeavyCreature = mock(Creature.class); + when(swimmingHeavyCreature.getMovement()).thenReturn(Movement.SWIMMING); + when(swimmingHeavyCreature.getMass()).thenReturn(new Mass(100.0)); + + final Creature swimmingLightCreature = mock(Creature.class); + when(swimmingLightCreature.getMovement()).thenReturn(Movement.SWIMMING); + when(swimmingLightCreature.getMass()).thenReturn(new Mass(25.0)); + + final AbstractSelector heavySelector = new MassSmallerThanOrEqSelector(50.0).not(); + assertTrue(heavySelector.test(swimmingHeavyCreature)); + assertFalse(heavySelector.test(swimmingLightCreature)); + } +} diff --git a/specification/src/test/java/com/iluwatar/specification/selector/MassSelectorTest.java b/specification/src/test/java/com/iluwatar/specification/selector/MassSelectorTest.java index eb2f4c5fe7ae..287f401648e6 100644 --- a/specification/src/test/java/com/iluwatar/specification/selector/MassSelectorTest.java +++ b/specification/src/test/java/com/iluwatar/specification/selector/MassSelectorTest.java @@ -34,7 +34,9 @@ public class MassSelectorTest { - /** Verify if the mass selector gives the correct results */ + /** + * Verify if the mass selector gives the correct results. + */ @Test public void testMass() { final Creature lightCreature = mock(Creature.class); diff --git a/specification/src/test/java/com/iluwatar/specification/selector/MovementSelectorTest.java b/specification/src/test/java/com/iluwatar/specification/selector/MovementSelectorTest.java index e194790fbc2c..f3d2482ad9fc 100644 --- a/specification/src/test/java/com/iluwatar/specification/selector/MovementSelectorTest.java +++ b/specification/src/test/java/com/iluwatar/specification/selector/MovementSelectorTest.java @@ -23,15 +23,15 @@ package com.iluwatar.specification.selector; -import com.iluwatar.specification.creature.Creature; -import com.iluwatar.specification.property.Movement; -import org.junit.jupiter.api.Test; - import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import com.iluwatar.specification.creature.Creature; +import com.iluwatar.specification.property.Movement; +import org.junit.jupiter.api.Test; + /** * Date: 12/29/15 - 7:37 PM * @@ -40,7 +40,7 @@ public class MovementSelectorTest { /** - * Verify if the movement selector gives the correct results + * Verify if the movement selector gives the correct results. */ @Test public void testMovement() { diff --git a/specification/src/test/java/com/iluwatar/specification/selector/SizeSelectorTest.java b/specification/src/test/java/com/iluwatar/specification/selector/SizeSelectorTest.java index 9145f9b810c6..7dcb30ee22f9 100644 --- a/specification/src/test/java/com/iluwatar/specification/selector/SizeSelectorTest.java +++ b/specification/src/test/java/com/iluwatar/specification/selector/SizeSelectorTest.java @@ -23,15 +23,15 @@ package com.iluwatar.specification.selector; -import com.iluwatar.specification.creature.Creature; -import com.iluwatar.specification.property.Size; -import org.junit.jupiter.api.Test; - import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import com.iluwatar.specification.creature.Creature; +import com.iluwatar.specification.property.Size; +import org.junit.jupiter.api.Test; + /** * Date: 12/29/15 - 7:43 PM * From 7d845505b5f854ee3d732087372e009869e89f4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilkka=20Sepp=C3=A4l=C3=A4?= Date: Sun, 17 Nov 2019 14:44:42 +0200 Subject: [PATCH 29/31] Java Design Patterns 1.22.0 --- abstract-document/pom.xml | 2 +- abstract-factory/pom.xml | 2 +- acyclic-visitor/pom.xml | 2 +- adapter/pom.xml | 2 +- aggregator-microservices/aggregator-service/pom.xml | 2 +- aggregator-microservices/information-microservice/pom.xml | 2 +- aggregator-microservices/inventory-microservice/pom.xml | 2 +- aggregator-microservices/pom.xml | 2 +- ambassador/pom.xml | 2 +- api-gateway/api-gateway-service/pom.xml | 2 +- api-gateway/image-microservice/pom.xml | 2 +- api-gateway/pom.xml | 2 +- api-gateway/price-microservice/pom.xml | 2 +- async-method-invocation/pom.xml | 2 +- balking/pom.xml | 2 +- bridge/pom.xml | 2 +- builder/pom.xml | 2 +- business-delegate/pom.xml | 2 +- bytecode/pom.xml | 2 +- caching/pom.xml | 2 +- callback/pom.xml | 2 +- chain/pom.xml | 2 +- circuit-breaker/pom.xml | 2 +- collection-pipeline/pom.xml | 2 +- command/pom.xml | 2 +- commander/pom.xml | 2 +- composite/pom.xml | 2 +- converter/pom.xml | 2 +- cqrs/pom.xml | 2 +- dao/pom.xml | 2 +- data-bus/pom.xml | 2 +- data-locality/pom.xml | 2 +- data-mapper/pom.xml | 2 +- data-transfer-object/pom.xml | 2 +- decorator/pom.xml | 2 +- delegation/pom.xml | 2 +- dependency-injection/pom.xml | 2 +- dirty-flag/pom.xml | 4 ++-- double-buffer/pom.xml | 2 +- double-checked-locking/pom.xml | 2 +- double-dispatch/pom.xml | 2 +- eip-aggregator/pom.xml | 2 +- eip-message-channel/pom.xml | 2 +- eip-publish-subscribe/pom.xml | 2 +- eip-splitter/pom.xml | 2 +- eip-wire-tap/pom.xml | 2 +- event-aggregator/pom.xml | 2 +- event-asynchronous/pom.xml | 2 +- event-driven-architecture/pom.xml | 2 +- event-queue/pom.xml | 2 +- event-sourcing/pom.xml | 2 +- execute-around/pom.xml | 2 +- extension-objects/pom.xml | 2 +- facade/pom.xml | 2 +- factory-kit/pom.xml | 2 +- factory-method/pom.xml | 2 +- feature-toggle/pom.xml | 2 +- fluentinterface/pom.xml | 2 +- flux/pom.xml | 2 +- flyweight/pom.xml | 2 +- front-controller/pom.xml | 2 +- game-loop/pom.xml | 2 +- guarded-suspension/pom.xml | 2 +- half-sync-half-async/pom.xml | 2 +- hexagonal/pom.xml | 2 +- intercepting-filter/pom.xml | 2 +- interpreter/pom.xml | 2 +- iterator/pom.xml | 2 +- layers/pom.xml | 2 +- lazy-loading/pom.xml | 2 +- leader-election/pom.xml | 2 +- marker/pom.xml | 2 +- master-worker-pattern/pom.xml | 2 +- mediator/pom.xml | 2 +- memento/pom.xml | 2 +- model-view-controller/pom.xml | 2 +- model-view-presenter/pom.xml | 2 +- module/pom.xml | 2 +- monad/pom.xml | 2 +- monostate/pom.xml | 2 +- multiton/pom.xml | 2 +- mute-idiom/pom.xml | 2 +- mutex/pom.xml | 2 +- naked-objects/dom/pom.xml | 2 +- naked-objects/fixture/pom.xml | 2 +- naked-objects/integtests/pom.xml | 2 +- naked-objects/pom.xml | 8 ++++---- naked-objects/webapp/pom.xml | 2 +- null-object/pom.xml | 2 +- object-mother/pom.xml | 2 +- object-pool/pom.xml | 2 +- observer/pom.xml | 2 +- page-object/pom.xml | 2 +- page-object/sample-application/pom.xml | 2 +- page-object/test-automation/pom.xml | 2 +- partial-response/pom.xml | 2 +- pipeline/pom.xml | 2 +- poison-pill/pom.xml | 2 +- pom.xml | 2 +- priority-queue/pom.xml | 2 +- private-class-data/pom.xml | 2 +- producer-consumer/pom.xml | 2 +- promise/pom.xml | 2 +- property/pom.xml | 2 +- prototype/pom.xml | 2 +- proxy/pom.xml | 2 +- queue-load-leveling/pom.xml | 2 +- reactor/pom.xml | 2 +- reader-writer-lock/pom.xml | 2 +- repository/pom.xml | 2 +- resource-acquisition-is-initialization/pom.xml | 2 +- retry/pom.xml | 2 +- role-object/pom.xml | 2 +- saga/pom.xml | 2 +- semaphore/pom.xml | 2 +- servant/pom.xml | 2 +- serverless/pom.xml | 2 +- service-layer/pom.xml | 2 +- service-locator/pom.xml | 2 +- sharding/pom.xml | 2 +- singleton/pom.xml | 2 +- spatial-partition/pom.xml | 2 +- specification/pom.xml | 2 +- state/pom.xml | 2 +- step-builder/pom.xml | 2 +- strategy/pom.xml | 2 +- subclass-sandbox/pom.xml | 2 +- template-method/pom.xml | 2 +- thread-pool/pom.xml | 2 +- throttling/pom.xml | 2 +- tls/pom.xml | 2 +- tolerant-reader/pom.xml | 2 +- trampoline/pom.xml | 2 +- twin/pom.xml | 2 +- typeobjectpattern/pom.xml | 2 +- unit-of-work/pom.xml | 2 +- value-object/pom.xml | 2 +- visitor/pom.xml | 2 +- 138 files changed, 142 insertions(+), 142 deletions(-) diff --git a/abstract-document/pom.xml b/abstract-document/pom.xml index ec1bd16dc633..620fd55bd736 100644 --- a/abstract-document/pom.xml +++ b/abstract-document/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.22.0-SNAPSHOT + 1.22.0 abstract-document diff --git a/abstract-factory/pom.xml b/abstract-factory/pom.xml index 7e2613a0402f..2b265140af04 100644 --- a/abstract-factory/pom.xml +++ b/abstract-factory/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 abstract-factory diff --git a/acyclic-visitor/pom.xml b/acyclic-visitor/pom.xml index 9e59d1cef31f..b6e4a635fb05 100644 --- a/acyclic-visitor/pom.xml +++ b/acyclic-visitor/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 acyclic-visitor diff --git a/adapter/pom.xml b/adapter/pom.xml index 4beedc26f85d..b815886beb87 100644 --- a/adapter/pom.xml +++ b/adapter/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 adapter diff --git a/aggregator-microservices/aggregator-service/pom.xml b/aggregator-microservices/aggregator-service/pom.xml index d6ebc823c307..9fbc362fddfe 100644 --- a/aggregator-microservices/aggregator-service/pom.xml +++ b/aggregator-microservices/aggregator-service/pom.xml @@ -29,7 +29,7 @@ aggregator-microservices com.iluwatar - 1.22.0-SNAPSHOT + 1.22.0 4.0.0 aggregator-service diff --git a/aggregator-microservices/information-microservice/pom.xml b/aggregator-microservices/information-microservice/pom.xml index f20337be309b..faf327371b7e 100644 --- a/aggregator-microservices/information-microservice/pom.xml +++ b/aggregator-microservices/information-microservice/pom.xml @@ -29,7 +29,7 @@ aggregator-microservices com.iluwatar - 1.22.0-SNAPSHOT + 1.22.0 4.0.0 diff --git a/aggregator-microservices/inventory-microservice/pom.xml b/aggregator-microservices/inventory-microservice/pom.xml index b4d62606f38b..f1dd08f56c75 100644 --- a/aggregator-microservices/inventory-microservice/pom.xml +++ b/aggregator-microservices/inventory-microservice/pom.xml @@ -29,7 +29,7 @@ aggregator-microservices com.iluwatar - 1.22.0-SNAPSHOT + 1.22.0 4.0.0 inventory-microservice diff --git a/aggregator-microservices/pom.xml b/aggregator-microservices/pom.xml index 7e4efa9f7b07..438ff3bed47a 100644 --- a/aggregator-microservices/pom.xml +++ b/aggregator-microservices/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.22.0-SNAPSHOT + 1.22.0 4.0.0 aggregator-microservices diff --git a/ambassador/pom.xml b/ambassador/pom.xml index 0ab56632bce4..2c32fe537a87 100644 --- a/ambassador/pom.xml +++ b/ambassador/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.22.0-SNAPSHOT + 1.22.0 4.0.0 ambassador diff --git a/api-gateway/api-gateway-service/pom.xml b/api-gateway/api-gateway-service/pom.xml index fa3e7286ba85..17869b9961bb 100644 --- a/api-gateway/api-gateway-service/pom.xml +++ b/api-gateway/api-gateway-service/pom.xml @@ -29,7 +29,7 @@ api-gateway com.iluwatar - 1.22.0-SNAPSHOT + 1.22.0 4.0.0 api-gateway-service diff --git a/api-gateway/image-microservice/pom.xml b/api-gateway/image-microservice/pom.xml index 06bd0b6e467d..333abaf508f7 100644 --- a/api-gateway/image-microservice/pom.xml +++ b/api-gateway/image-microservice/pom.xml @@ -29,7 +29,7 @@ api-gateway com.iluwatar - 1.22.0-SNAPSHOT + 1.22.0 4.0.0 image-microservice diff --git a/api-gateway/pom.xml b/api-gateway/pom.xml index 8ebf7a73f948..0b315a444733 100644 --- a/api-gateway/pom.xml +++ b/api-gateway/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.22.0-SNAPSHOT + 1.22.0 4.0.0 api-gateway diff --git a/api-gateway/price-microservice/pom.xml b/api-gateway/price-microservice/pom.xml index ad21da6831c8..913ca0c630fe 100644 --- a/api-gateway/price-microservice/pom.xml +++ b/api-gateway/price-microservice/pom.xml @@ -29,7 +29,7 @@ api-gateway com.iluwatar - 1.22.0-SNAPSHOT + 1.22.0 4.0.0 diff --git a/async-method-invocation/pom.xml b/async-method-invocation/pom.xml index 6d118e74727a..4d461b5103f8 100644 --- a/async-method-invocation/pom.xml +++ b/async-method-invocation/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 async-method-invocation diff --git a/balking/pom.xml b/balking/pom.xml index 8d798ecb43a0..5b71c8c85ea8 100644 --- a/balking/pom.xml +++ b/balking/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.22.0-SNAPSHOT + 1.22.0 4.0.0 diff --git a/bridge/pom.xml b/bridge/pom.xml index 56b2b61f1fb3..6342ad4c2a18 100644 --- a/bridge/pom.xml +++ b/bridge/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 bridge diff --git a/builder/pom.xml b/builder/pom.xml index 3a8e6ccf0d85..fc3a439acf16 100644 --- a/builder/pom.xml +++ b/builder/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 builder diff --git a/business-delegate/pom.xml b/business-delegate/pom.xml index 7c7313e8f3b8..6052c650a892 100644 --- a/business-delegate/pom.xml +++ b/business-delegate/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 business-delegate diff --git a/bytecode/pom.xml b/bytecode/pom.xml index ac60e9345dba..bab4ed4f111a 100644 --- a/bytecode/pom.xml +++ b/bytecode/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.22.0-SNAPSHOT + 1.22.0 4.0.0 diff --git a/caching/pom.xml b/caching/pom.xml index fec70be733db..373caa0f4f24 100644 --- a/caching/pom.xml +++ b/caching/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 caching diff --git a/callback/pom.xml b/callback/pom.xml index 14c3462036a3..9adfbe0087da 100644 --- a/callback/pom.xml +++ b/callback/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 callback diff --git a/chain/pom.xml b/chain/pom.xml index 4e5357b8d4f4..c1362a45770e 100644 --- a/chain/pom.xml +++ b/chain/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 chain diff --git a/circuit-breaker/pom.xml b/circuit-breaker/pom.xml index 6ef7da2236a2..b8092ad62d17 100644 --- a/circuit-breaker/pom.xml +++ b/circuit-breaker/pom.xml @@ -27,7 +27,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 circuit-breaker diff --git a/collection-pipeline/pom.xml b/collection-pipeline/pom.xml index 0ab16f8259d1..397224d50e4e 100644 --- a/collection-pipeline/pom.xml +++ b/collection-pipeline/pom.xml @@ -27,7 +27,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 collection-pipeline diff --git a/command/pom.xml b/command/pom.xml index d9fbd90d091d..633f332587ac 100644 --- a/command/pom.xml +++ b/command/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 command diff --git a/commander/pom.xml b/commander/pom.xml index fbe45337707e..78ff81e38287 100644 --- a/commander/pom.xml +++ b/commander/pom.xml @@ -27,7 +27,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 commander diff --git a/composite/pom.xml b/composite/pom.xml index fb16cae3af53..7cb008d10f16 100644 --- a/composite/pom.xml +++ b/composite/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 composite diff --git a/converter/pom.xml b/converter/pom.xml index 6c900efc3305..6b6969ebb8f3 100644 --- a/converter/pom.xml +++ b/converter/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.22.0-SNAPSHOT + 1.22.0 4.0.0 diff --git a/cqrs/pom.xml b/cqrs/pom.xml index feab9d1acacb..14969e89416a 100644 --- a/cqrs/pom.xml +++ b/cqrs/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 cqrs diff --git a/dao/pom.xml b/dao/pom.xml index 5d6bc94546fa..51688d3e7b43 100644 --- a/dao/pom.xml +++ b/dao/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 dao diff --git a/data-bus/pom.xml b/data-bus/pom.xml index 230fe6b84bde..d0a655d67c42 100644 --- a/data-bus/pom.xml +++ b/data-bus/pom.xml @@ -33,7 +33,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 data-bus diff --git a/data-locality/pom.xml b/data-locality/pom.xml index 12c0f4f185e6..f7874149a8ea 100644 --- a/data-locality/pom.xml +++ b/data-locality/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 data-locality diff --git a/data-mapper/pom.xml b/data-mapper/pom.xml index 7da70f8fd243..e547f6a0eb8d 100644 --- a/data-mapper/pom.xml +++ b/data-mapper/pom.xml @@ -28,7 +28,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 data-mapper diff --git a/data-transfer-object/pom.xml b/data-transfer-object/pom.xml index ebdb15afa3dd..fb0c55a59a48 100644 --- a/data-transfer-object/pom.xml +++ b/data-transfer-object/pom.xml @@ -28,7 +28,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 data-transfer-object diff --git a/decorator/pom.xml b/decorator/pom.xml index 9b9ae0548602..a6f7dc58357d 100644 --- a/decorator/pom.xml +++ b/decorator/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 decorator diff --git a/delegation/pom.xml b/delegation/pom.xml index c7ceea6c0c48..46e19240133c 100644 --- a/delegation/pom.xml +++ b/delegation/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.22.0-SNAPSHOT + 1.22.0 4.0.0 diff --git a/dependency-injection/pom.xml b/dependency-injection/pom.xml index fd9584ed2ac8..018393738194 100644 --- a/dependency-injection/pom.xml +++ b/dependency-injection/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 dependency-injection diff --git a/dirty-flag/pom.xml b/dirty-flag/pom.xml index a044ad4d1e07..20fa25d8b5b2 100644 --- a/dirty-flag/pom.xml +++ b/dirty-flag/pom.xml @@ -29,11 +29,11 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 com.iluwatar dirty-flag - 1.22.0-SNAPSHOT + 1.22.0 dirty-flag http://maven.apache.org diff --git a/double-buffer/pom.xml b/double-buffer/pom.xml index a904c58842ef..5af4ccd7fc95 100644 --- a/double-buffer/pom.xml +++ b/double-buffer/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.22.0-SNAPSHOT + 1.22.0 4.0.0 diff --git a/double-checked-locking/pom.xml b/double-checked-locking/pom.xml index 02b03b7733f4..2b3af0c373dd 100644 --- a/double-checked-locking/pom.xml +++ b/double-checked-locking/pom.xml @@ -27,7 +27,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 double-checked-locking diff --git a/double-dispatch/pom.xml b/double-dispatch/pom.xml index 0884d29c2164..53ac5d95d26b 100644 --- a/double-dispatch/pom.xml +++ b/double-dispatch/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 double-dispatch diff --git a/eip-aggregator/pom.xml b/eip-aggregator/pom.xml index e4b96d0aa75d..1633ce4649ea 100644 --- a/eip-aggregator/pom.xml +++ b/eip-aggregator/pom.xml @@ -31,7 +31,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 diff --git a/eip-message-channel/pom.xml b/eip-message-channel/pom.xml index 5e72da9ef32e..20f92388d6b6 100644 --- a/eip-message-channel/pom.xml +++ b/eip-message-channel/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 eip-message-channel diff --git a/eip-publish-subscribe/pom.xml b/eip-publish-subscribe/pom.xml index 150490a7f0da..6c6bd2a0eeee 100644 --- a/eip-publish-subscribe/pom.xml +++ b/eip-publish-subscribe/pom.xml @@ -28,7 +28,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 eip-publish-subscribe diff --git a/eip-splitter/pom.xml b/eip-splitter/pom.xml index 6aef2dc09953..05a914cabffe 100644 --- a/eip-splitter/pom.xml +++ b/eip-splitter/pom.xml @@ -31,7 +31,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 diff --git a/eip-wire-tap/pom.xml b/eip-wire-tap/pom.xml index ae896f0d0399..18360c266c8e 100644 --- a/eip-wire-tap/pom.xml +++ b/eip-wire-tap/pom.xml @@ -31,7 +31,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 diff --git a/event-aggregator/pom.xml b/event-aggregator/pom.xml index 191eaed043e0..ddf7f11ddb08 100644 --- a/event-aggregator/pom.xml +++ b/event-aggregator/pom.xml @@ -28,7 +28,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 event-aggregator diff --git a/event-asynchronous/pom.xml b/event-asynchronous/pom.xml index 227c70a2afe3..778a8f37d0c2 100644 --- a/event-asynchronous/pom.xml +++ b/event-asynchronous/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 event-asynchronous diff --git a/event-driven-architecture/pom.xml b/event-driven-architecture/pom.xml index 13217786ac36..4304b030557e 100644 --- a/event-driven-architecture/pom.xml +++ b/event-driven-architecture/pom.xml @@ -31,7 +31,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 event-driven-architecture diff --git a/event-queue/pom.xml b/event-queue/pom.xml index 74f467a4847a..674be4d2a480 100644 --- a/event-queue/pom.xml +++ b/event-queue/pom.xml @@ -30,7 +30,7 @@ java-design-patterns com.iluwatar - 1.22.0-SNAPSHOT + 1.22.0 event-queue diff --git a/event-sourcing/pom.xml b/event-sourcing/pom.xml index 0b9c93770639..95950fb33774 100644 --- a/event-sourcing/pom.xml +++ b/event-sourcing/pom.xml @@ -30,7 +30,7 @@ java-design-patterns com.iluwatar - 1.22.0-SNAPSHOT + 1.22.0 event-sourcing diff --git a/execute-around/pom.xml b/execute-around/pom.xml index 1fc4125f3220..e3e2ee19d5bd 100644 --- a/execute-around/pom.xml +++ b/execute-around/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 execute-around diff --git a/extension-objects/pom.xml b/extension-objects/pom.xml index 7eb914e3ec9c..2a878dafade9 100644 --- a/extension-objects/pom.xml +++ b/extension-objects/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.22.0-SNAPSHOT + 1.22.0 4.0.0 diff --git a/facade/pom.xml b/facade/pom.xml index 9c68490a63f5..45e59b244242 100644 --- a/facade/pom.xml +++ b/facade/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 facade diff --git a/factory-kit/pom.xml b/factory-kit/pom.xml index 03e5e822347a..2999da14a30d 100644 --- a/factory-kit/pom.xml +++ b/factory-kit/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 factory-kit diff --git a/factory-method/pom.xml b/factory-method/pom.xml index f4ca2cd5048b..9f983e570e50 100644 --- a/factory-method/pom.xml +++ b/factory-method/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 factory-method diff --git a/feature-toggle/pom.xml b/feature-toggle/pom.xml index 7215eaf0083e..4d35a41a4340 100644 --- a/feature-toggle/pom.xml +++ b/feature-toggle/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.22.0-SNAPSHOT + 1.22.0 4.0.0 diff --git a/fluentinterface/pom.xml b/fluentinterface/pom.xml index 1e76ea628f9d..3c7d346672b7 100644 --- a/fluentinterface/pom.xml +++ b/fluentinterface/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.22.0-SNAPSHOT + 1.22.0 4.0.0 diff --git a/flux/pom.xml b/flux/pom.xml index 324e4499544b..4b07c57b65a8 100644 --- a/flux/pom.xml +++ b/flux/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 flux diff --git a/flyweight/pom.xml b/flyweight/pom.xml index 04b153be8ffb..047246558336 100644 --- a/flyweight/pom.xml +++ b/flyweight/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 flyweight diff --git a/front-controller/pom.xml b/front-controller/pom.xml index 1f6e1a7f661a..2bd5acd488e0 100644 --- a/front-controller/pom.xml +++ b/front-controller/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 front-controller diff --git a/game-loop/pom.xml b/game-loop/pom.xml index c28ac04cd88e..8584ec417326 100644 --- a/game-loop/pom.xml +++ b/game-loop/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.22.0-SNAPSHOT + 1.22.0 4.0.0 diff --git a/guarded-suspension/pom.xml b/guarded-suspension/pom.xml index b594a2b71108..adc59f37cb13 100644 --- a/guarded-suspension/pom.xml +++ b/guarded-suspension/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 jar guarded-suspension diff --git a/half-sync-half-async/pom.xml b/half-sync-half-async/pom.xml index 462d4ab0d3c8..3073af6cab9b 100644 --- a/half-sync-half-async/pom.xml +++ b/half-sync-half-async/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 half-sync-half-async diff --git a/hexagonal/pom.xml b/hexagonal/pom.xml index 060d0135b428..42c2dd8f88b2 100644 --- a/hexagonal/pom.xml +++ b/hexagonal/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 hexagonal diff --git a/intercepting-filter/pom.xml b/intercepting-filter/pom.xml index bff125ee68cc..3c2e5de02a39 100644 --- a/intercepting-filter/pom.xml +++ b/intercepting-filter/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 intercepting-filter diff --git a/interpreter/pom.xml b/interpreter/pom.xml index 311df2fe356f..ac5924284ca5 100644 --- a/interpreter/pom.xml +++ b/interpreter/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 interpreter diff --git a/iterator/pom.xml b/iterator/pom.xml index 7f8b120ec3e4..3eaa24775021 100644 --- a/iterator/pom.xml +++ b/iterator/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 iterator diff --git a/layers/pom.xml b/layers/pom.xml index 1e018c3a2ea3..e87ec1c0a2c5 100644 --- a/layers/pom.xml +++ b/layers/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 com.iluwatar.layers layers diff --git a/lazy-loading/pom.xml b/lazy-loading/pom.xml index d52c14a42f45..be204707ef12 100644 --- a/lazy-loading/pom.xml +++ b/lazy-loading/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 lazy-loading diff --git a/leader-election/pom.xml b/leader-election/pom.xml index 725942e2adb2..7eb3b6751461 100644 --- a/leader-election/pom.xml +++ b/leader-election/pom.xml @@ -30,7 +30,7 @@ java-design-patterns com.iluwatar - 1.22.0-SNAPSHOT + 1.22.0 leader-election diff --git a/marker/pom.xml b/marker/pom.xml index d8166ab86c32..e383b2ab2a5c 100644 --- a/marker/pom.xml +++ b/marker/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.22.0-SNAPSHOT + 1.22.0 4.0.0 diff --git a/master-worker-pattern/pom.xml b/master-worker-pattern/pom.xml index 8ce79ed7f7c5..7f7b2ee81520 100644 --- a/master-worker-pattern/pom.xml +++ b/master-worker-pattern/pom.xml @@ -27,7 +27,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 master-worker-pattern diff --git a/mediator/pom.xml b/mediator/pom.xml index 7fba84dd11ab..ed8edffcba96 100644 --- a/mediator/pom.xml +++ b/mediator/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 mediator diff --git a/memento/pom.xml b/memento/pom.xml index 260cb4c58016..91d84ae7025b 100644 --- a/memento/pom.xml +++ b/memento/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 memento diff --git a/model-view-controller/pom.xml b/model-view-controller/pom.xml index 035a6a27bb95..b90477b6aae3 100644 --- a/model-view-controller/pom.xml +++ b/model-view-controller/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 model-view-controller diff --git a/model-view-presenter/pom.xml b/model-view-presenter/pom.xml index 14de90aed9e8..3e907fd07524 100644 --- a/model-view-presenter/pom.xml +++ b/model-view-presenter/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 model-view-presenter model-view-presenter diff --git a/module/pom.xml b/module/pom.xml index 0a60960b53c6..7a2e9388cefe 100644 --- a/module/pom.xml +++ b/module/pom.xml @@ -28,7 +28,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 module diff --git a/monad/pom.xml b/monad/pom.xml index 67768a5d52b3..92b52af47795 100644 --- a/monad/pom.xml +++ b/monad/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 monad diff --git a/monostate/pom.xml b/monostate/pom.xml index b39ef2d95b06..dbe745634cbd 100644 --- a/monostate/pom.xml +++ b/monostate/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 monostate diff --git a/multiton/pom.xml b/multiton/pom.xml index cd827aa6de27..887b53aedefc 100644 --- a/multiton/pom.xml +++ b/multiton/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 multiton diff --git a/mute-idiom/pom.xml b/mute-idiom/pom.xml index aeb18dc5ce6e..0ed5fb3f122b 100644 --- a/mute-idiom/pom.xml +++ b/mute-idiom/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 mute-idiom diff --git a/mutex/pom.xml b/mutex/pom.xml index 05f9295eead8..269f3dd7d897 100644 --- a/mutex/pom.xml +++ b/mutex/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 mutex diff --git a/naked-objects/dom/pom.xml b/naked-objects/dom/pom.xml index 2709edda03f4..7536add36764 100644 --- a/naked-objects/dom/pom.xml +++ b/naked-objects/dom/pom.xml @@ -30,7 +30,7 @@ com.iluwatar naked-objects - 1.22.0-SNAPSHOT + 1.22.0 naked-objects-dom diff --git a/naked-objects/fixture/pom.xml b/naked-objects/fixture/pom.xml index 9de092976117..8cb5395d8048 100644 --- a/naked-objects/fixture/pom.xml +++ b/naked-objects/fixture/pom.xml @@ -30,7 +30,7 @@ com.iluwatar naked-objects - 1.22.0-SNAPSHOT + 1.22.0 naked-objects-fixture diff --git a/naked-objects/integtests/pom.xml b/naked-objects/integtests/pom.xml index 62d25df032c9..c3f332de377d 100644 --- a/naked-objects/integtests/pom.xml +++ b/naked-objects/integtests/pom.xml @@ -30,7 +30,7 @@ com.iluwatar naked-objects - 1.22.0-SNAPSHOT + 1.22.0 naked-objects-integtests diff --git a/naked-objects/pom.xml b/naked-objects/pom.xml index b035c3894058..acd9f7156985 100644 --- a/naked-objects/pom.xml +++ b/naked-objects/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.22.0-SNAPSHOT + 1.22.0 naked-objects pom @@ -333,17 +333,17 @@ ${project.groupId} naked-objects-dom - 1.22.0-SNAPSHOT + 1.22.0 ${project.groupId} naked-objects-fixture - 1.22.0-SNAPSHOT + 1.22.0 ${project.groupId} naked-objects-webapp - 1.22.0-SNAPSHOT + 1.22.0 diff --git a/naked-objects/webapp/pom.xml b/naked-objects/webapp/pom.xml index e0697b855b31..89d35eba07a4 100644 --- a/naked-objects/webapp/pom.xml +++ b/naked-objects/webapp/pom.xml @@ -30,7 +30,7 @@ com.iluwatar naked-objects - 1.22.0-SNAPSHOT + 1.22.0 naked-objects-webapp diff --git a/null-object/pom.xml b/null-object/pom.xml index 7111c8ff9822..73dfd57477b2 100644 --- a/null-object/pom.xml +++ b/null-object/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 null-object diff --git a/object-mother/pom.xml b/object-mother/pom.xml index e59607414c6e..24ae4e652413 100644 --- a/object-mother/pom.xml +++ b/object-mother/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 object-mother diff --git a/object-pool/pom.xml b/object-pool/pom.xml index efbb7ee4047c..57545bff040a 100644 --- a/object-pool/pom.xml +++ b/object-pool/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 object-pool diff --git a/observer/pom.xml b/observer/pom.xml index 9a538aa294d9..3a2a886e12c2 100644 --- a/observer/pom.xml +++ b/observer/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 observer diff --git a/page-object/pom.xml b/page-object/pom.xml index 7a3db030ee16..85c4e8108a92 100644 --- a/page-object/pom.xml +++ b/page-object/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 page-object pom diff --git a/page-object/sample-application/pom.xml b/page-object/sample-application/pom.xml index c21e52e9901c..b2ff13239b94 100644 --- a/page-object/sample-application/pom.xml +++ b/page-object/sample-application/pom.xml @@ -29,7 +29,7 @@ page-object com.iluwatar - 1.22.0-SNAPSHOT + 1.22.0 sample-application diff --git a/page-object/test-automation/pom.xml b/page-object/test-automation/pom.xml index 5b275084c4cf..0cb69217f554 100644 --- a/page-object/test-automation/pom.xml +++ b/page-object/test-automation/pom.xml @@ -29,7 +29,7 @@ page-object com.iluwatar - 1.22.0-SNAPSHOT + 1.22.0 test-automation diff --git a/partial-response/pom.xml b/partial-response/pom.xml index bef921f0583a..d76beb51489a 100644 --- a/partial-response/pom.xml +++ b/partial-response/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.22.0-SNAPSHOT + 1.22.0 4.0.0 diff --git a/pipeline/pom.xml b/pipeline/pom.xml index f67e6ad2df16..37051b715c9a 100644 --- a/pipeline/pom.xml +++ b/pipeline/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 pipeline diff --git a/poison-pill/pom.xml b/poison-pill/pom.xml index b10b54c008ff..528090777f96 100644 --- a/poison-pill/pom.xml +++ b/poison-pill/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 poison-pill diff --git a/pom.xml b/pom.xml index 201854085405..dba196399071 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ 4.0.0 com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 pom 2014-2019 diff --git a/priority-queue/pom.xml b/priority-queue/pom.xml index 3e5ac50e81ab..37bd3896e99f 100644 --- a/priority-queue/pom.xml +++ b/priority-queue/pom.xml @@ -31,7 +31,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 diff --git a/private-class-data/pom.xml b/private-class-data/pom.xml index da9b510542c6..a613d52776b2 100644 --- a/private-class-data/pom.xml +++ b/private-class-data/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 private-class-data diff --git a/producer-consumer/pom.xml b/producer-consumer/pom.xml index 1cbf039103ca..bd0fd0bc1cf2 100644 --- a/producer-consumer/pom.xml +++ b/producer-consumer/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 producer-consumer diff --git a/promise/pom.xml b/promise/pom.xml index 6ee49075766b..a9e4f57a9f44 100644 --- a/promise/pom.xml +++ b/promise/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 promise diff --git a/property/pom.xml b/property/pom.xml index b04242256f0f..0ebddd453bd0 100644 --- a/property/pom.xml +++ b/property/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 property diff --git a/prototype/pom.xml b/prototype/pom.xml index a715deb79dce..1babcc542b6e 100644 --- a/prototype/pom.xml +++ b/prototype/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 prototype diff --git a/proxy/pom.xml b/proxy/pom.xml index e1df3657a6fa..d379cc3da4a2 100644 --- a/proxy/pom.xml +++ b/proxy/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 proxy diff --git a/queue-load-leveling/pom.xml b/queue-load-leveling/pom.xml index be8404c2da25..cbd13c030cc4 100644 --- a/queue-load-leveling/pom.xml +++ b/queue-load-leveling/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 queue-load-leveling diff --git a/reactor/pom.xml b/reactor/pom.xml index 104b52521975..fcb7ef9a6c73 100644 --- a/reactor/pom.xml +++ b/reactor/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 reactor diff --git a/reader-writer-lock/pom.xml b/reader-writer-lock/pom.xml index 9cde49e389c5..3bd4f6007ff8 100644 --- a/reader-writer-lock/pom.xml +++ b/reader-writer-lock/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 reader-writer-lock diff --git a/repository/pom.xml b/repository/pom.xml index 906389282945..da6be0c49945 100644 --- a/repository/pom.xml +++ b/repository/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 repository diff --git a/resource-acquisition-is-initialization/pom.xml b/resource-acquisition-is-initialization/pom.xml index d094eff8d052..f172dad687cc 100644 --- a/resource-acquisition-is-initialization/pom.xml +++ b/resource-acquisition-is-initialization/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 resource-acquisition-is-initialization diff --git a/retry/pom.xml b/retry/pom.xml index 73b25b64b9ee..d44666c62747 100644 --- a/retry/pom.xml +++ b/retry/pom.xml @@ -28,7 +28,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 retry jar diff --git a/role-object/pom.xml b/role-object/pom.xml index c9feb1419afd..c9760527fe44 100644 --- a/role-object/pom.xml +++ b/role-object/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 role-object diff --git a/saga/pom.xml b/saga/pom.xml index 111f4e7b8134..4f87c9873347 100644 --- a/saga/pom.xml +++ b/saga/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 saga diff --git a/semaphore/pom.xml b/semaphore/pom.xml index 1ae865f02442..a61f20f0c90e 100644 --- a/semaphore/pom.xml +++ b/semaphore/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 semaphore diff --git a/servant/pom.xml b/servant/pom.xml index e8c791d613be..eebd1355c31a 100644 --- a/servant/pom.xml +++ b/servant/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 servant diff --git a/serverless/pom.xml b/serverless/pom.xml index 292df78c55f1..bb9391d9428f 100644 --- a/serverless/pom.xml +++ b/serverless/pom.xml @@ -31,7 +31,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 diff --git a/service-layer/pom.xml b/service-layer/pom.xml index 31fc6f625b68..4f4403151099 100644 --- a/service-layer/pom.xml +++ b/service-layer/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 service-layer diff --git a/service-locator/pom.xml b/service-locator/pom.xml index 5232bbd28818..f9c0ea023202 100644 --- a/service-locator/pom.xml +++ b/service-locator/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 service-locator diff --git a/sharding/pom.xml b/sharding/pom.xml index f0dd01a7c8a2..3033c355a2b3 100644 --- a/sharding/pom.xml +++ b/sharding/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.22.0-SNAPSHOT + 1.22.0 4.0.0 diff --git a/singleton/pom.xml b/singleton/pom.xml index c07183c7fae7..951999192d4d 100644 --- a/singleton/pom.xml +++ b/singleton/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 singleton diff --git a/spatial-partition/pom.xml b/spatial-partition/pom.xml index b7d6d4b633b3..d54cae176fde 100644 --- a/spatial-partition/pom.xml +++ b/spatial-partition/pom.xml @@ -46,7 +46,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 spatial-partition diff --git a/specification/pom.xml b/specification/pom.xml index 9f64b41d71b7..7fc6a470c7e4 100644 --- a/specification/pom.xml +++ b/specification/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 specification diff --git a/state/pom.xml b/state/pom.xml index ac31bc5ebfa7..02eaf7e86c97 100644 --- a/state/pom.xml +++ b/state/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 state diff --git a/step-builder/pom.xml b/step-builder/pom.xml index 23d73ed1b4a3..6c9cdf3bce78 100644 --- a/step-builder/pom.xml +++ b/step-builder/pom.xml @@ -30,7 +30,7 @@ java-design-patterns com.iluwatar - 1.22.0-SNAPSHOT + 1.22.0 step-builder diff --git a/strategy/pom.xml b/strategy/pom.xml index d251b9a96610..9eefa5539a04 100644 --- a/strategy/pom.xml +++ b/strategy/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 strategy diff --git a/subclass-sandbox/pom.xml b/subclass-sandbox/pom.xml index eb493b28cc3b..298274bb9dbf 100644 --- a/subclass-sandbox/pom.xml +++ b/subclass-sandbox/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.22.0-SNAPSHOT + 1.22.0 4.0.0 diff --git a/template-method/pom.xml b/template-method/pom.xml index 0f4a03a5fec2..d3cb03cf63f3 100644 --- a/template-method/pom.xml +++ b/template-method/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 template-method diff --git a/thread-pool/pom.xml b/thread-pool/pom.xml index 8968b3f4e70e..8e3ccbfd0fb0 100644 --- a/thread-pool/pom.xml +++ b/thread-pool/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 thread-pool diff --git a/throttling/pom.xml b/throttling/pom.xml index 55e1b3e57ee8..ab6572764878 100644 --- a/throttling/pom.xml +++ b/throttling/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.22.0-SNAPSHOT + 1.22.0 4.0.0 diff --git a/tls/pom.xml b/tls/pom.xml index 050604d7bc50..ac0f1e1a3fab 100644 --- a/tls/pom.xml +++ b/tls/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 tls diff --git a/tolerant-reader/pom.xml b/tolerant-reader/pom.xml index e0d935112aaa..ac7a801c5dde 100644 --- a/tolerant-reader/pom.xml +++ b/tolerant-reader/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 tolerant-reader diff --git a/trampoline/pom.xml b/trampoline/pom.xml index 99ef231ef534..dc700f664324 100644 --- a/trampoline/pom.xml +++ b/trampoline/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 trampoline diff --git a/twin/pom.xml b/twin/pom.xml index 9e62469b15cb..b71d4e223f86 100644 --- a/twin/pom.xml +++ b/twin/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 twin diff --git a/typeobjectpattern/pom.xml b/typeobjectpattern/pom.xml index 03d21de3770d..fbf05e9bc6cb 100644 --- a/typeobjectpattern/pom.xml +++ b/typeobjectpattern/pom.xml @@ -27,7 +27,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 typeobjectpattern diff --git a/unit-of-work/pom.xml b/unit-of-work/pom.xml index c27a674660aa..c1e4b6776f1f 100644 --- a/unit-of-work/pom.xml +++ b/unit-of-work/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.22.0-SNAPSHOT + 1.22.0 4.0.0 diff --git a/value-object/pom.xml b/value-object/pom.xml index 8aec02a8dfbe..4d076c5e49ef 100644 --- a/value-object/pom.xml +++ b/value-object/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 value-object diff --git a/visitor/pom.xml b/visitor/pom.xml index c2a673ec6e4e..dc18dd5202f5 100644 --- a/visitor/pom.xml +++ b/visitor/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0-SNAPSHOT + 1.22.0 visitor From 6941e65cb467cfcf8f17b54b9ee51e7f3d0b0563 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilkka=20Sepp=C3=A4l=C3=A4?= Date: Sun, 17 Nov 2019 14:45:41 +0200 Subject: [PATCH 30/31] Set version for next development iteration --- abstract-document/pom.xml | 2 +- abstract-factory/pom.xml | 2 +- acyclic-visitor/pom.xml | 2 +- adapter/pom.xml | 2 +- aggregator-microservices/aggregator-service/pom.xml | 2 +- aggregator-microservices/information-microservice/pom.xml | 2 +- aggregator-microservices/inventory-microservice/pom.xml | 2 +- aggregator-microservices/pom.xml | 2 +- ambassador/pom.xml | 2 +- api-gateway/api-gateway-service/pom.xml | 2 +- api-gateway/image-microservice/pom.xml | 2 +- api-gateway/pom.xml | 2 +- api-gateway/price-microservice/pom.xml | 2 +- async-method-invocation/pom.xml | 2 +- balking/pom.xml | 2 +- bridge/pom.xml | 2 +- builder/pom.xml | 2 +- business-delegate/pom.xml | 2 +- bytecode/pom.xml | 2 +- caching/pom.xml | 2 +- callback/pom.xml | 2 +- chain/pom.xml | 2 +- circuit-breaker/pom.xml | 2 +- collection-pipeline/pom.xml | 2 +- command/pom.xml | 2 +- commander/pom.xml | 2 +- composite/pom.xml | 2 +- converter/pom.xml | 2 +- cqrs/pom.xml | 2 +- dao/pom.xml | 2 +- data-bus/pom.xml | 2 +- data-locality/pom.xml | 2 +- data-mapper/pom.xml | 2 +- data-transfer-object/pom.xml | 2 +- decorator/pom.xml | 2 +- delegation/pom.xml | 2 +- dependency-injection/pom.xml | 2 +- dirty-flag/pom.xml | 4 ++-- double-buffer/pom.xml | 2 +- double-checked-locking/pom.xml | 2 +- double-dispatch/pom.xml | 2 +- eip-aggregator/pom.xml | 2 +- eip-message-channel/pom.xml | 2 +- eip-publish-subscribe/pom.xml | 2 +- eip-splitter/pom.xml | 2 +- eip-wire-tap/pom.xml | 2 +- event-aggregator/pom.xml | 2 +- event-asynchronous/pom.xml | 2 +- event-driven-architecture/pom.xml | 2 +- event-queue/pom.xml | 2 +- event-sourcing/pom.xml | 2 +- execute-around/pom.xml | 2 +- extension-objects/pom.xml | 2 +- facade/pom.xml | 2 +- factory-kit/pom.xml | 2 +- factory-method/pom.xml | 2 +- feature-toggle/pom.xml | 2 +- fluentinterface/pom.xml | 2 +- flux/pom.xml | 2 +- flyweight/pom.xml | 2 +- front-controller/pom.xml | 2 +- game-loop/pom.xml | 2 +- guarded-suspension/pom.xml | 2 +- half-sync-half-async/pom.xml | 2 +- hexagonal/pom.xml | 2 +- intercepting-filter/pom.xml | 2 +- interpreter/pom.xml | 2 +- iterator/pom.xml | 2 +- layers/pom.xml | 2 +- lazy-loading/pom.xml | 2 +- leader-election/pom.xml | 2 +- marker/pom.xml | 2 +- master-worker-pattern/pom.xml | 2 +- mediator/pom.xml | 2 +- memento/pom.xml | 2 +- model-view-controller/pom.xml | 2 +- model-view-presenter/pom.xml | 2 +- module/pom.xml | 2 +- monad/pom.xml | 2 +- monostate/pom.xml | 2 +- multiton/pom.xml | 2 +- mute-idiom/pom.xml | 2 +- mutex/pom.xml | 2 +- naked-objects/dom/pom.xml | 2 +- naked-objects/fixture/pom.xml | 2 +- naked-objects/integtests/pom.xml | 2 +- naked-objects/pom.xml | 8 ++++---- naked-objects/webapp/pom.xml | 2 +- null-object/pom.xml | 2 +- object-mother/pom.xml | 2 +- object-pool/pom.xml | 2 +- observer/pom.xml | 2 +- page-object/pom.xml | 2 +- page-object/sample-application/pom.xml | 2 +- page-object/test-automation/pom.xml | 2 +- partial-response/pom.xml | 2 +- pipeline/pom.xml | 2 +- poison-pill/pom.xml | 2 +- pom.xml | 2 +- priority-queue/pom.xml | 2 +- private-class-data/pom.xml | 2 +- producer-consumer/pom.xml | 2 +- promise/pom.xml | 2 +- property/pom.xml | 2 +- prototype/pom.xml | 2 +- proxy/pom.xml | 2 +- queue-load-leveling/pom.xml | 2 +- reactor/pom.xml | 2 +- reader-writer-lock/pom.xml | 2 +- repository/pom.xml | 2 +- resource-acquisition-is-initialization/pom.xml | 2 +- retry/pom.xml | 2 +- role-object/pom.xml | 2 +- saga/pom.xml | 2 +- semaphore/pom.xml | 2 +- servant/pom.xml | 2 +- serverless/pom.xml | 2 +- service-layer/pom.xml | 2 +- service-locator/pom.xml | 2 +- sharding/pom.xml | 2 +- singleton/pom.xml | 2 +- spatial-partition/pom.xml | 2 +- specification/pom.xml | 2 +- state/pom.xml | 2 +- step-builder/pom.xml | 2 +- strategy/pom.xml | 2 +- subclass-sandbox/pom.xml | 2 +- template-method/pom.xml | 2 +- thread-pool/pom.xml | 2 +- throttling/pom.xml | 2 +- tls/pom.xml | 2 +- tolerant-reader/pom.xml | 2 +- trampoline/pom.xml | 2 +- twin/pom.xml | 2 +- typeobjectpattern/pom.xml | 2 +- unit-of-work/pom.xml | 2 +- value-object/pom.xml | 2 +- visitor/pom.xml | 2 +- 138 files changed, 142 insertions(+), 142 deletions(-) diff --git a/abstract-document/pom.xml b/abstract-document/pom.xml index 620fd55bd736..020b04953b98 100644 --- a/abstract-document/pom.xml +++ b/abstract-document/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.22.0 + 1.23.0-SNAPSHOT abstract-document diff --git a/abstract-factory/pom.xml b/abstract-factory/pom.xml index 2b265140af04..5bbe3afa7951 100644 --- a/abstract-factory/pom.xml +++ b/abstract-factory/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT abstract-factory diff --git a/acyclic-visitor/pom.xml b/acyclic-visitor/pom.xml index b6e4a635fb05..55de9c7f9e4d 100644 --- a/acyclic-visitor/pom.xml +++ b/acyclic-visitor/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT acyclic-visitor diff --git a/adapter/pom.xml b/adapter/pom.xml index b815886beb87..02b979ec9a5f 100644 --- a/adapter/pom.xml +++ b/adapter/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT adapter diff --git a/aggregator-microservices/aggregator-service/pom.xml b/aggregator-microservices/aggregator-service/pom.xml index 9fbc362fddfe..5690c026a241 100644 --- a/aggregator-microservices/aggregator-service/pom.xml +++ b/aggregator-microservices/aggregator-service/pom.xml @@ -29,7 +29,7 @@ aggregator-microservices com.iluwatar - 1.22.0 + 1.23.0-SNAPSHOT 4.0.0 aggregator-service diff --git a/aggregator-microservices/information-microservice/pom.xml b/aggregator-microservices/information-microservice/pom.xml index faf327371b7e..f1d9d2dc0de8 100644 --- a/aggregator-microservices/information-microservice/pom.xml +++ b/aggregator-microservices/information-microservice/pom.xml @@ -29,7 +29,7 @@ aggregator-microservices com.iluwatar - 1.22.0 + 1.23.0-SNAPSHOT 4.0.0 diff --git a/aggregator-microservices/inventory-microservice/pom.xml b/aggregator-microservices/inventory-microservice/pom.xml index f1dd08f56c75..93ced9f686e1 100644 --- a/aggregator-microservices/inventory-microservice/pom.xml +++ b/aggregator-microservices/inventory-microservice/pom.xml @@ -29,7 +29,7 @@ aggregator-microservices com.iluwatar - 1.22.0 + 1.23.0-SNAPSHOT 4.0.0 inventory-microservice diff --git a/aggregator-microservices/pom.xml b/aggregator-microservices/pom.xml index 438ff3bed47a..a63ec2f126a9 100644 --- a/aggregator-microservices/pom.xml +++ b/aggregator-microservices/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.22.0 + 1.23.0-SNAPSHOT 4.0.0 aggregator-microservices diff --git a/ambassador/pom.xml b/ambassador/pom.xml index 2c32fe537a87..350cace6adeb 100644 --- a/ambassador/pom.xml +++ b/ambassador/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.22.0 + 1.23.0-SNAPSHOT 4.0.0 ambassador diff --git a/api-gateway/api-gateway-service/pom.xml b/api-gateway/api-gateway-service/pom.xml index 17869b9961bb..1be25c304665 100644 --- a/api-gateway/api-gateway-service/pom.xml +++ b/api-gateway/api-gateway-service/pom.xml @@ -29,7 +29,7 @@ api-gateway com.iluwatar - 1.22.0 + 1.23.0-SNAPSHOT 4.0.0 api-gateway-service diff --git a/api-gateway/image-microservice/pom.xml b/api-gateway/image-microservice/pom.xml index 333abaf508f7..bcbaeb539717 100644 --- a/api-gateway/image-microservice/pom.xml +++ b/api-gateway/image-microservice/pom.xml @@ -29,7 +29,7 @@ api-gateway com.iluwatar - 1.22.0 + 1.23.0-SNAPSHOT 4.0.0 image-microservice diff --git a/api-gateway/pom.xml b/api-gateway/pom.xml index 0b315a444733..63a98699677c 100644 --- a/api-gateway/pom.xml +++ b/api-gateway/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.22.0 + 1.23.0-SNAPSHOT 4.0.0 api-gateway diff --git a/api-gateway/price-microservice/pom.xml b/api-gateway/price-microservice/pom.xml index 913ca0c630fe..47f16b4dd31f 100644 --- a/api-gateway/price-microservice/pom.xml +++ b/api-gateway/price-microservice/pom.xml @@ -29,7 +29,7 @@ api-gateway com.iluwatar - 1.22.0 + 1.23.0-SNAPSHOT 4.0.0 diff --git a/async-method-invocation/pom.xml b/async-method-invocation/pom.xml index 4d461b5103f8..62ec375dfad7 100644 --- a/async-method-invocation/pom.xml +++ b/async-method-invocation/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT async-method-invocation diff --git a/balking/pom.xml b/balking/pom.xml index 5b71c8c85ea8..aca041684f50 100644 --- a/balking/pom.xml +++ b/balking/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.22.0 + 1.23.0-SNAPSHOT 4.0.0 diff --git a/bridge/pom.xml b/bridge/pom.xml index 6342ad4c2a18..b37cb8c9da27 100644 --- a/bridge/pom.xml +++ b/bridge/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT bridge diff --git a/builder/pom.xml b/builder/pom.xml index fc3a439acf16..e31ef2798bcf 100644 --- a/builder/pom.xml +++ b/builder/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT builder diff --git a/business-delegate/pom.xml b/business-delegate/pom.xml index 6052c650a892..4bf05843c00c 100644 --- a/business-delegate/pom.xml +++ b/business-delegate/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT business-delegate diff --git a/bytecode/pom.xml b/bytecode/pom.xml index bab4ed4f111a..6b2f0bf548ee 100644 --- a/bytecode/pom.xml +++ b/bytecode/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.22.0 + 1.23.0-SNAPSHOT 4.0.0 diff --git a/caching/pom.xml b/caching/pom.xml index 373caa0f4f24..e479bc143b52 100644 --- a/caching/pom.xml +++ b/caching/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT caching diff --git a/callback/pom.xml b/callback/pom.xml index 9adfbe0087da..634e4f7e90c9 100644 --- a/callback/pom.xml +++ b/callback/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT callback diff --git a/chain/pom.xml b/chain/pom.xml index c1362a45770e..f92637935560 100644 --- a/chain/pom.xml +++ b/chain/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT chain diff --git a/circuit-breaker/pom.xml b/circuit-breaker/pom.xml index b8092ad62d17..b04cd5c25ecc 100644 --- a/circuit-breaker/pom.xml +++ b/circuit-breaker/pom.xml @@ -27,7 +27,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT circuit-breaker diff --git a/collection-pipeline/pom.xml b/collection-pipeline/pom.xml index 397224d50e4e..3c2a925c4836 100644 --- a/collection-pipeline/pom.xml +++ b/collection-pipeline/pom.xml @@ -27,7 +27,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT collection-pipeline diff --git a/command/pom.xml b/command/pom.xml index 633f332587ac..d43e09822734 100644 --- a/command/pom.xml +++ b/command/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT command diff --git a/commander/pom.xml b/commander/pom.xml index 78ff81e38287..7c675a304d3a 100644 --- a/commander/pom.xml +++ b/commander/pom.xml @@ -27,7 +27,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT commander diff --git a/composite/pom.xml b/composite/pom.xml index 7cb008d10f16..e833646807da 100644 --- a/composite/pom.xml +++ b/composite/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT composite diff --git a/converter/pom.xml b/converter/pom.xml index 6b6969ebb8f3..9495e811ec9a 100644 --- a/converter/pom.xml +++ b/converter/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.22.0 + 1.23.0-SNAPSHOT 4.0.0 diff --git a/cqrs/pom.xml b/cqrs/pom.xml index 14969e89416a..0f1b4a7c31d9 100644 --- a/cqrs/pom.xml +++ b/cqrs/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT cqrs diff --git a/dao/pom.xml b/dao/pom.xml index 51688d3e7b43..c3bc3300c030 100644 --- a/dao/pom.xml +++ b/dao/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT dao diff --git a/data-bus/pom.xml b/data-bus/pom.xml index d0a655d67c42..9a13745fe159 100644 --- a/data-bus/pom.xml +++ b/data-bus/pom.xml @@ -33,7 +33,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT data-bus diff --git a/data-locality/pom.xml b/data-locality/pom.xml index f7874149a8ea..d64b0f9416ff 100644 --- a/data-locality/pom.xml +++ b/data-locality/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT data-locality diff --git a/data-mapper/pom.xml b/data-mapper/pom.xml index e547f6a0eb8d..b587960ef788 100644 --- a/data-mapper/pom.xml +++ b/data-mapper/pom.xml @@ -28,7 +28,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT data-mapper diff --git a/data-transfer-object/pom.xml b/data-transfer-object/pom.xml index fb0c55a59a48..d01ff4f72ec0 100644 --- a/data-transfer-object/pom.xml +++ b/data-transfer-object/pom.xml @@ -28,7 +28,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT data-transfer-object diff --git a/decorator/pom.xml b/decorator/pom.xml index a6f7dc58357d..3d005fa64a0a 100644 --- a/decorator/pom.xml +++ b/decorator/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT decorator diff --git a/delegation/pom.xml b/delegation/pom.xml index 46e19240133c..5179a86852cd 100644 --- a/delegation/pom.xml +++ b/delegation/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.22.0 + 1.23.0-SNAPSHOT 4.0.0 diff --git a/dependency-injection/pom.xml b/dependency-injection/pom.xml index 018393738194..5caf8fbbce4f 100644 --- a/dependency-injection/pom.xml +++ b/dependency-injection/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT dependency-injection diff --git a/dirty-flag/pom.xml b/dirty-flag/pom.xml index 20fa25d8b5b2..0362780cb1e2 100644 --- a/dirty-flag/pom.xml +++ b/dirty-flag/pom.xml @@ -29,11 +29,11 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT com.iluwatar dirty-flag - 1.22.0 + 1.23.0-SNAPSHOT dirty-flag http://maven.apache.org diff --git a/double-buffer/pom.xml b/double-buffer/pom.xml index 5af4ccd7fc95..f4ea7db792a3 100644 --- a/double-buffer/pom.xml +++ b/double-buffer/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.22.0 + 1.23.0-SNAPSHOT 4.0.0 diff --git a/double-checked-locking/pom.xml b/double-checked-locking/pom.xml index 2b3af0c373dd..27d7d24205d2 100644 --- a/double-checked-locking/pom.xml +++ b/double-checked-locking/pom.xml @@ -27,7 +27,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT double-checked-locking diff --git a/double-dispatch/pom.xml b/double-dispatch/pom.xml index 53ac5d95d26b..059a7515b3b5 100644 --- a/double-dispatch/pom.xml +++ b/double-dispatch/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT double-dispatch diff --git a/eip-aggregator/pom.xml b/eip-aggregator/pom.xml index 1633ce4649ea..e32969eaec76 100644 --- a/eip-aggregator/pom.xml +++ b/eip-aggregator/pom.xml @@ -31,7 +31,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT diff --git a/eip-message-channel/pom.xml b/eip-message-channel/pom.xml index 20f92388d6b6..800a62883c18 100644 --- a/eip-message-channel/pom.xml +++ b/eip-message-channel/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT eip-message-channel diff --git a/eip-publish-subscribe/pom.xml b/eip-publish-subscribe/pom.xml index 6c6bd2a0eeee..65384438ef44 100644 --- a/eip-publish-subscribe/pom.xml +++ b/eip-publish-subscribe/pom.xml @@ -28,7 +28,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT eip-publish-subscribe diff --git a/eip-splitter/pom.xml b/eip-splitter/pom.xml index 05a914cabffe..e73139b959fb 100644 --- a/eip-splitter/pom.xml +++ b/eip-splitter/pom.xml @@ -31,7 +31,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT diff --git a/eip-wire-tap/pom.xml b/eip-wire-tap/pom.xml index 18360c266c8e..6d29aac1afd7 100644 --- a/eip-wire-tap/pom.xml +++ b/eip-wire-tap/pom.xml @@ -31,7 +31,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT diff --git a/event-aggregator/pom.xml b/event-aggregator/pom.xml index ddf7f11ddb08..a9e8b4cd16ff 100644 --- a/event-aggregator/pom.xml +++ b/event-aggregator/pom.xml @@ -28,7 +28,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT event-aggregator diff --git a/event-asynchronous/pom.xml b/event-asynchronous/pom.xml index 778a8f37d0c2..c05f54afde3f 100644 --- a/event-asynchronous/pom.xml +++ b/event-asynchronous/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT event-asynchronous diff --git a/event-driven-architecture/pom.xml b/event-driven-architecture/pom.xml index 4304b030557e..62a00fb70a5d 100644 --- a/event-driven-architecture/pom.xml +++ b/event-driven-architecture/pom.xml @@ -31,7 +31,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT event-driven-architecture diff --git a/event-queue/pom.xml b/event-queue/pom.xml index 674be4d2a480..58f31e3a05cb 100644 --- a/event-queue/pom.xml +++ b/event-queue/pom.xml @@ -30,7 +30,7 @@ java-design-patterns com.iluwatar - 1.22.0 + 1.23.0-SNAPSHOT event-queue diff --git a/event-sourcing/pom.xml b/event-sourcing/pom.xml index 95950fb33774..1232bb4b43fe 100644 --- a/event-sourcing/pom.xml +++ b/event-sourcing/pom.xml @@ -30,7 +30,7 @@ java-design-patterns com.iluwatar - 1.22.0 + 1.23.0-SNAPSHOT event-sourcing diff --git a/execute-around/pom.xml b/execute-around/pom.xml index e3e2ee19d5bd..e4f1d3fd299f 100644 --- a/execute-around/pom.xml +++ b/execute-around/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT execute-around diff --git a/extension-objects/pom.xml b/extension-objects/pom.xml index 2a878dafade9..34630508f480 100644 --- a/extension-objects/pom.xml +++ b/extension-objects/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.22.0 + 1.23.0-SNAPSHOT 4.0.0 diff --git a/facade/pom.xml b/facade/pom.xml index 45e59b244242..560f7ae1018c 100644 --- a/facade/pom.xml +++ b/facade/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT facade diff --git a/factory-kit/pom.xml b/factory-kit/pom.xml index 2999da14a30d..194f94d5d926 100644 --- a/factory-kit/pom.xml +++ b/factory-kit/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT factory-kit diff --git a/factory-method/pom.xml b/factory-method/pom.xml index 9f983e570e50..5b3b6c9cc5b1 100644 --- a/factory-method/pom.xml +++ b/factory-method/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT factory-method diff --git a/feature-toggle/pom.xml b/feature-toggle/pom.xml index 4d35a41a4340..4ecd5f59df29 100644 --- a/feature-toggle/pom.xml +++ b/feature-toggle/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.22.0 + 1.23.0-SNAPSHOT 4.0.0 diff --git a/fluentinterface/pom.xml b/fluentinterface/pom.xml index 3c7d346672b7..a40541fc4e2b 100644 --- a/fluentinterface/pom.xml +++ b/fluentinterface/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.22.0 + 1.23.0-SNAPSHOT 4.0.0 diff --git a/flux/pom.xml b/flux/pom.xml index 4b07c57b65a8..1c44d80574ec 100644 --- a/flux/pom.xml +++ b/flux/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT flux diff --git a/flyweight/pom.xml b/flyweight/pom.xml index 047246558336..a17b43dcd572 100644 --- a/flyweight/pom.xml +++ b/flyweight/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT flyweight diff --git a/front-controller/pom.xml b/front-controller/pom.xml index 2bd5acd488e0..de0f084a9aa2 100644 --- a/front-controller/pom.xml +++ b/front-controller/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT front-controller diff --git a/game-loop/pom.xml b/game-loop/pom.xml index 8584ec417326..da5c2bb09bc0 100644 --- a/game-loop/pom.xml +++ b/game-loop/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.22.0 + 1.23.0-SNAPSHOT 4.0.0 diff --git a/guarded-suspension/pom.xml b/guarded-suspension/pom.xml index adc59f37cb13..bc1dec09eedc 100644 --- a/guarded-suspension/pom.xml +++ b/guarded-suspension/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT jar guarded-suspension diff --git a/half-sync-half-async/pom.xml b/half-sync-half-async/pom.xml index 3073af6cab9b..3e86d3a173b2 100644 --- a/half-sync-half-async/pom.xml +++ b/half-sync-half-async/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT half-sync-half-async diff --git a/hexagonal/pom.xml b/hexagonal/pom.xml index 42c2dd8f88b2..324b9c8b8bf6 100644 --- a/hexagonal/pom.xml +++ b/hexagonal/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT hexagonal diff --git a/intercepting-filter/pom.xml b/intercepting-filter/pom.xml index 3c2e5de02a39..acc9f2268cfb 100644 --- a/intercepting-filter/pom.xml +++ b/intercepting-filter/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT intercepting-filter diff --git a/interpreter/pom.xml b/interpreter/pom.xml index ac5924284ca5..1789069f757a 100644 --- a/interpreter/pom.xml +++ b/interpreter/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT interpreter diff --git a/iterator/pom.xml b/iterator/pom.xml index 3eaa24775021..a1f1b29100ec 100644 --- a/iterator/pom.xml +++ b/iterator/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT iterator diff --git a/layers/pom.xml b/layers/pom.xml index e87ec1c0a2c5..0627fdf9b103 100644 --- a/layers/pom.xml +++ b/layers/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT com.iluwatar.layers layers diff --git a/lazy-loading/pom.xml b/lazy-loading/pom.xml index be204707ef12..c0245aac018a 100644 --- a/lazy-loading/pom.xml +++ b/lazy-loading/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT lazy-loading diff --git a/leader-election/pom.xml b/leader-election/pom.xml index 7eb3b6751461..9e94ce32f241 100644 --- a/leader-election/pom.xml +++ b/leader-election/pom.xml @@ -30,7 +30,7 @@ java-design-patterns com.iluwatar - 1.22.0 + 1.23.0-SNAPSHOT leader-election diff --git a/marker/pom.xml b/marker/pom.xml index e383b2ab2a5c..fa794b5959da 100644 --- a/marker/pom.xml +++ b/marker/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.22.0 + 1.23.0-SNAPSHOT 4.0.0 diff --git a/master-worker-pattern/pom.xml b/master-worker-pattern/pom.xml index 7f7b2ee81520..7ace130d8a9e 100644 --- a/master-worker-pattern/pom.xml +++ b/master-worker-pattern/pom.xml @@ -27,7 +27,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT master-worker-pattern diff --git a/mediator/pom.xml b/mediator/pom.xml index ed8edffcba96..2c0bfd4135b6 100644 --- a/mediator/pom.xml +++ b/mediator/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT mediator diff --git a/memento/pom.xml b/memento/pom.xml index 91d84ae7025b..07e4f0b839e5 100644 --- a/memento/pom.xml +++ b/memento/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT memento diff --git a/model-view-controller/pom.xml b/model-view-controller/pom.xml index b90477b6aae3..4759bf2d3158 100644 --- a/model-view-controller/pom.xml +++ b/model-view-controller/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT model-view-controller diff --git a/model-view-presenter/pom.xml b/model-view-presenter/pom.xml index 3e907fd07524..21ba3f14c56d 100644 --- a/model-view-presenter/pom.xml +++ b/model-view-presenter/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT model-view-presenter model-view-presenter diff --git a/module/pom.xml b/module/pom.xml index 7a2e9388cefe..d30353070a15 100644 --- a/module/pom.xml +++ b/module/pom.xml @@ -28,7 +28,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT module diff --git a/monad/pom.xml b/monad/pom.xml index 92b52af47795..868cc871059b 100644 --- a/monad/pom.xml +++ b/monad/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT monad diff --git a/monostate/pom.xml b/monostate/pom.xml index dbe745634cbd..0e51fc70084a 100644 --- a/monostate/pom.xml +++ b/monostate/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT monostate diff --git a/multiton/pom.xml b/multiton/pom.xml index 887b53aedefc..39deb9e4dcbe 100644 --- a/multiton/pom.xml +++ b/multiton/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT multiton diff --git a/mute-idiom/pom.xml b/mute-idiom/pom.xml index 0ed5fb3f122b..91f5063a7a0e 100644 --- a/mute-idiom/pom.xml +++ b/mute-idiom/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT mute-idiom diff --git a/mutex/pom.xml b/mutex/pom.xml index 269f3dd7d897..c1cad3d8aae4 100644 --- a/mutex/pom.xml +++ b/mutex/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT mutex diff --git a/naked-objects/dom/pom.xml b/naked-objects/dom/pom.xml index 7536add36764..dffc1650caad 100644 --- a/naked-objects/dom/pom.xml +++ b/naked-objects/dom/pom.xml @@ -30,7 +30,7 @@ com.iluwatar naked-objects - 1.22.0 + 1.23.0-SNAPSHOT naked-objects-dom diff --git a/naked-objects/fixture/pom.xml b/naked-objects/fixture/pom.xml index 8cb5395d8048..3457ac0a42ab 100644 --- a/naked-objects/fixture/pom.xml +++ b/naked-objects/fixture/pom.xml @@ -30,7 +30,7 @@ com.iluwatar naked-objects - 1.22.0 + 1.23.0-SNAPSHOT naked-objects-fixture diff --git a/naked-objects/integtests/pom.xml b/naked-objects/integtests/pom.xml index c3f332de377d..f46541f48fb4 100644 --- a/naked-objects/integtests/pom.xml +++ b/naked-objects/integtests/pom.xml @@ -30,7 +30,7 @@ com.iluwatar naked-objects - 1.22.0 + 1.23.0-SNAPSHOT naked-objects-integtests diff --git a/naked-objects/pom.xml b/naked-objects/pom.xml index acd9f7156985..0ca5a3ef3cb4 100644 --- a/naked-objects/pom.xml +++ b/naked-objects/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.22.0 + 1.23.0-SNAPSHOT naked-objects pom @@ -333,17 +333,17 @@ ${project.groupId} naked-objects-dom - 1.22.0 + 1.23.0-SNAPSHOT ${project.groupId} naked-objects-fixture - 1.22.0 + 1.23.0-SNAPSHOT ${project.groupId} naked-objects-webapp - 1.22.0 + 1.23.0-SNAPSHOT diff --git a/naked-objects/webapp/pom.xml b/naked-objects/webapp/pom.xml index 89d35eba07a4..bdf638cbaa3a 100644 --- a/naked-objects/webapp/pom.xml +++ b/naked-objects/webapp/pom.xml @@ -30,7 +30,7 @@ com.iluwatar naked-objects - 1.22.0 + 1.23.0-SNAPSHOT naked-objects-webapp diff --git a/null-object/pom.xml b/null-object/pom.xml index 73dfd57477b2..d80b97d95734 100644 --- a/null-object/pom.xml +++ b/null-object/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT null-object diff --git a/object-mother/pom.xml b/object-mother/pom.xml index 24ae4e652413..5ac3ce410b6c 100644 --- a/object-mother/pom.xml +++ b/object-mother/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT object-mother diff --git a/object-pool/pom.xml b/object-pool/pom.xml index 57545bff040a..fdd247476d12 100644 --- a/object-pool/pom.xml +++ b/object-pool/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT object-pool diff --git a/observer/pom.xml b/observer/pom.xml index 3a2a886e12c2..fc8a53eae564 100644 --- a/observer/pom.xml +++ b/observer/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT observer diff --git a/page-object/pom.xml b/page-object/pom.xml index 85c4e8108a92..99c67dbc5f38 100644 --- a/page-object/pom.xml +++ b/page-object/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT page-object pom diff --git a/page-object/sample-application/pom.xml b/page-object/sample-application/pom.xml index b2ff13239b94..5ded184cc74f 100644 --- a/page-object/sample-application/pom.xml +++ b/page-object/sample-application/pom.xml @@ -29,7 +29,7 @@ page-object com.iluwatar - 1.22.0 + 1.23.0-SNAPSHOT sample-application diff --git a/page-object/test-automation/pom.xml b/page-object/test-automation/pom.xml index 0cb69217f554..68025f4b82dd 100644 --- a/page-object/test-automation/pom.xml +++ b/page-object/test-automation/pom.xml @@ -29,7 +29,7 @@ page-object com.iluwatar - 1.22.0 + 1.23.0-SNAPSHOT test-automation diff --git a/partial-response/pom.xml b/partial-response/pom.xml index d76beb51489a..6bca7007329d 100644 --- a/partial-response/pom.xml +++ b/partial-response/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.22.0 + 1.23.0-SNAPSHOT 4.0.0 diff --git a/pipeline/pom.xml b/pipeline/pom.xml index 37051b715c9a..e7d879d4a5ce 100644 --- a/pipeline/pom.xml +++ b/pipeline/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT pipeline diff --git a/poison-pill/pom.xml b/poison-pill/pom.xml index 528090777f96..b751fad04837 100644 --- a/poison-pill/pom.xml +++ b/poison-pill/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT poison-pill diff --git a/pom.xml b/pom.xml index dba196399071..39582fd93718 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ 4.0.0 com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT pom 2014-2019 diff --git a/priority-queue/pom.xml b/priority-queue/pom.xml index 37bd3896e99f..3ba564b55583 100644 --- a/priority-queue/pom.xml +++ b/priority-queue/pom.xml @@ -31,7 +31,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT diff --git a/private-class-data/pom.xml b/private-class-data/pom.xml index a613d52776b2..ecc2933d9ef7 100644 --- a/private-class-data/pom.xml +++ b/private-class-data/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT private-class-data diff --git a/producer-consumer/pom.xml b/producer-consumer/pom.xml index bd0fd0bc1cf2..479bd321aed2 100644 --- a/producer-consumer/pom.xml +++ b/producer-consumer/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT producer-consumer diff --git a/promise/pom.xml b/promise/pom.xml index a9e4f57a9f44..369e95748a87 100644 --- a/promise/pom.xml +++ b/promise/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT promise diff --git a/property/pom.xml b/property/pom.xml index 0ebddd453bd0..4e1a16a0d9f4 100644 --- a/property/pom.xml +++ b/property/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT property diff --git a/prototype/pom.xml b/prototype/pom.xml index 1babcc542b6e..7a8a685cc260 100644 --- a/prototype/pom.xml +++ b/prototype/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT prototype diff --git a/proxy/pom.xml b/proxy/pom.xml index d379cc3da4a2..e08c6ad87b51 100644 --- a/proxy/pom.xml +++ b/proxy/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT proxy diff --git a/queue-load-leveling/pom.xml b/queue-load-leveling/pom.xml index cbd13c030cc4..b77466934933 100644 --- a/queue-load-leveling/pom.xml +++ b/queue-load-leveling/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT queue-load-leveling diff --git a/reactor/pom.xml b/reactor/pom.xml index fcb7ef9a6c73..7610804309e5 100644 --- a/reactor/pom.xml +++ b/reactor/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT reactor diff --git a/reader-writer-lock/pom.xml b/reader-writer-lock/pom.xml index 3bd4f6007ff8..3892e5c62fee 100644 --- a/reader-writer-lock/pom.xml +++ b/reader-writer-lock/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT reader-writer-lock diff --git a/repository/pom.xml b/repository/pom.xml index da6be0c49945..3bae29a70ba9 100644 --- a/repository/pom.xml +++ b/repository/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT repository diff --git a/resource-acquisition-is-initialization/pom.xml b/resource-acquisition-is-initialization/pom.xml index f172dad687cc..c368d1b531cc 100644 --- a/resource-acquisition-is-initialization/pom.xml +++ b/resource-acquisition-is-initialization/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT resource-acquisition-is-initialization diff --git a/retry/pom.xml b/retry/pom.xml index d44666c62747..d1dc9531f71b 100644 --- a/retry/pom.xml +++ b/retry/pom.xml @@ -28,7 +28,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT retry jar diff --git a/role-object/pom.xml b/role-object/pom.xml index c9760527fe44..322122897394 100644 --- a/role-object/pom.xml +++ b/role-object/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT role-object diff --git a/saga/pom.xml b/saga/pom.xml index 4f87c9873347..a22ec9797f61 100644 --- a/saga/pom.xml +++ b/saga/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT saga diff --git a/semaphore/pom.xml b/semaphore/pom.xml index a61f20f0c90e..2684289981fa 100644 --- a/semaphore/pom.xml +++ b/semaphore/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT semaphore diff --git a/servant/pom.xml b/servant/pom.xml index eebd1355c31a..db5abe580025 100644 --- a/servant/pom.xml +++ b/servant/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT servant diff --git a/serverless/pom.xml b/serverless/pom.xml index bb9391d9428f..1fb55ec47536 100644 --- a/serverless/pom.xml +++ b/serverless/pom.xml @@ -31,7 +31,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT diff --git a/service-layer/pom.xml b/service-layer/pom.xml index 4f4403151099..809454907b10 100644 --- a/service-layer/pom.xml +++ b/service-layer/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT service-layer diff --git a/service-locator/pom.xml b/service-locator/pom.xml index f9c0ea023202..56a11da10b3f 100644 --- a/service-locator/pom.xml +++ b/service-locator/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT service-locator diff --git a/sharding/pom.xml b/sharding/pom.xml index 3033c355a2b3..eb24071fa4d5 100644 --- a/sharding/pom.xml +++ b/sharding/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.22.0 + 1.23.0-SNAPSHOT 4.0.0 diff --git a/singleton/pom.xml b/singleton/pom.xml index 951999192d4d..7862cd2a090b 100644 --- a/singleton/pom.xml +++ b/singleton/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT singleton diff --git a/spatial-partition/pom.xml b/spatial-partition/pom.xml index d54cae176fde..4b048714de72 100644 --- a/spatial-partition/pom.xml +++ b/spatial-partition/pom.xml @@ -46,7 +46,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT spatial-partition diff --git a/specification/pom.xml b/specification/pom.xml index 7fc6a470c7e4..79d81fd5c3a8 100644 --- a/specification/pom.xml +++ b/specification/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT specification diff --git a/state/pom.xml b/state/pom.xml index 02eaf7e86c97..cb90a53f856a 100644 --- a/state/pom.xml +++ b/state/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT state diff --git a/step-builder/pom.xml b/step-builder/pom.xml index 6c9cdf3bce78..7733af66dfc9 100644 --- a/step-builder/pom.xml +++ b/step-builder/pom.xml @@ -30,7 +30,7 @@ java-design-patterns com.iluwatar - 1.22.0 + 1.23.0-SNAPSHOT step-builder diff --git a/strategy/pom.xml b/strategy/pom.xml index 9eefa5539a04..a0f09297ecf2 100644 --- a/strategy/pom.xml +++ b/strategy/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT strategy diff --git a/subclass-sandbox/pom.xml b/subclass-sandbox/pom.xml index 298274bb9dbf..264343b00516 100644 --- a/subclass-sandbox/pom.xml +++ b/subclass-sandbox/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.22.0 + 1.23.0-SNAPSHOT 4.0.0 diff --git a/template-method/pom.xml b/template-method/pom.xml index d3cb03cf63f3..e236c28c8340 100644 --- a/template-method/pom.xml +++ b/template-method/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT template-method diff --git a/thread-pool/pom.xml b/thread-pool/pom.xml index 8e3ccbfd0fb0..14946b393710 100644 --- a/thread-pool/pom.xml +++ b/thread-pool/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT thread-pool diff --git a/throttling/pom.xml b/throttling/pom.xml index ab6572764878..5192ba28abb7 100644 --- a/throttling/pom.xml +++ b/throttling/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.22.0 + 1.23.0-SNAPSHOT 4.0.0 diff --git a/tls/pom.xml b/tls/pom.xml index ac0f1e1a3fab..48273ca715fd 100644 --- a/tls/pom.xml +++ b/tls/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT tls diff --git a/tolerant-reader/pom.xml b/tolerant-reader/pom.xml index ac7a801c5dde..c0ebaeaec7e6 100644 --- a/tolerant-reader/pom.xml +++ b/tolerant-reader/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT tolerant-reader diff --git a/trampoline/pom.xml b/trampoline/pom.xml index dc700f664324..1129de4fb265 100644 --- a/trampoline/pom.xml +++ b/trampoline/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT trampoline diff --git a/twin/pom.xml b/twin/pom.xml index b71d4e223f86..bdde082d229f 100644 --- a/twin/pom.xml +++ b/twin/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT twin diff --git a/typeobjectpattern/pom.xml b/typeobjectpattern/pom.xml index fbf05e9bc6cb..0d56a8376fdb 100644 --- a/typeobjectpattern/pom.xml +++ b/typeobjectpattern/pom.xml @@ -27,7 +27,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT typeobjectpattern diff --git a/unit-of-work/pom.xml b/unit-of-work/pom.xml index c1e4b6776f1f..a92cc4110100 100644 --- a/unit-of-work/pom.xml +++ b/unit-of-work/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.22.0 + 1.23.0-SNAPSHOT 4.0.0 diff --git a/value-object/pom.xml b/value-object/pom.xml index 4d076c5e49ef..bf8e4a1e2696 100644 --- a/value-object/pom.xml +++ b/value-object/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT value-object diff --git a/visitor/pom.xml b/visitor/pom.xml index dc18dd5202f5..c7097611fde5 100644 --- a/visitor/pom.xml +++ b/visitor/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.22.0 + 1.23.0-SNAPSHOT visitor From 8037495e04e1dfa5b4dbc97da454d2caf1f40a90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilkka=20Sepp=C3=A4l=C3=A4?= Date: Sun, 17 Nov 2019 15:20:42 +0200 Subject: [PATCH 31/31] Add some formatting to Specification pattern readme --- specification/README.md | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/specification/README.md b/specification/README.md index e55c0b799217..1764f448bb78 100644 --- a/specification/README.md +++ b/specification/README.md @@ -44,11 +44,12 @@ Wikipedia says **Programmatic Example** -If we look at our creature pool example from above, we have a set of creatures with certain properties.\ +If we look at our creature pool example from above, we have a set of creatures with certain properties. Those properties can be part of a pre-defined, limited set (represented here by the enums Size, Movement and Color); but they can also be continuous values (e.g. the mass of a Creature). In this case, it is more appropriate to use what we call "parameterized specification", where the property value can be given as an argument when the Creature is instantiated, allowing for more flexibility. -A third option is to combine pre-defined and/or parameterized properties using boolean logic, allowing for near-endless selection possibilities (this is called Composite Specification, see below). +A third option is to combine pre-defined and/or parameterized properties using boolean logic, allowing for near-endless selection possibilities (this is called "composite specification", see below). The pros and cons of each approach are detailed in the table at the end of this document. + ```java public interface Creature { String getName(); @@ -60,6 +61,7 @@ public interface Creature { ``` And ``Dragon`` implementation looks like this. + ```java public class Dragon extends AbstractCreature { @@ -70,6 +72,7 @@ public class Dragon extends AbstractCreature { ``` Now that we want to select some subset of them, we use selectors. To select creatures that fly, we should use ``MovementSelector``. + ```java public class MovementSelector extends AbstractSelector { @@ -87,6 +90,7 @@ public class MovementSelector extends AbstractSelector { ``` On the other hand, when selecting creatures heavier than a chosen amount, we use ``MassGreaterThanSelector``. + ```java public class MassGreaterThanSelector extends AbstractSelector { @@ -103,19 +107,22 @@ public class MassGreaterThanSelector extends AbstractSelector { } ``` -With these building blocks in place, we can perform a search for red creatures as follows : +With these building blocks in place, we can perform a search for red creatures as follows: + ```java List redCreatures = creatures.stream().filter(new ColorSelector(Color.RED)) .collect(Collectors.toList()); ``` -But we could also use our parameterized selector like this : +But we could also use our parameterized selector like this: + ```java List heavyCreatures = creatures.stream().filter(new MassGreaterThanSelector(500.0) .collect(Collectors.toList()); ``` -Our third option is to combine multiple selectors together. Performing a search for special creatures (defined as red, flying, and not small) could be done as follows : +Our third option is to combine multiple selectors together. Performing a search for special creatures (defined as red, flying, and not small) could be done as follows: + ```java AbstractSelector specialCreaturesSelector = new ColorSelector(Color.RED).and(new MovementSelector(Movement.FLYING)).and(new SizeSelector(Size.SMALL).not()); @@ -128,6 +135,7 @@ Our third option is to combine multiple selectors together. Performing a search In Composite Specification, we will create custom instances of ``AbstractSelector`` by combining other selectors (called "leaves") using the three basic logical operators. These are implemented in ``ConjunctionSelector``, ``DisjunctionSelector`` and ``NegationSelector``. + ```java public abstract class AbstractSelector implements Predicate { @@ -144,6 +152,7 @@ public abstract class AbstractSelector implements Predicate { } } ``` + ```java public class ConjunctionSelector extends AbstractSelector {