diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..097054fe5 --- /dev/null +++ b/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,15 @@ + +Pull request title + +- Clearly and concisely describes what it does +- Refer to the issue that it solves, if available + + +Pull request description + +- Describes the main changes that come with the pull request +- Any relevant additional information is provided + + + +> For detailed contributing instructions see https://github.com/iluwatar/java-design-patterns/wiki/01.-How-to-contribute diff --git a/README.md b/README.md index 6eed9561b..d7f2f154c 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ [![License MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/iluwatar/java-design-patterns/master/LICENSE.md) [![Join the chat at https://gitter.im/iluwatar/java-design-patterns](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/iluwatar/java-design-patterns?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Quality Gate](https://sonarqube.com/api/badges/gate?key=com.iluwatar%3Ajava-design-patterns)](https://sonarqube.com/dashboard/index/com.iluwatar%3Ajava-design-patterns) +[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/1503/badge)](https://bestpractices.coreinfrastructure.org/projects/1503) # Introduction diff --git a/_scripts/postPumlsToServer.py b/_scripts/postPumlsToServer.py deleted file mode 100644 index 107ea1988..000000000 --- a/_scripts/postPumlsToServer.py +++ /dev/null @@ -1,67 +0,0 @@ -# -# The MIT License -# Copyright (c) 2014-2016 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. -# - -import requests, glob, re, os - -# taken from here: http://stackoverflow.com/a/13641746 -def replace(file, pattern, subst): - # Read contents from file as a single string - file_handle = open(file, 'r') - file_string = file_handle.read() - file_handle.close() - - # Use RE package to allow for replacement (also allowing for (multiline) REGEX) - file_string = (re.sub(pattern, subst, file_string)) - - # Write contents to file. - # Using mode 'w' truncates the file. - file_handle = open(file, 'w') - file_handle.write(file_string) - file_handle.close() - -# list of all puml files -fileList = glob.glob('*/etc/*.puml') -for puml in fileList: - pathSplit = puml.split("/") - # parent folder - parent = pathSplit[0] - # individual artifact/project name - artifact = pathSplit[2].replace(".urm.puml", "") - print "parent: " + parent + "; artifact: " + artifact - - # do a POST to the official plantuml hosting site with a little trick "!includeurl" and raw github content - data = { - 'text': "!includeurl https://raw.githubusercontent.com/iluwatar/java-design-patterns/master/" + puml - } - r = requests.post('http://plantuml.com/plantuml/uml', data=data) - pumlId = r.url.replace("http://plantuml.com/plantuml/uml/", "") - - # the only thing needed to get a png/svg/ascii from the server back - print "Puml Server ID: " + pumlId - - # add the id so jekyll/liquid can use it - if (parent == artifact): - replace("./" + parent + "/README.md", "categories:", "pumlid: {}\\ncategories:".format(pumlId)) - else: - print "I dont want to program this, just add the following lines to the README.md file that corresponds to this puml file '" + puml + "'\npumlid: {}".format(pumlId) - diff --git a/abstract-document/README.md b/abstract-document/README.md index c8755ce07..bf28ff999 100644 --- a/abstract-document/README.md +++ b/abstract-document/README.md @@ -3,7 +3,6 @@ layout: pattern title: Abstract Document folder: abstract-document permalink: /patterns/abstract-document/ -pumlid: PSjB3eCm34NHhPG599vtDyQn85L-ifzX-p3lxEf8Twj3MXGDQvyJMFubChxpKN767gucSq07iinEjSNDOACVNvoAUZr6MWoe3QVE_WRnxZ0Mf38b-hkIGlurX_MyehS7 categories: Structural tags: - Java diff --git a/abstract-document/etc/abstract-document.urm.puml b/abstract-document/etc/abstract-document.urm.puml deleted file mode 100644 index 0c6ffc5ec..000000000 --- a/abstract-document/etc/abstract-document.urm.puml +++ /dev/null @@ -1,59 +0,0 @@ -@startuml -package com.iluwatar.abstractdocument.domain { - class Car { - + Car(properties : Map) - } - interface HasModel { - + PROPERTY : String {static} - + getModel() : Optional - } - interface HasParts { - + PROPERTY : String {static} - + getParts() : Stream - } - interface HasPrice { - + PROPERTY : String {static} - + getPrice() : Optional - } - interface HasType { - + PROPERTY : String {static} - + getType() : Optional - } - class Part { - + Part(properties : Map) - } -} -package com.iluwatar.abstractdocument { - abstract class AbstractDocument { - - properties : Map - # AbstractDocument(properties : Map) - + children(key : String, constructor : Function, T>) : Stream - + get(key : String) : Object - + put(key : String, value : Object) - + toString() : String - } - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } - interface Document { - + children(String, Function, T>) : Stream {abstract} - + get(String) : Object {abstract} - + put(String, Object) {abstract} - } -} -AbstractDocument ..|> Document -Car ..|> HasModel -Car ..|> HasPrice -Car ..|> HasParts -Car --|> AbstractDocument -HasModel --|> Document -HasParts --|> Document -HasPrice --|> Document -HasType --|> Document -Part ..|> HasType -Part ..|> HasModel -Part ..|> HasPrice -Part --|> AbstractDocument -@enduml \ No newline at end of file diff --git a/abstract-document/pom.xml b/abstract-document/pom.xml index 42d439afd..cf49544cd 100644 --- a/abstract-document/pom.xml +++ b/abstract-document/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT abstract-document diff --git a/abstract-factory/README.md b/abstract-factory/README.md index c049401fc..a08cbd35c 100644 --- a/abstract-factory/README.md +++ b/abstract-factory/README.md @@ -3,7 +3,6 @@ layout: pattern title: Abstract Factory folder: abstract-factory permalink: /patterns/abstract-factory/ -pumlid: PSZB3OD034NHLa81Czwd6sCC39gVxEUWT1_ssLmTtQLqgR5fM7sTmFGtaV6TZu8prd0r6HtQaMKqAZLk1XjT_E6qgPUZfyc0MdTgx0-8LuUn8ErFXdr98NypXxKyezKV categories: Creational tags: - Java @@ -120,6 +119,45 @@ king.getDescription(); // Output: This is the Elven king! army.getDescription(); // Output: This is the Elven Army! ``` +Now, we can design a factory for our different kingdom factories. In this example, we created FactoryMaker, responsible for returning an instance of either ElfKingdomFactory or OrcKingdomFactory. +The client can use FactoryMaker to create the desired concrete factory which, in turn, will produce different concrete objects (Army, King, Castle). +In this example, we also used an enum to parameterize which type of kingdom factory the client will ask for. + +``` +public static class FactoryMaker { + + public enum KingdomType { + ELF, ORC + } + + public static KingdomFactory makeFactory(KingdomType type) { + switch (type) { + case ELF: + return new ElfKingdomFactory(); + case ORC: + return new OrcKingdomFactory(); + default: + throw new IllegalArgumentException("KingdomType not supported."); + } + } +} + +public static void main(String[] args) { + App app = new App(); + + LOGGER.info("Elf Kingdom"); + app.createKingdom(FactoryMaker.makeFactory(KingdomType.ELF)); + LOGGER.info(app.getArmy().getDescription()); + LOGGER.info(app.getCastle().getDescription()); + LOGGER.info(app.getKing().getDescription()); + + LOGGER.info("Orc Kingdom"); + app.createKingdom(FactoryMaker.makeFactory(KingdomType.ORC)); + -- similar use of the orc factory +} +``` + + ## Applicability Use the Abstract Factory pattern when @@ -141,6 +179,10 @@ Use the Abstract Factory pattern when * Dependency injection in java hides the service class dependencies that can lead to runtime errors that would have been caught at compile time. +## Presentations + +* [Abstract Factory Pattern](etc/presentation.html) + ## Real world examples * [javax.xml.parsers.DocumentBuilderFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/parsers/DocumentBuilderFactory.html) diff --git a/abstract-factory/etc/diagram1.png b/abstract-factory/etc/diagram1.png new file mode 100644 index 000000000..e9c3c84c2 Binary files /dev/null and b/abstract-factory/etc/diagram1.png differ diff --git a/abstract-factory/etc/diagram2.png b/abstract-factory/etc/diagram2.png new file mode 100644 index 000000000..2ab524535 Binary files /dev/null and b/abstract-factory/etc/diagram2.png differ diff --git a/abstract-factory/etc/presentation.html b/abstract-factory/etc/presentation.html new file mode 100644 index 000000000..9e549faf8 --- /dev/null +++ b/abstract-factory/etc/presentation.html @@ -0,0 +1,190 @@ + + + + + Design Patterns - Abstract Factory Presentation + + + + + + + + + \ No newline at end of file diff --git a/abstract-factory/pom.xml b/abstract-factory/pom.xml index 4c7e51be2..f3a266f8e 100644 --- a/abstract-factory/pom.xml +++ b/abstract-factory/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT abstract-factory diff --git a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/App.java b/abstract-factory/src/main/java/com/iluwatar/abstractfactory/App.java index d7cb296c0..4d6043abc 100644 --- a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/App.java +++ b/abstract-factory/src/main/java/com/iluwatar/abstractfactory/App.java @@ -25,6 +25,8 @@ package com.iluwatar.abstractfactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.iluwatar.abstractfactory.App.FactoryMaker.KingdomType; + /** * * The Abstract Factory pattern provides a way to encapsulate a group of individual factories that have a common theme @@ -56,7 +58,7 @@ public class App { setCastle(factory.createCastle()); setArmy(factory.createArmy()); } - + King getKing(final KingdomFactory factory) { return factory.createKing(); } @@ -92,9 +94,36 @@ public class App { private void setArmy(final Army army) { this.army = army; } - + /** - * Program entry point + * The factory of kingdom factories. + */ + public static class FactoryMaker { + + /** + * Enumeration for the different types of Kingdoms. + */ + public enum KingdomType { + ELF, ORC + } + + /** + * The factory method to create KingdomFactory concrete objects. + */ + public static KingdomFactory makeFactory(KingdomType type) { + switch (type) { + case ELF: + return new ElfKingdomFactory(); + case ORC: + return new OrcKingdomFactory(); + default: + throw new IllegalArgumentException("KingdomType not supported."); + } + } + } + + /** + * Program entry point. * * @param args * command line args @@ -104,17 +133,15 @@ public class App { App app = new App(); LOGGER.info("Elf Kingdom"); - app.createKingdom(new ElfKingdomFactory()); + app.createKingdom(FactoryMaker.makeFactory(KingdomType.ELF)); LOGGER.info(app.getArmy().getDescription()); LOGGER.info(app.getCastle().getDescription()); LOGGER.info(app.getKing().getDescription()); LOGGER.info("Orc Kingdom"); - app.createKingdom(new OrcKingdomFactory()); + app.createKingdom(FactoryMaker.makeFactory(KingdomType.ORC)); LOGGER.info(app.getArmy().getDescription()); LOGGER.info(app.getCastle().getDescription()); LOGGER.info(app.getKing().getDescription()); - } - -} +} \ No newline at end of file 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 b6fca8b23..7613edf65 100644 --- a/abstract-factory/src/test/java/com/iluwatar/abstractfactory/AbstractFactoryTest.java +++ b/abstract-factory/src/test/java/com/iluwatar/abstractfactory/AbstractFactoryTest.java @@ -25,6 +25,9 @@ package com.iluwatar.abstractfactory; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import com.iluwatar.abstractfactory.App.FactoryMaker; +import com.iluwatar.abstractfactory.App.FactoryMaker.KingdomType; + import org.junit.Before; import org.junit.Test; @@ -39,8 +42,8 @@ public class AbstractFactoryTest { @Before public void setUp() { - elfFactory = new ElfKingdomFactory(); - orcFactory = new OrcKingdomFactory(); + elfFactory = FactoryMaker.makeFactory(KingdomType.ELF); + orcFactory = FactoryMaker.makeFactory(KingdomType.ORC); } @Test diff --git a/adapter/README.md b/adapter/README.md index 6de04a72c..3344490ff 100644 --- a/adapter/README.md +++ b/adapter/README.md @@ -3,7 +3,6 @@ layout: pattern title: Adapter folder: adapter permalink: /patterns/adapter/ -pumlid: DSR14S8m30J0Lg20M7-wEMnDOiPMFDA9j0yyUEtUkzMHJTF7xI1NF4GSLzaxZtncgDVJgCPIpobzv0N2vOKtjgRHTziMI7KBcOXl10thfxB-Nz9dMJd71m00 categories: Structural tags: - Java diff --git a/adapter/pom.xml b/adapter/pom.xml index 44259f1c6..24245fad7 100644 --- a/adapter/pom.xml +++ b/adapter/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT adapter diff --git a/aggregator-microservices/README.md b/aggregator-microservices/README.md index 75fe373fd..e65f26d9a 100644 --- a/aggregator-microservices/README.md +++ b/aggregator-microservices/README.md @@ -3,7 +3,6 @@ layout: pattern title: Aggregator Microservices folder: aggregator-microservices permalink: /patterns/aggregator-microservices/ -pumlid: JOov3SCm301NIGQGs7iRXYPa1g8ayB7NjuiKwGvtmBrbKC-Tq_hhY5Y-0HXUjKaS-Kbdepc2HrIQ2jBpma23BvvOTdPfeooCO1iEYlu0O6l63MDQKI6Rp-CKOWSE-ey_NzEqhjH-0m00 categories: Architectural tags: - Java diff --git a/aggregator-microservices/aggregator-service/pom.xml b/aggregator-microservices/aggregator-service/pom.xml index 078e38d30..32d5caa3f 100644 --- a/aggregator-microservices/aggregator-service/pom.xml +++ b/aggregator-microservices/aggregator-service/pom.xml @@ -29,7 +29,7 @@ aggregator-microservices com.iluwatar - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT 4.0.0 diff --git a/aggregator-microservices/etc/aggregator-service.urm.puml b/aggregator-microservices/etc/aggregator-service.urm.puml deleted file mode 100644 index ebb782f20..000000000 --- a/aggregator-microservices/etc/aggregator-service.urm.puml +++ /dev/null @@ -1,43 +0,0 @@ -@startuml -package com.iluwatar.aggregator.microservices { - class Aggregator { - - informationClient : ProductInformationClient - - inventoryClient : ProductInventoryClient - + Aggregator() - + getProduct() : Product - } - class App { - + App() - + main(args : String[]) {static} - } - class Product { - - productInventories : int - - title : String - + Product() - + getProductInventories() : int - + getTitle() : String - + setProductInventories(productInventories : int) - + setTitle(title : String) - } - interface ProductInformationClient { - + getProductTitle() : String {abstract} - } - class ProductInformationClientImpl { - - LOGGER : Logger {static} - + ProductInformationClientImpl() - + getProductTitle() : String - } - interface ProductInventoryClient { - + getProductInventories() : int {abstract} - } - class ProductInventoryClientImpl { - - LOGGER : Logger {static} - + ProductInventoryClientImpl() - + getProductInventories() : int - } -} -Aggregator --> "-informationClient" ProductInformationClient -Aggregator --> "-inventoryClient" ProductInventoryClient -ProductInformationClientImpl ..|> ProductInformationClient -ProductInventoryClientImpl ..|> ProductInventoryClient -@enduml \ No newline at end of file diff --git a/aggregator-microservices/etc/information-microservice.urm.puml b/aggregator-microservices/etc/information-microservice.urm.puml deleted file mode 100644 index e0a2ccb24..000000000 --- a/aggregator-microservices/etc/information-microservice.urm.puml +++ /dev/null @@ -1,12 +0,0 @@ -@startuml -package com.iluwatar.information.microservice { - class InformationApplication { - + InformationApplication() - + main(args : String[]) {static} - } - class InformationController { - + InformationController() - + getProductTitle() : String - } -} -@enduml \ No newline at end of file diff --git a/aggregator-microservices/etc/inventory-microservice.urm.puml b/aggregator-microservices/etc/inventory-microservice.urm.puml deleted file mode 100644 index 90f327e07..000000000 --- a/aggregator-microservices/etc/inventory-microservice.urm.puml +++ /dev/null @@ -1,12 +0,0 @@ -@startuml -package com.iluwatar.inventory.microservice { - class InventoryApplication { - + InventoryApplication() - + main(args : String[]) {static} - } - class InventoryController { - + InventoryController() - + getProductInventories() : int - } -} -@enduml \ No newline at end of file diff --git a/aggregator-microservices/information-microservice/pom.xml b/aggregator-microservices/information-microservice/pom.xml index f379afa27..8b24cdcc0 100644 --- a/aggregator-microservices/information-microservice/pom.xml +++ b/aggregator-microservices/information-microservice/pom.xml @@ -29,7 +29,7 @@ aggregator-microservices com.iluwatar - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT 4.0.0 diff --git a/aggregator-microservices/inventory-microservice/pom.xml b/aggregator-microservices/inventory-microservice/pom.xml index 8db0814c9..06804343c 100644 --- a/aggregator-microservices/inventory-microservice/pom.xml +++ b/aggregator-microservices/inventory-microservice/pom.xml @@ -29,7 +29,7 @@ aggregator-microservices com.iluwatar - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT 4.0.0 diff --git a/aggregator-microservices/pom.xml b/aggregator-microservices/pom.xml index caf600e86..9364ad999 100644 --- a/aggregator-microservices/pom.xml +++ b/aggregator-microservices/pom.xml @@ -29,32 +29,11 @@ java-design-patterns com.iluwatar - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT 4.0.0 aggregator-microservices pom - - - - - com.github.markusmo3.urm - urm-maven-plugin - ${urm.version} - - ${project.basedir}/../etc - - com.iluwatar - - - - aggregator-microservices - - - - - - information-microservice aggregator-service diff --git a/api-gateway/README.md b/api-gateway/README.md index 93b975e13..23014ae0b 100644 --- a/api-gateway/README.md +++ b/api-gateway/README.md @@ -3,7 +3,6 @@ layout: pattern title: API Gateway folder: api-gateway permalink: /patterns/api-gateway/ -pumlid: JSox3SCm303HLP819FRUXg49cO542_nOyFPncUvUSszHwhbpMdyT4TCt0CDLcyIHdtGsEZLOez8vG7ek33JuueLbPvUcPM84cpeCz2S0fvI6mGjluA1_b-Tt2N5D6tNcw3y0 categories: Architectural tags: - Java diff --git a/api-gateway/api-gateway-service/pom.xml b/api-gateway/api-gateway-service/pom.xml index 372c4d0dd..a97c25cfc 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.17.0-SNAPSHOT + 1.18.0-SNAPSHOT 4.0.0 api-gateway-service diff --git a/api-gateway/etc/api-gateway-service.urm.puml b/api-gateway/etc/api-gateway-service.urm.puml deleted file mode 100644 index 5fabc6a0f..000000000 --- a/api-gateway/etc/api-gateway-service.urm.puml +++ /dev/null @@ -1,48 +0,0 @@ -@startuml -package com.iluwatar.api.gateway { - class ApiGateway { - - imageClient : ImageClient - - priceClient : PriceClient - + ApiGateway() - + getProductDesktop() : DesktopProduct - + getProductMobile() : MobileProduct - } - class App { - + App() - + main(args : String[]) {static} - } - class DesktopProduct { - - imagePath : String - - price : String - + DesktopProduct() - + getImagePath() : String - + getPrice() : String - + setImagePath(imagePath : String) - + setPrice(price : String) - } - interface ImageClient { - + getImagePath() : String {abstract} - } - class ImageClientImpl { - + ImageClientImpl() - + getImagePath() : String - } - class MobileProduct { - - price : String - + MobileProduct() - + getPrice() : String - + setPrice(price : String) - } - interface PriceClient { - + getPrice() : String {abstract} - } - class PriceClientImpl { - + PriceClientImpl() - + getPrice() : String - } -} -ApiGateway --> "-imageClient" ImageClient -ApiGateway --> "-priceClient" PriceClient -ImageClientImpl ..|> ImageClient -PriceClientImpl ..|> PriceClient -@enduml \ No newline at end of file diff --git a/api-gateway/etc/image-microservice.urm.puml b/api-gateway/etc/image-microservice.urm.puml deleted file mode 100644 index 130dac9de..000000000 --- a/api-gateway/etc/image-microservice.urm.puml +++ /dev/null @@ -1,12 +0,0 @@ -@startuml -package com.iluwatar.image.microservice { - class ImageApplication { - + ImageApplication() - + main(args : String[]) {static} - } - class ImageController { - + ImageController() - + getImagePath() : String - } -} -@enduml \ No newline at end of file diff --git a/api-gateway/etc/price-microservice.urm.puml b/api-gateway/etc/price-microservice.urm.puml deleted file mode 100644 index 9893c9c60..000000000 --- a/api-gateway/etc/price-microservice.urm.puml +++ /dev/null @@ -1,12 +0,0 @@ -@startuml -package com.iluwatar.price.microservice { - class PriceApplication { - + PriceApplication() - + main(args : String[]) {static} - } - class PriceController { - + PriceController() - + getPrice() : String - } -} -@enduml \ No newline at end of file diff --git a/api-gateway/image-microservice/pom.xml b/api-gateway/image-microservice/pom.xml index 50fc12886..574623b3a 100644 --- a/api-gateway/image-microservice/pom.xml +++ b/api-gateway/image-microservice/pom.xml @@ -29,7 +29,7 @@ api-gateway com.iluwatar - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT 4.0.0 diff --git a/api-gateway/pom.xml b/api-gateway/pom.xml index f474ba66a..4334385dd 100644 --- a/api-gateway/pom.xml +++ b/api-gateway/pom.xml @@ -29,32 +29,11 @@ java-design-patterns com.iluwatar - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT 4.0.0 api-gateway pom - - - - - com.github.markusmo3.urm - urm-maven-plugin - ${urm.version} - - ${project.basedir}/../etc - - com.iluwatar - - - - api-gateway - - - - - - image-microservice price-microservice diff --git a/api-gateway/price-microservice/pom.xml b/api-gateway/price-microservice/pom.xml index ec6799674..aed9fb38b 100644 --- a/api-gateway/price-microservice/pom.xml +++ b/api-gateway/price-microservice/pom.xml @@ -29,7 +29,7 @@ api-gateway com.iluwatar - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT 4.0.0 diff --git a/async-method-invocation/README.md b/async-method-invocation/README.md index b96c1d77a..2d99820c5 100644 --- a/async-method-invocation/README.md +++ b/async-method-invocation/README.md @@ -3,7 +3,6 @@ layout: pattern title: Async Method Invocation folder: async-method-invocation permalink: /patterns/async-method-invocation/ -pumlid: TSdB3SCW303GLTe1mFTkunWhk0A3_4dKxTi5UdlIUuhIoCPfuz4Zjhy03EzwIlGyqjbeQR16fJL1HjuOQF362qjZbrFBnWWsTPZeFm3wHwbCZhvQ4RqMOSXIuA1_LzDctJd75m00 categories: Concurrency tags: - Java diff --git a/async-method-invocation/etc/async-method-invocation.urm.puml b/async-method-invocation/etc/async-method-invocation.urm.puml deleted file mode 100644 index 6f5d0b27f..000000000 --- a/async-method-invocation/etc/async-method-invocation.urm.puml +++ /dev/null @@ -1,51 +0,0 @@ -@startuml -package com.iluwatar.async.method.invocation { - class App { - - LOGGER : Logger {static} - + App() - - callback(name : String) : AsyncCallback {static} - - lazyval(value : T, delayMillis : long) : Callable {static} - - log(msg : String) {static} - + main(args : String[]) {static} - } - interface AsyncCallback { - + onComplete(T, Optional) {abstract} - } - interface AsyncExecutor { - + endProcess(AsyncResult) : T {abstract} - + startProcess(Callable) : AsyncResult {abstract} - + startProcess(Callable, AsyncCallback) : AsyncResult {abstract} - } - interface AsyncResult { - + await() {abstract} - + getValue() : T {abstract} - + isCompleted() : boolean {abstract} - } - class ThreadAsyncExecutor { - - idx : AtomicInteger - + ThreadAsyncExecutor() - + endProcess(asyncResult : AsyncResult) : T - + startProcess(task : Callable) : AsyncResult - + startProcess(task : Callable, callback : AsyncCallback) : AsyncResult - } - -class CompletableResult { - ~ COMPLETED : int {static} - ~ FAILED : int {static} - ~ RUNNING : int {static} - ~ callback : Optional> - ~ exception : Exception - ~ lock : Object - ~ state : int - ~ value : T - ~ CompletableResult(callback : AsyncCallback) - + await() - + getValue() : T - + isCompleted() : boolean - ~ setException(exception : Exception) - ~ setValue(value : T) - } -} -CompletableResult ..+ ThreadAsyncExecutor -ThreadAsyncExecutor ..|> AsyncExecutor -CompletableResult ..|> AsyncResult -@enduml \ No newline at end of file diff --git a/async-method-invocation/pom.xml b/async-method-invocation/pom.xml index af169c14f..7e15aff73 100644 --- a/async-method-invocation/pom.xml +++ b/async-method-invocation/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT async-method-invocation diff --git a/balking/README.md b/balking/README.md index f720c0d02..fb5c83d5b 100644 --- a/balking/README.md +++ b/balking/README.md @@ -18,10 +18,10 @@ incomplete or inappropriate state ## Applicability Use the Balking pattern when -*you want to invoke an action on an object only when it is in a particular state -*objects are generally only in a state that is prone to balking temporarily +* you want to invoke an action on an object only when it is in a particular state +* objects are generally only in a state that is prone to balking temporarily but for an unknown amount of time ## Related patterns * Guarded Suspension Pattern -* Double Checked Locking Pattern \ No newline at end of file +* Double Checked Locking Pattern diff --git a/balking/etc/balking.urm.puml b/balking/etc/balking.urm.puml deleted file mode 100644 index b0296b925..000000000 --- a/balking/etc/balking.urm.puml +++ /dev/null @@ -1,24 +0,0 @@ -@startuml -package com.iluwatar.balking { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } - class WashingMachine { - - LOGGER : Logger {static} - - washingMachineState : WashingMachineState - + WashingMachine() - + endOfWashing() - + getWashingMachineState() : WashingMachineState - + wash() - } - enum WashingMachineState { - + ENABLED {static} - + WASHING {static} - + valueOf(name : String) : WashingMachineState {static} - + values() : WashingMachineState[] {static} - } -} -WashingMachine --> "-washingMachineState" WashingMachineState -@enduml \ No newline at end of file diff --git a/balking/pom.xml b/balking/pom.xml index a924eae43..28fa0db61 100644 --- a/balking/pom.xml +++ b/balking/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT 4.0.0 diff --git a/bridge/README.md b/bridge/README.md index a37c35174..882640725 100644 --- a/bridge/README.md +++ b/bridge/README.md @@ -3,7 +3,6 @@ layout: pattern title: Bridge folder: bridge permalink: /patterns/bridge/ -pumlid: BSR14SCm20J0Lf82BFxf1akCJ4R26ZZYzkE7zxLljJgoIVfu7S2A3v7pLRhYo3r3l9u6CPHwJjAH5uETllpZhKbejsqn86v1a-CExQwj2mdgqv8-oyev_W00 categories: Structural tags: - Java diff --git a/bridge/pom.xml b/bridge/pom.xml index 5a807bbdd..be0f5439c 100644 --- a/bridge/pom.xml +++ b/bridge/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT bridge diff --git a/bridge/src/test/java/com/iluwatar/bridge/WeaponTest.java b/bridge/src/test/java/com/iluwatar/bridge/WeaponTest.java index daec1014a..0e62374be 100644 --- a/bridge/src/test/java/com/iluwatar/bridge/WeaponTest.java +++ b/bridge/src/test/java/com/iluwatar/bridge/WeaponTest.java @@ -44,15 +44,15 @@ public abstract class WeaponTest { assertNotNull(weapon.getEnchantment()); weapon.swing(); - verify(enchantment, times(1)).apply(); + verify(enchantment).apply(); verifyNoMoreInteractions(enchantment); weapon.wield(); - verify(enchantment, times(1)).onActivate(); + verify(enchantment).onActivate(); verifyNoMoreInteractions(enchantment); weapon.unwield(); - verify(enchantment, times(1)).onDeactivate(); + verify(enchantment).onDeactivate(); verifyNoMoreInteractions(enchantment); } diff --git a/builder/README.md b/builder/README.md index d255ec2f6..51495619b 100644 --- a/builder/README.md +++ b/builder/README.md @@ -3,7 +3,6 @@ layout: pattern title: Builder folder: builder permalink: /patterns/builder/ -pumlid: DSR94O0m2030LhG0mzzkC64KXs26GzlNZw_TcRLADagJwOWOlW8OFcNdE79B9wkN1ccKUdLWoGS33KwySMdalEioC89C7Jhw5zYIfNrIrFybhPUHNLu0 categories: Creational tags: - Java diff --git a/builder/pom.xml b/builder/pom.xml index 0c4d44bdc..0f70791e4 100644 --- a/builder/pom.xml +++ b/builder/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT builder diff --git a/business-delegate/README.md b/business-delegate/README.md index 8e6e3456c..e6e249122 100644 --- a/business-delegate/README.md +++ b/business-delegate/README.md @@ -3,7 +3,6 @@ layout: pattern title: Business Delegate folder: business-delegate permalink: /patterns/business-delegate/ -pumlid: POl13SCm3CHMQGU8zUysgYCuBcJ5a4x9-l6_Fu84tzsgvYxf-Zg06HyYvxkqZYE_6UBrD8YXr7DGrxmPxFJZYxTTeZVR9WFY5ZGu5j2wkad4wYgD8IIe_xQaZp9pw0C0 categories: Business Tier tags: - Java diff --git a/business-delegate/etc/business-delegate.urm.puml b/business-delegate/etc/business-delegate.urm.puml deleted file mode 100644 index 40aa2d6f0..000000000 --- a/business-delegate/etc/business-delegate.urm.puml +++ /dev/null @@ -1,57 +0,0 @@ -@startuml -package com.iluwatar.business.delegate { - class App { - + App() - + main(args : String[]) {static} - } - class BusinessDelegate { - - businessService : BusinessService - - lookupService : BusinessLookup - - serviceType : ServiceType - + BusinessDelegate() - + doTask() - + setLookupService(businessLookup : BusinessLookup) - + setServiceType(serviceType : ServiceType) - } - class BusinessLookup { - - ejbService : EjbService - - jmsService : JmsService - + BusinessLookup() - + getBusinessService(serviceType : ServiceType) : BusinessService - + setEjbService(ejbService : EjbService) - + setJmsService(jmsService : JmsService) - } - interface BusinessService { - + doProcessing() {abstract} - } - class Client { - - businessDelegate : BusinessDelegate - + Client(businessDelegate : BusinessDelegate) - + doTask() - } - class EjbService { - - LOGGER : Logger {static} - + EjbService() - + doProcessing() - } - class JmsService { - - LOGGER : Logger {static} - + JmsService() - + doProcessing() - } - enum ServiceType { - + EJB {static} - + JMS {static} - + valueOf(name : String) : ServiceType {static} - + values() : ServiceType[] {static} - } -} -BusinessLookup --> "-ejbService" EjbService -BusinessDelegate --> "-serviceType" ServiceType -Client --> "-businessDelegate" BusinessDelegate -BusinessDelegate --> "-businessService" BusinessService -BusinessDelegate --> "-lookupService" BusinessLookup -BusinessLookup --> "-jmsService" JmsService -EjbService ..|> BusinessService -JmsService ..|> BusinessService -@enduml \ No newline at end of file diff --git a/business-delegate/pom.xml b/business-delegate/pom.xml index db04484a4..c6ceb7e43 100644 --- a/business-delegate/pom.xml +++ b/business-delegate/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT business-delegate diff --git a/caching/README.md b/caching/README.md index b48d060f0..7184d51d4 100644 --- a/caching/README.md +++ b/caching/README.md @@ -3,7 +3,6 @@ layout: pattern title: Caching folder: caching permalink: /patterns/caching/ -pumlid: DSRB4OKm2030LhG0m_rrWyWaE0bc-6ZxpujxsbMKUXwSrfSMCVq7OFYKAj5oJsUZIuCr2bq3fEU3WGOdthWTx59rcnZ1fWu3_GqGKXEjm47VIzeeCqV_0m00 categories: Other tags: - Java diff --git a/caching/etc/caching.urm.puml b/caching/etc/caching.urm.puml deleted file mode 100644 index 6ac3fd4cc..000000000 --- a/caching/etc/caching.urm.puml +++ /dev/null @@ -1,110 +0,0 @@ -@startuml -package com.iluwatar.caching { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - + useCacheAsideStategy() - + useReadAndWriteThroughStrategy() - + useReadThroughAndWriteAroundStrategy() - + useReadThroughAndWriteBehindStrategy() - } - class AppManager { - - cachingPolicy : CachingPolicy {static} - - AppManager() - + find(userId : String) : UserAccount {static} - - findAside(userId : String) : UserAccount {static} - + initCacheCapacity(capacity : int) {static} - + initCachingPolicy(policy : CachingPolicy) {static} - + initDb(useMongoDb : boolean) {static} - + printCacheContent() : String {static} - + save(userAccount : UserAccount) {static} - - saveAside(userAccount : UserAccount) {static} - } - class CacheStore { - - LOGGER : Logger {static} - ~ cache : LruCache {static} - - CacheStore() - + clearCache() {static} - + flushCache() {static} - + get(userId : String) : UserAccount {static} - + initCapacity(capacity : int) {static} - + invalidate(userId : String) {static} - + print() : String {static} - + readThrough(userId : String) : UserAccount {static} - + readThroughWithWriteBackPolicy(userId : String) : UserAccount {static} - + set(userId : String, userAccount : UserAccount) {static} - + writeAround(userAccount : UserAccount) {static} - + writeBehind(userAccount : UserAccount) {static} - + writeThrough(userAccount : UserAccount) {static} - } - enum CachingPolicy { - + AROUND {static} - + ASIDE {static} - + BEHIND {static} - + THROUGH {static} - - policy : String - + getPolicy() : String - + valueOf(name : String) : CachingPolicy {static} - + values() : CachingPolicy[] {static} - } - class DbManager { - - db : MongoDatabase {static} - - mongoClient : MongoClient {static} - - useMongoDB : boolean {static} - - virtualDB : Map {static} - - DbManager() - + connect() {static} - + createVirtualDb() {static} - + readFromDb(userId : String) : UserAccount {static} - + updateDb(userAccount : UserAccount) {static} - + upsertDb(userAccount : UserAccount) {static} - + writeToDb(userAccount : UserAccount) {static} - } - class LruCache { - - LOGGER : Logger {static} - ~ cache : Map - ~ capacity : int - ~ end : Node - ~ head : Node - + LruCache(capacity : int) - + clear() - + contains(userId : String) : boolean - + get(userId : String) : UserAccount - + getCacheDataInListForm() : List - + getLruData() : UserAccount - + invalidate(userId : String) - + isFull() : boolean - + remove(node : Node) - + set(userId : String, userAccount : UserAccount) - + setCapacity(newCapacity : int) - + setHead(node : Node) - } - ~class Node { - ~ next : Node - ~ previous : Node - ~ userAccount : UserAccount - ~ userId : String - + Node(this$0 : String, userId : UserAccount) - } - class UserAccount { - - additionalInfo : String - - userId : String - - userName : String - + UserAccount(userId : String, userName : String, additionalInfo : String) - + getAdditionalInfo() : String - + getUserId() : String - + getUserName() : String - + setAdditionalInfo(additionalInfo : String) - + setUserId(userId : String) - + setUserName(userName : String) - + toString() : String - } -} -LruCache --> "-head" Node -Node --+ LruCache -Node --> "-previous" Node -AppManager --> "-cachingPolicy" CachingPolicy -Node --> "-userAccount" UserAccount -CacheStore --> "-cache" LruCache -@enduml \ No newline at end of file diff --git a/caching/pom.xml b/caching/pom.xml index 1da9a33d3..cd1784539 100644 --- a/caching/pom.xml +++ b/caching/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT caching diff --git a/callback/README.md b/callback/README.md index 278aa9b0a..a408fd5e0 100644 --- a/callback/README.md +++ b/callback/README.md @@ -3,7 +3,6 @@ layout: pattern title: Callback folder: callback permalink: /patterns/callback/ -pumlid: FSVB4S8m30N0Lg20M7UwUL4qYOciUFGXxSE9s-wp6sjjKgwF8tF6YyXnjxtdKMk5E5-MOjdu6jIrRYIStlXWsIJwRij4fhW53SGFn51TmIT9yZ-jVBHPGxy0 categories: Other tags: - Java diff --git a/callback/etc/callback.urm.puml b/callback/etc/callback.urm.puml deleted file mode 100644 index 02545e80f..000000000 --- a/callback/etc/callback.urm.puml +++ /dev/null @@ -1,28 +0,0 @@ -@startuml -package com.iluwatar.callback { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } - interface Callback { - + call() {abstract} - } - class LambdasApp { - - LOGGER : Logger {static} - + LambdasApp() - + main(args : String[]) {static} - } - class SimpleTask { - - LOGGER : Logger {static} - + SimpleTask() - + execute() - } - abstract class Task { - + Task() - + execute() {abstract} - + executeWith(callback : Callback) - } -} -SimpleTask --|> Task -@enduml \ No newline at end of file diff --git a/callback/pom.xml b/callback/pom.xml index b4ece4579..c87e58f63 100644 --- a/callback/pom.xml +++ b/callback/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT callback diff --git a/chain/README.md b/chain/README.md index f5f6c9de9..6bca81610 100644 --- a/chain/README.md +++ b/chain/README.md @@ -3,7 +3,6 @@ layout: pattern title: Chain of responsibility folder: chain permalink: /patterns/chain/ -pumlid: 9SR13SCm20NGLTe1OkxTXX0KKzd4Wa-pVYlrdTxJN4OTMZ4U7LZv8Wg-ssdejLTgoELGHvDhaesw6HpqvWzlXwQTlYq6D3nfSlv2qjcS5F9VgvXjrHnV categories: Behavioral tags: - Java @@ -16,7 +15,131 @@ Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it. -![alt text](./etc/chain_1.png "Chain of Responsibility") +## Explanation + +Real world example + +> The Orc King gives loud orders to his army. The closest one to react is the commander, then officer and then soldier. The commander, officer and soldier here form a chain of responsibility. + +In plain words + +> It helps building a chain of objects. Request enters from one end and keeps going from object to object till it finds the suitable handler. + +Wikipedia says + +> In object-oriented design, the chain-of-responsibility pattern is a design pattern consisting of a source of command objects and a series of processing objects. Each processing object contains logic that defines the types of command objects that it can handle; the rest are passed to the next processing object in the chain. + +**Programmatic Example** + +Translating our example with orcs from above. First we have the request class + +``` +public class Request { + + private final RequestType requestType; + private final String requestDescription; + private boolean handled; + + public Request(final RequestType requestType, final String requestDescription) { + this.requestType = Objects.requireNonNull(requestType); + this.requestDescription = Objects.requireNonNull(requestDescription); + } + + public String getRequestDescription() { return requestDescription; } + + public RequestType getRequestType() { return requestType; } + + public void markHandled() { this.handled = true; } + + public boolean isHandled() { return this.handled; } + + @Override + public String toString() { return getRequestDescription(); } +} + +public enum RequestType { + DEFEND_CASTLE, TORTURE_PRISONER, COLLECT_TAX +} +``` + +Then the request handler hierarchy + +``` +public abstract class RequestHandler { + private static final Logger LOGGER = LoggerFactory.getLogger(RequestHandler.class); + private RequestHandler next; + + public RequestHandler(RequestHandler next) { + this.next = next; + } + + public void handleRequest(Request req) { + if (next != null) { + next.handleRequest(req); + } + } + + protected void printHandling(Request req) { + LOGGER.info("{} handling request \"{}\"", this, req); + } + + @Override + public abstract String toString(); +} + +public class OrcCommander extends RequestHandler { + public OrcCommander(RequestHandler handler) { + super(handler); + } + + @Override + public void handleRequest(Request req) { + if (req.getRequestType().equals(RequestType.DEFEND_CASTLE)) { + printHandling(req); + req.markHandled(); + } else { + super.handleRequest(req); + } + } + + @Override + public String toString() { + return "Orc commander"; + } +} + +// OrcOfficer and OrcSoldier are defined similarly as OrcCommander + +``` + +Then we have the Orc King who gives the orders and forms the chain + +``` +public class OrcKing { + RequestHandler chain; + + public OrcKing() { + buildChain(); + } + + private void buildChain() { + chain = new OrcCommander(new OrcOfficer(new OrcSoldier(null))); + } + + public void makeRequest(Request req) { + chain.handleRequest(req); + } +} +``` + +Then it is used as follows + +``` +OrcKing king = new OrcKing(); +king.makeRequest(new Request(RequestType.DEFEND_CASTLE, "defend castle")); // Orc commander handling request "defend castle" +king.makeRequest(new Request(RequestType.TORTURE_PRISONER, "torture prisoner")); // Orc officer handling request "torture prisoner" +king.makeRequest(new Request(RequestType.COLLECT_TAX, "collect tax")); // Orc soldier handling request "collect tax" +``` ## Applicability Use Chain of Responsibility when diff --git a/chain/etc/chain.png b/chain/etc/chain.png deleted file mode 100644 index 7316ff3d0..000000000 Binary files a/chain/etc/chain.png and /dev/null differ diff --git a/chain/etc/chain.ucls b/chain/etc/chain.ucls deleted file mode 100644 index 4f82b40c7..000000000 --- a/chain/etc/chain.ucls +++ /dev/null @@ -1,109 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/chain/etc/chain.urm.puml b/chain/etc/chain.urm.puml deleted file mode 100644 index 4a2f6a188..000000000 --- a/chain/etc/chain.urm.puml +++ /dev/null @@ -1,61 +0,0 @@ -@startuml -package com.iluwatar.chain { - class App { - + App() - + main(args : String[]) {static} - } - class OrcCommander { - + OrcCommander(handler : RequestHandler) - + handleRequest(req : Request) - + toString() : String - } - class OrcKing { - ~ chain : RequestHandler - + OrcKing() - - buildChain() - + makeRequest(req : Request) - } - class OrcOfficer { - + OrcOfficer(handler : RequestHandler) - + handleRequest(req : Request) - + toString() : String - } - class OrcSoldier { - + OrcSoldier(handler : RequestHandler) - + handleRequest(req : Request) - + toString() : String - } - class Request { - - handled : boolean - - requestDescription : String - - requestType : RequestType - + Request(requestType : RequestType, requestDescription : String) - + getRequestDescription() : String - + getRequestType() : RequestType - + isHandled() : boolean - + markHandled() - + toString() : String - } - abstract class RequestHandler { - - LOGGER : Logger {static} - - next : RequestHandler - + RequestHandler(next : RequestHandler) - + handleRequest(req : Request) - # printHandling(req : Request) - + toString() : String {abstract} - } - enum RequestType { - + COLLECT_TAX {static} - + DEFEND_CASTLE {static} - + TORTURE_PRISONER {static} - + valueOf(name : String) : RequestType {static} - + values() : RequestType[] {static} - } -} -RequestHandler --> "-next" RequestHandler -Request --> "-requestType" RequestType -OrcKing --> "-chain" RequestHandler -OrcCommander --|> RequestHandler -OrcOfficer --|> RequestHandler -OrcSoldier --|> RequestHandler -@enduml \ No newline at end of file diff --git a/chain/etc/chain_1.png b/chain/etc/chain_1.png deleted file mode 100644 index fe9e3d6ed..000000000 Binary files a/chain/etc/chain_1.png and /dev/null differ diff --git a/chain/pom.xml b/chain/pom.xml index f35faf468..ffdb13821 100644 --- a/chain/pom.xml +++ b/chain/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT chain diff --git a/checkstyle.xml b/checkstyle.xml index 37db7e711..b3fbf19a8 100644 --- a/checkstyle.xml +++ b/checkstyle.xml @@ -85,9 +85,7 @@ value="LITERAL_TRY, LITERAL_CATCH, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, LITERAL_SWITCH"/> - - - + diff --git a/command/README.md b/command/README.md index 3996d2842..614654f5b 100644 --- a/command/README.md +++ b/command/README.md @@ -3,7 +3,6 @@ layout: pattern title: Command folder: command permalink: /patterns/command/ -pumlid: DSgn4OCm30NGLM00h3xR25i7vYpXaxx2-g59zugtTgiZcwIFvGHcV8YSdt9qdBbdYDVR88PIRwK-yc6mqyLVtff4FsoR38XRa7Aye3SgMoD1_RkaQvcfumS0 categories: Behavioral tags: - Java @@ -37,6 +36,10 @@ Use the Command pattern when you want to * implement callback functionality * implement the undo functionality +## Presentations + +* [Command Pattern](etc/presentation.html) + ## Real world examples * [java.lang.Runnable](http://docs.oracle.com/javase/8/docs/api/java/lang/Runnable.html) diff --git a/command/etc/command.urm.puml b/command/etc/command.urm.puml deleted file mode 100644 index 9bdbce64d..000000000 --- a/command/etc/command.urm.puml +++ /dev/null @@ -1,86 +0,0 @@ -@startuml -package com.iluwatar.command { - class App { - + App() - + main(args : String[]) {static} - } - abstract class Command { - + Command() - + execute(Target) {abstract} - + redo() {abstract} - + toString() : String {abstract} - + undo() {abstract} - } - class Goblin { - + Goblin() - + toString() : String - } - class InvisibilitySpell { - - target : Target - + InvisibilitySpell() - + execute(target : Target) - + redo() - + toString() : String - + undo() - } - class ShrinkSpell { - - oldSize : Size - - target : Target - + ShrinkSpell() - + execute(target : Target) - + redo() - + toString() : String - + undo() - } - enum Size { - + LARGE {static} - + NORMAL {static} - + SMALL {static} - + UNDEFINED {static} - - title : String - + toString() : String - + valueOf(name : String) : Size {static} - + values() : Size[] {static} - } - abstract class Target { - - LOGGER : Logger {static} - - size : Size - - visibility : Visibility - + Target() - + getSize() : Size - + getVisibility() : Visibility - + printStatus() - + setSize(size : Size) - + setVisibility(visibility : Visibility) - + toString() : String {abstract} - } - enum Visibility { - + INVISIBLE {static} - + UNDEFINED {static} - + VISIBLE {static} - - title : String - + toString() : String - + valueOf(name : String) : Visibility {static} - + values() : Visibility[] {static} - } - class Wizard { - - LOGGER : Logger {static} - - redoStack : Deque - - undoStack : Deque - + Wizard() - + castSpell(command : Command, target : Target) - + redoLastSpell() - + toString() : String - + undoLastSpell() - } -} -Target --> "-size" Size -Wizard --> "-undoStack" Command -ShrinkSpell --> "-oldSize" Size -InvisibilitySpell --> "-target" Target -ShrinkSpell --> "-target" Target -Target --> "-visibility" Visibility -Goblin --|> Target -InvisibilitySpell --|> Command -ShrinkSpell --|> Command -@enduml \ No newline at end of file diff --git a/command/etc/diagram.png b/command/etc/diagram.png new file mode 100644 index 000000000..1d3494292 Binary files /dev/null and b/command/etc/diagram.png differ diff --git a/command/etc/presentation.html b/command/etc/presentation.html new file mode 100644 index 000000000..88a3f0c66 --- /dev/null +++ b/command/etc/presentation.html @@ -0,0 +1,243 @@ + + + + + Design Patterns - Command Presentation + + + + + + + + + \ No newline at end of file diff --git a/command/pom.xml b/command/pom.xml index 3612dd8aa..397818f5c 100644 --- a/command/pom.xml +++ b/command/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT command diff --git a/command/src/main/java/com/iluwatar/command/Size.java b/command/src/main/java/com/iluwatar/command/Size.java index 1e72474cc..25f94a101 100644 --- a/command/src/main/java/com/iluwatar/command/Size.java +++ b/command/src/main/java/com/iluwatar/command/Size.java @@ -29,7 +29,7 @@ package com.iluwatar.command; */ public enum Size { - SMALL("small"), NORMAL("normal"), LARGE("large"), UNDEFINED(""); + SMALL("small"), NORMAL("normal"); private String title; diff --git a/command/src/main/java/com/iluwatar/command/Visibility.java b/command/src/main/java/com/iluwatar/command/Visibility.java index 802927b9d..8c360d534 100644 --- a/command/src/main/java/com/iluwatar/command/Visibility.java +++ b/command/src/main/java/com/iluwatar/command/Visibility.java @@ -29,7 +29,7 @@ package com.iluwatar.command; */ public enum Visibility { - VISIBLE("visible"), INVISIBLE("invisible"), UNDEFINED(""); + VISIBLE("visible"), INVISIBLE("invisible"); private String title; diff --git a/command/src/main/java/com/iluwatar/command/Wizard.java b/command/src/main/java/com/iluwatar/command/Wizard.java index 501676984..866ea0e0f 100644 --- a/command/src/main/java/com/iluwatar/command/Wizard.java +++ b/command/src/main/java/com/iluwatar/command/Wizard.java @@ -40,7 +40,9 @@ public class Wizard { private Deque undoStack = new LinkedList<>(); private Deque redoStack = new LinkedList<>(); - public Wizard() {} + public Wizard() { + // comment to ignore sonar issue: LEVEL critical + } /** * Cast spell diff --git a/command/src/test/java/com/iluwatar/command/CommandTest.java b/command/src/test/java/com/iluwatar/command/CommandTest.java index 5c3fa6fe1..9b8436a77 100644 --- a/command/src/test/java/com/iluwatar/command/CommandTest.java +++ b/command/src/test/java/com/iluwatar/command/CommandTest.java @@ -81,13 +81,13 @@ public class CommandTest { * @param goblin a goblin object whose state is to be verified against other parameters * @param expectedName expectedName of the goblin * @param expectedSize expected size of the goblin - * @param expectedVisibilty exepcted visibility of the goblin + * @param expectedVisibility expected visibility of the goblin */ private void verifyGoblin(Goblin goblin, String expectedName, Size expectedSize, - Visibility expectedVisibilty) { + Visibility expectedVisibility) { assertEquals("Goblin's name must be same as expectedName", expectedName, goblin.toString()); assertEquals("Goblin's size must be same as expectedSize", expectedSize, goblin.getSize()); - assertEquals("Goblin's visibility must be same as expectedVisibility", expectedVisibilty, + assertEquals("Goblin's visibility must be same as expectedVisibility", expectedVisibility, goblin.getVisibility()); } } diff --git a/composite/README.md b/composite/README.md index fbb21ecb3..e4f45ddd0 100644 --- a/composite/README.md +++ b/composite/README.md @@ -3,7 +3,6 @@ layout: pattern title: Composite folder: composite permalink: /patterns/composite/ -pumlid: HSf13eCm30NHgy01YFUzZGaM62LEP7-NwvTTT_EaMTLgoqFIst81Cpv4payv5LVk6U9r6CHGwkYaBHy6EztyvUsGqDEsoO2u1NMED-WTvmY5aA3-LT9xcTdR3m00 categories: Structural tags: - Java diff --git a/composite/pom.xml b/composite/pom.xml index 62f07c8d5..913db6989 100644 --- a/composite/pom.xml +++ b/composite/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT composite diff --git a/converter/README.md b/converter/README.md index 190ae8bfc..79b539422 100644 --- a/converter/README.md +++ b/converter/README.md @@ -3,7 +3,7 @@ layout: pattern title: Converter folder: converter permalink: /patterns/converter/ -categories: +categories: Business Tier tags: - Java - Difficulty-Beginner diff --git a/converter/etc/converter.urm.puml b/converter/etc/converter.urm.puml deleted file mode 100644 index 5e0acf191..000000000 --- a/converter/etc/converter.urm.puml +++ /dev/null @@ -1,49 +0,0 @@ -@startuml -package com.iluwatar.converter { - class App { - + App() - + main(args : String[]) {static} - } - class Converter { - - fromDto : Function - - fromEntity : Function - + Converter(fromDto : Function, fromEntity : Function) - + convertFromDto(userDto : T) : U - + convertFromEntity(user : U) : T - + createFromDtos(dtoUsers : Collection) : List - + createFromEntities(users : Collection) : List - } - class User { - - firstName : String - - isActive : boolean - - lastName : String - - userId : String - + User(firstName : String, lastName : String, isActive : boolean, userId : String) - + equals(o : Object) : boolean - + getFirstName() : String - + getLastName() : String - + getUserId() : String - + hashCode() : int - + isActive() : boolean - + toString() : String - } - class UserConverter { - + UserConverter() - } - class UserDto { - - email : String - - firstName : String - - isActive : boolean - - lastName : String - + UserDto(firstName : String, lastName : String, isActive : boolean, email : String) - + equals(o : Object) : boolean - + getEmail() : String - + getFirstName() : String - + getLastName() : String - + hashCode() : int - + isActive() : boolean - + toString() : String - } -} -UserConverter --|> Converter -@enduml \ No newline at end of file diff --git a/converter/pom.xml b/converter/pom.xml index 6bd1c5c16..923b0e43c 100644 --- a/converter/pom.xml +++ b/converter/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT 4.0.0 diff --git a/converter/src/main/java/com/iluwatar/converter/App.java b/converter/src/main/java/com/iluwatar/converter/App.java index fbae0309d..6e436706d 100644 --- a/converter/src/main/java/com/iluwatar/converter/App.java +++ b/converter/src/main/java/com/iluwatar/converter/App.java @@ -41,10 +41,7 @@ public class App { * @param args command line args */ public static void main(String[] args) { - Converter userConverter = new Converter<>( - userDto -> new User(userDto.getFirstName(), userDto.getLastName(), userDto.isActive(), - userDto.getEmail()), - user -> new UserDto(user.getFirstName(), user.getLastName(), user.isActive(), user.getUserId())); + Converter userConverter = new UserConverter(); UserDto dtoUser = new UserDto("John", "Doe", true, "whatever[at]wherever.com"); User user = userConverter.convertFromDto(dtoUser); diff --git a/converter/src/main/java/com/iluwatar/converter/Converter.java b/converter/src/main/java/com/iluwatar/converter/Converter.java index eeabc4102..918d2d503 100644 --- a/converter/src/main/java/com/iluwatar/converter/Converter.java +++ b/converter/src/main/java/com/iluwatar/converter/Converter.java @@ -68,7 +68,7 @@ public class Converter { /** * @param dtoUsers collection of DTO entities * @return List of domain representation of provided entities retrieved by - * mapping each of them with the convertion function + * mapping each of them with the conversion function */ public final List createFromDtos(final Collection dtoUsers) { return dtoUsers.stream().map(this::convertFromDto).collect(Collectors.toList()); @@ -77,7 +77,7 @@ public class Converter { /** * @param users collection of domain entities * @return List of domain representation of provided entities retrieved by - * mapping each of them with the convertion function + * mapping each of them with the conversion function */ public final List createFromEntities(final Collection users) { return users.stream().map(this::convertFromEntity).collect(Collectors.toList()); diff --git a/cqrs/README.md b/cqrs/README.md index 3cdd429a1..111c1ccd4 100644 --- a/cqrs/README.md +++ b/cqrs/README.md @@ -3,7 +3,6 @@ layout: pattern title: CQRS folder: cqrs permalink: /patterns/cqrs/ -pumlid: 7SPR4a0m3030gt00pR_RH6I8QQFouFgC_TfHb6gkd5Q7FQBx363ub4rYpoMTZKuDrYXqDX37HIuuyCPfPPTDfuuHREhGqBy0NUR0GNzAMYizMtq1 categories: Architectural tags: - Java diff --git a/cqrs/etc/cqrs.urm.puml b/cqrs/etc/cqrs.urm.puml deleted file mode 100644 index 6dd65dd3a..000000000 --- a/cqrs/etc/cqrs.urm.puml +++ /dev/null @@ -1,124 +0,0 @@ -@startuml -package com.iluwatar.cqrs.util { - class HibernateUtil { - - LOGGER : Logger {static} - - SESSIONFACTORY : SessionFactory {static} - + HibernateUtil() - - buildSessionFactory() : SessionFactory {static} - + getSessionFactory() : SessionFactory {static} - } -} -package com.iluwatar.cqrs.app { - class App { - + App() - + main(args : String[]) {static} - } -} -package com.iluwatar.cqrs.dto { - class Author { - - email : String - - name : String - - username : String - + Author() - + Author(name : String, email : String, username : String) - + equals(obj : Object) : boolean - + getEmail() : String - + getName() : String - + getUsername() : String - + hashCode() : int - + toString() : String - } - class Book { - - price : double - - title : String - + Book() - + Book(title : String, price : double) - + equals(obj : Object) : boolean - + getPrice() : double - + getTitle() : String - + hashCode() : int - + toString() : String - } -} -package com.iluwatar.cqrs.commandes { - class CommandServiceImpl { - - sessionFactory : SessionFactory - + CommandServiceImpl() - + authorCreated(username : String, name : String, email : String) - + authorEmailUpdated(username : String, email : String) - + authorNameUpdated(username : String, name : String) - + authorUsernameUpdated(oldUsername : String, newUsername : String) - + bookAddedToAuthor(title : String, price : double, username : String) - + bookPriceUpdated(title : String, price : double) - + bookTitleUpdated(oldTitle : String, newTitle : String) - - getAuthorByUsername(username : String) : Author - - getBookByTitle(title : String) : Book - } - interface ICommandService { - + authorCreated(String, String, String) {abstract} - + authorEmailUpdated(String, String) {abstract} - + authorNameUpdated(String, String) {abstract} - + authorUsernameUpdated(String, String) {abstract} - + bookAddedToAuthor(String, double, String) {abstract} - + bookPriceUpdated(String, double) {abstract} - + bookTitleUpdated(String, String) {abstract} - } -} -package com.iluwatar.cqrs.queries { - interface IQueryService { - + getAuthorBooks(String) : List {abstract} - + getAuthorBooksCount(String) : BigInteger {abstract} - + getAuthorByUsername(String) : Author {abstract} - + getAuthorsCount() : BigInteger {abstract} - + getBook(String) : Book {abstract} - } - class QueryServiceImpl { - - sessionFactory : SessionFactory - + QueryServiceImpl() - + getAuthorBooks(username : String) : List - + getAuthorBooksCount(username : String) : BigInteger - + getAuthorByUsername(username : String) : Author - + getAuthorsCount() : BigInteger - + getBook(title : String) : Book - } -} -package com.iluwatar.cqrs.domain.model { - class Author { - - email : String - - id : long - - name : String - - username : String - # Author() - + Author(username : String, name : String, email : String) - + getEmail() : String - + getId() : long - + getName() : String - + getUsername() : String - + setEmail(email : String) - + setId(id : long) - + setName(name : String) - + setUsername(username : String) - + toString() : String - } - class Book { - - author : Author - - id : long - - price : double - - title : String - # Book() - + Book(title : String, price : double, author : Author) - + getAuthor() : Author - + getId() : long - + getPrice() : double - + getTitle() : String - + setAuthor(author : Author) - + setId(id : long) - + setPrice(price : double) - + setTitle(title : String) - + toString() : String - } -} -Book --> "-author" Author -CommandServiceImpl ..|> ICommandService -QueryServiceImpl ..|> IQueryService -@enduml \ No newline at end of file diff --git a/cqrs/pom.xml b/cqrs/pom.xml index 6c036a933..2e5644bb6 100644 --- a/cqrs/pom.xml +++ b/cqrs/pom.xml @@ -21,7 +21,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT cqrs diff --git a/dao/README.md b/dao/README.md index b1b655edf..785a1c362 100644 --- a/dao/README.md +++ b/dao/README.md @@ -3,7 +3,6 @@ layout: pattern title: Data Access Object folder: dao permalink: /patterns/dao/ -pumlid: 5SR14OKW30N0LhG0oVrt4o6ZE12Ov4NR_thQNQlc5aN2sd82qtz4naywAixOmyNoK8WYvT6fjdWOR7JnpLiHhuTkam4nTUhiRwZm847-J64zpUZj3m00 categories: Persistence Tier tags: - Java diff --git a/dao/etc/dao.urm.puml b/dao/etc/dao.urm.puml deleted file mode 100644 index b0a5b2c54..000000000 --- a/dao/etc/dao.urm.puml +++ /dev/null @@ -1,66 +0,0 @@ -@startuml -package com.iluwatar.dao { - class App { - - DB_URL : String {static} - - log : Logger {static} - + App() - - addCustomers(customerDao : CustomerDao) {static} - - createDataSource() : DataSource {static} - - createSchema(dataSource : DataSource) {static} - - deleteSchema(dataSource : DataSource) {static} - + generateSampleCustomers() : List {static} - + main(args : String[]) {static} - - performOperationsUsing(customerDao : CustomerDao) {static} - } - class Customer { - - firstName : String - - id : int - - lastName : String - + Customer(id : int, firstName : String, lastName : String) - + equals(that : Object) : boolean - + getFirstName() : String - + getId() : int - + getLastName() : String - + hashCode() : int - + setFirstName(firstName : String) - + setId(id : int) - + setLastName(lastName : String) - + toString() : String - } - interface CustomerDao { - + add(Customer) : boolean {abstract} - + delete(Customer) : boolean {abstract} - + getAll() : Stream {abstract} - + getById(int) : Optional {abstract} - + update(Customer) : boolean {abstract} - } - class CustomerSchemaSql { - + CREATE_SCHEMA_SQL : String {static} - + DELETE_SCHEMA_SQL : String {static} - - CustomerSchemaSql() - } - class DbCustomerDao { - - dataSource : DataSource - + DbCustomerDao(dataSource : DataSource) - + add(customer : Customer) : boolean - - createCustomer(resultSet : ResultSet) : Customer - + delete(customer : Customer) : boolean - + getAll() : Stream - + getById(id : int) : Optional - - getConnection() : Connection - - mutedClose(connection : Connection) - + update(customer : Customer) : boolean - } - class InMemoryCustomerDao { - - idToCustomer : Map - + InMemoryCustomerDao() - + add(customer : Customer) : boolean - + delete(customer : Customer) : boolean - + getAll() : Stream - + getById(id : int) : Optional - + update(customer : Customer) : boolean - } -} -DbCustomerDao ..|> CustomerDao -InMemoryCustomerDao ..|> CustomerDao -@enduml \ No newline at end of file diff --git a/dao/pom.xml b/dao/pom.xml index e61eaba3c..4c4c8500d 100644 --- a/dao/pom.xml +++ b/dao/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT dao diff --git a/dao/src/main/java/com/iluwatar/dao/CustomException.java b/dao/src/main/java/com/iluwatar/dao/CustomException.java new file mode 100644 index 000000000..fd291b605 --- /dev/null +++ b/dao/src/main/java/com/iluwatar/dao/CustomException.java @@ -0,0 +1,43 @@ +/** + * The MIT License + * Copyright (c) 2014 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.dao; + +/** + * + * Custom exception + * + */ +public class CustomException extends Exception { + + private static final long serialVersionUID = 1L; + + public CustomException() {} + + public CustomException(String message) { + super(message); + } + + public CustomException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/dao/src/main/java/com/iluwatar/dao/DbCustomerDao.java b/dao/src/main/java/com/iluwatar/dao/DbCustomerDao.java index 6e93207cc..fa2e411da 100644 --- a/dao/src/main/java/com/iluwatar/dao/DbCustomerDao.java +++ b/dao/src/main/java/com/iluwatar/dao/DbCustomerDao.java @@ -36,12 +36,16 @@ import java.util.stream.StreamSupport; import javax.sql.DataSource; +import org.apache.log4j.Logger; + /** - * An implementation of {@link CustomerDao} that persists customers in RDBMS. + * An implementation of {@link CustomerDao} that persists customers in RDBMS. * */ public class DbCustomerDao implements CustomerDao { + private static final Logger LOGGER = Logger.getLogger(DbCustomerDao.class); + private final DataSource dataSource; /** @@ -65,8 +69,8 @@ public class DbCustomerDao implements CustomerDao { Connection connection; try { connection = getConnection(); - PreparedStatement statement = connection.prepareStatement("SELECT * FROM CUSTOMERS"); //NOSONAR - ResultSet resultSet = statement.executeQuery(); //NOSONAR + PreparedStatement statement = connection.prepareStatement("SELECT * FROM CUSTOMERS"); // NOSONAR + ResultSet resultSet = statement.executeQuery(); // NOSONAR return StreamSupport.stream(new Spliterators.AbstractSpliterator(Long.MAX_VALUE, Spliterator.ORDERED) { @@ -79,12 +83,12 @@ public class DbCustomerDao implements CustomerDao { action.accept(createCustomer(resultSet)); return true; } catch (SQLException e) { - throw new RuntimeException(e); + throw new RuntimeException(e); // NOSONAR } } }, false).onClose(() -> mutedClose(connection, statement, resultSet)); } catch (SQLException e) { - throw new Exception(e.getMessage(), e); + throw new CustomException(e.getMessage(), e); } } @@ -98,7 +102,7 @@ public class DbCustomerDao implements CustomerDao { statement.close(); connection.close(); } catch (SQLException e) { - e.printStackTrace(); + LOGGER.info("Exception thrown " + e.getMessage()); } } @@ -113,19 +117,26 @@ public class DbCustomerDao implements CustomerDao { */ @Override public Optional getById(int id) throws Exception { + + ResultSet resultSet = null; + try (Connection connection = getConnection(); PreparedStatement statement = connection.prepareStatement("SELECT * FROM CUSTOMERS WHERE ID = ?")) { statement.setInt(1, id); - ResultSet resultSet = statement.executeQuery(); + resultSet = statement.executeQuery(); if (resultSet.next()) { return Optional.of(createCustomer(resultSet)); } else { return Optional.empty(); } } catch (SQLException ex) { - throw new Exception(ex.getMessage(), ex); + throw new CustomException(ex.getMessage(), ex); + } finally { + if (resultSet != null) { + resultSet.close(); + } } } @@ -147,7 +158,7 @@ public class DbCustomerDao implements CustomerDao { statement.execute(); return true; } catch (SQLException ex) { - throw new Exception(ex.getMessage(), ex); + throw new CustomException(ex.getMessage(), ex); } } @@ -164,7 +175,7 @@ public class DbCustomerDao implements CustomerDao { statement.setInt(3, customer.getId()); return statement.executeUpdate() > 0; } catch (SQLException ex) { - throw new Exception(ex.getMessage(), ex); + throw new CustomException(ex.getMessage(), ex); } } @@ -179,7 +190,7 @@ public class DbCustomerDao implements CustomerDao { statement.setInt(1, customer.getId()); return statement.executeUpdate() > 0; } catch (SQLException ex) { - throw new Exception(ex.getMessage(), ex); + throw new CustomException(ex.getMessage(), ex); } } } diff --git a/data-bus/etc/data-bus.urm.puml b/data-bus/etc/data-bus.urm.puml deleted file mode 100644 index 9ca0ab602..000000000 --- a/data-bus/etc/data-bus.urm.puml +++ /dev/null @@ -1,77 +0,0 @@ -@startuml -package com.iluwatar.databus { - class AbstractDataType { - - dataBus : DataBus - + AbstractDataType() - + getDataBus() : DataBus - + setDataBus(dataBus : DataBus) - } - ~class App { - - log : Logger {static} - ~ App() - + main(args : String[]) {static} - } - class DataBus { - - INSTANCE : DataBus {static} - - listeners : Set - + DataBus() - + getInstance() : DataBus {static} - + publish(event : DataType) - + subscribe(member : Member) - + unsubscribe(member : Member) - } - interface DataType { - + getDataBus() : DataBus {abstract} - + setDataBus(DataBus) {abstract} - } - interface Member { - + accept(DataType) {abstract} - } -} -package com.iluwatar.databus.data { - class MessageData { - - message : String - + MessageData(message : String) - + getMessage() : String - + of(message : String) : DataType {static} - } - class StartingData { - - when : LocalDateTime - + StartingData(when : LocalDateTime) - + getWhen() : LocalDateTime - + of(when : LocalDateTime) : DataType {static} - } - class StoppingData { - - when : LocalDateTime - + StoppingData(when : LocalDateTime) - + getWhen() : LocalDateTime - + of(when : LocalDateTime) : DataType {static} - } -} -package com.iluwatar.databus.members { - class CounterMember { - - log : Logger {static} - - name : String - + CounterMember(name : String) - + accept(data : DataType) - - handleEvent(data : MessageData) - } - class StatusMember { - - id : int - - log : Logger {static} - + StatusMember(id : int) - + accept(data : DataType) - - handleEvent(data : StartingData) - - handleEvent(data : StoppingData) - } -} -AbstractDataType --> "-dataBus" DataBus -DataBus --> "-INSTANCE" DataBus -DataBus --> "-listeners" Member -AbstractDataType ..|> DataType -MessageData --|> AbstractDataType -StartingData --|> AbstractDataType -StoppingData --|> AbstractDataType -CounterMember ..|> Member -StatusMember ..|> Member -@enduml \ No newline at end of file diff --git a/data-bus/pom.xml b/data-bus/pom.xml index a77b59106..318caf89a 100644 --- a/data-bus/pom.xml +++ b/data-bus/pom.xml @@ -33,7 +33,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT data-bus diff --git a/data-mapper/README.md b/data-mapper/README.md index 362f19c51..075e8eece 100644 --- a/data-mapper/README.md +++ b/data-mapper/README.md @@ -3,7 +3,6 @@ layout: pattern title: Data Mapper folder: data-mapper permalink: /patterns/data-mapper/ -pumlid: JShB3OGm303HLg20nFVjnYGM1CN6ycTfVtFSsnjfzY5jPgUqkLqHwXy0mxUU8wuyqidQ8q4IjJqCO-QBWGOtVh5qyd5AKOmW4mT6Nu2-ZiAekapH_hkcSTNa-GC0 categories: Persistence Tier tags: - Java diff --git a/data-mapper/etc/data-mapper.urm.puml b/data-mapper/etc/data-mapper.urm.puml deleted file mode 100644 index 041cbb07b..000000000 --- a/data-mapper/etc/data-mapper.urm.puml +++ /dev/null @@ -1,42 +0,0 @@ -@startuml -package com.iluwatar.datamapper { - class App { - - log : Logger {static} - - App() - + main(args : String[]) {static} - } - class Student { - - grade : char - - name : String - - serialVersionUID : long {static} - - studentId : int - + Student(studentId : int, name : String, grade : char) - + equals(inputObject : Object) : boolean - + getGrade() : char - + getName() : String - + getStudentId() : int - + hashCode() : int - + setGrade(grade : char) - + setName(name : String) - + setStudentId(studentId : int) - + toString() : String - } - interface StudentDataMapper { - + delete(Student) {abstract} - + find(int) : Optional {abstract} - + insert(Student) {abstract} - + update(Student) {abstract} - } - class StudentDataMapperImpl { - - students : List - + StudentDataMapperImpl() - + delete(studentToBeDeleted : Student) - + find(studentId : int) : Optional - + getStudents() : List - + insert(studentToBeInserted : Student) - + update(studentToBeUpdated : Student) - } -} -StudentDataMapperImpl --> "-students" Student -StudentDataMapperImpl ..|> StudentDataMapper -@enduml \ No newline at end of file diff --git a/data-mapper/pom.xml b/data-mapper/pom.xml index 2d39ed042..66a0e469e 100644 --- a/data-mapper/pom.xml +++ b/data-mapper/pom.xml @@ -28,7 +28,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT data-mapper diff --git a/data-transfer-object/README.md b/data-transfer-object/README.md index 7fe2d9cdc..ad9b9f4e2 100644 --- a/data-transfer-object/README.md +++ b/data-transfer-object/README.md @@ -3,7 +3,6 @@ layout: pattern title: Data Transfer Object folder: data-transfer-object permalink: /patterns/data-transfer-object/ -pumlid: RSh14SCW30NHLk82GFTq8uDYum71I5zn-t41kUtCswrfwL4bhBzEOFcRoFZEHyCPUxXOcGfHv387jHutWuqk_dAguktGj1WGKwV1_WJLvqWmLl-8fRbVKa22yXTosCWhHly1 categories: Architectural tags: - Java diff --git a/data-transfer-object/etc/data-transfer-object.urm.puml b/data-transfer-object/etc/data-transfer-object.urm.puml deleted file mode 100644 index 2c21dd21c..000000000 --- a/data-transfer-object/etc/data-transfer-object.urm.puml +++ /dev/null @@ -1,26 +0,0 @@ -@startuml -package com.iluwatar.datatransfer { - class CustomerClientApp { - + CustomerClientApp() - + main(args : String[]) {static} - - printCustomerDetails(allCustomers : List) {static} - } - class CustomerDto { - - firstName : String - - id : String - - lastName : String - + CustomerDto(id : String, firstName : String, lastName : String) - + getFirstName() : String - + getId() : String - + getLastName() : String - } - class CustomerResource { - - customers : List - + CustomerResource(customers : List) - + delete(customerId : String) - + getAllCustomers() : List - + save(customer : CustomerDto) - } -} -CustomerResource --> "-customers" CustomerDto -@enduml \ No newline at end of file diff --git a/data-transfer-object/pom.xml b/data-transfer-object/pom.xml index 2f4871cb6..b0fd66da3 100644 --- a/data-transfer-object/pom.xml +++ b/data-transfer-object/pom.xml @@ -28,7 +28,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT data-transfer-object diff --git a/decorator/README.md b/decorator/README.md index 5f86166fe..4b6bfe61f 100644 --- a/decorator/README.md +++ b/decorator/README.md @@ -3,7 +3,6 @@ layout: pattern title: Decorator folder: decorator permalink: /patterns/decorator/ -pumlid: HSV14SCm20J0Lk82BFxf1YF6LaP26ZZizfDVVhjRC-bPDRs_Bc35cyZvAMV3bKU6kao36ehCGQtdms2d3z-yLursshuOKBUWmV43LPNfZEcaaFzA-YWhH_y2 categories: Structural tags: - Java @@ -35,7 +34,7 @@ Wikipedia says **Programmatic Example** -Lets take the troll example. First of all we have a simple troll implementing the troll interface +Let's take the troll example. First of all we have a simple troll implementing the troll interface ``` public interface Troll { @@ -105,9 +104,9 @@ troll.attack(); // The troll tries to grab you! troll.fleeBattle(); // The troll shrieks in horror and runs away! // change the behavior of the simple troll by adding a decorator -Troll clubbed = new ClubbedTroll(troll); -clubbed.attack(); // The troll tries to grab you! The troll swings at you with a club! -clubbed.fleeBattle(); // The troll shrieks in horror and runs away! +troll = new ClubbedTroll(troll); +troll.attack(); // The troll tries to grab you! The troll swings at you with a club! +troll.fleeBattle(); // The troll shrieks in horror and runs away! ``` ## Applicability diff --git a/decorator/pom.xml b/decorator/pom.xml index 99a7b14c0..8319c7a8f 100644 --- a/decorator/pom.xml +++ b/decorator/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT decorator diff --git a/decorator/src/main/java/com/iluwatar/decorator/App.java b/decorator/src/main/java/com/iluwatar/decorator/App.java index 14cb8aa89..5b072b9c2 100644 --- a/decorator/src/main/java/com/iluwatar/decorator/App.java +++ b/decorator/src/main/java/com/iluwatar/decorator/App.java @@ -57,9 +57,9 @@ public class App { // change the behavior of the simple troll by adding a decorator LOGGER.info("A troll with huge club surprises you."); - Troll clubbed = new ClubbedTroll(troll); - clubbed.attack(); - clubbed.fleeBattle(); - LOGGER.info("Clubbed troll power {}.\n", clubbed.getAttackPower()); + troll = new ClubbedTroll(troll); + troll.attack(); + troll.fleeBattle(); + LOGGER.info("Clubbed troll power {}.\n", troll.getAttackPower()); } } diff --git a/delegation/README.md b/delegation/README.md index b294607ec..e5c0c6376 100644 --- a/delegation/README.md +++ b/delegation/README.md @@ -3,7 +3,6 @@ layout: pattern title: Delegation folder: delegation permalink: /patterns/delegation/ -pumlid: JSV14GCX20NGLf82LkxfXbN69OFeu2VRVdBCxRsdUhLiac6F2rZxHHHybwwuyimjKQT37ANEGMfvCpZepHy-ccpjVYm697pJuFq3DJ7f39rEWlhNaZ7Aoc5V categories: Behavioral tags: - Java diff --git a/delegation/etc/delegation.urm.puml b/delegation/etc/delegation.urm.puml deleted file mode 100644 index 419cf350b..000000000 --- a/delegation/etc/delegation.urm.puml +++ /dev/null @@ -1,39 +0,0 @@ -@startuml -package com.iluwatar.delegation.simple.printers { - class CanonPrinter { - - LOGGER : Logger {static} - + CanonPrinter() - + print(message : String) - } - class EpsonPrinter { - - LOGGER : Logger {static} - + EpsonPrinter() - + print(message : String) - } - class HpPrinter { - - LOGGER : Logger {static} - + HpPrinter() - + print(message : String) - } -} -package com.iluwatar.delegation.simple { - class App { - + MESSAGE_TO_PRINT : String {static} - + App() - + main(args : String[]) {static} - } - interface Printer { - + print(String) {abstract} - } - class PrinterController { - - printer : Printer - + PrinterController(printer : Printer) - + print(message : String) - } -} -PrinterController --> "-printer" Printer -PrinterController ..|> Printer -CanonPrinter ..|> Printer -EpsonPrinter ..|> Printer -HpPrinter ..|> Printer -@enduml \ No newline at end of file diff --git a/delegation/pom.xml b/delegation/pom.xml index 67b1e599f..f2cb95dc1 100644 --- a/delegation/pom.xml +++ b/delegation/pom.xml @@ -30,7 +30,7 @@ java-design-patterns com.iluwatar - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT 4.0.0 diff --git a/dependency-injection/README.md b/dependency-injection/README.md index b4ec12e6b..735f589b1 100644 --- a/dependency-injection/README.md +++ b/dependency-injection/README.md @@ -3,7 +3,6 @@ layout: pattern title: Dependency Injection folder: dependency-injection permalink: /patterns/dependency-injection/ -pumlid: RSdB3SCW303GLPe1mFTkunWhSGG6-PEesxS3zFQajubIpyPf_NL6B7y363xra3XpJsUZgS4QbUO0wVbWeC65DvR6BeUMXH5iwZ3GVu36YxMnqgU8NamXKu63_aPD6tNbw5y0 categories: Behavioral tags: - Java diff --git a/dependency-injection/etc/dependency-injection.urm.puml b/dependency-injection/etc/dependency-injection.urm.puml deleted file mode 100644 index 80f15fce3..000000000 --- a/dependency-injection/etc/dependency-injection.urm.puml +++ /dev/null @@ -1,49 +0,0 @@ -@startuml -package com.iluwatar.dependency.injection { - class AdvancedWizard { - - tobacco : Tobacco - + AdvancedWizard(tobacco : Tobacco) - + smoke() - } - class App { - + App() - + main(args : String[]) {static} - } - class GuiceWizard { - - tobacco : Tobacco - + GuiceWizard(tobacco : Tobacco) - + smoke() - } - class OldTobyTobacco { - + OldTobyTobacco() - } - class RivendellTobacco { - + RivendellTobacco() - } - class SecondBreakfastTobacco { - + SecondBreakfastTobacco() - } - class SimpleWizard { - - tobacco : OldTobyTobacco - + SimpleWizard() - + smoke() - } - abstract class Tobacco { - - LOGGER : Logger {static} - + Tobacco() - + smoke(wizard : Wizard) - } - interface Wizard { - + smoke() {abstract} - } -} -SimpleWizard --> "-tobacco" OldTobyTobacco -AdvancedWizard --> "-tobacco" Tobacco -GuiceWizard --> "-tobacco" Tobacco -AdvancedWizard ..|> Wizard -GuiceWizard ..|> Wizard -OldTobyTobacco --|> Tobacco -RivendellTobacco --|> Tobacco -SecondBreakfastTobacco --|> Tobacco -SimpleWizard ..|> Wizard -@enduml \ No newline at end of file diff --git a/dependency-injection/pom.xml b/dependency-injection/pom.xml index e4e7765a3..e01d5b68d 100644 --- a/dependency-injection/pom.xml +++ b/dependency-injection/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT dependency-injection diff --git a/double-checked-locking/README.md b/double-checked-locking/README.md index 582e4aac6..da1fdd1a2 100644 --- a/double-checked-locking/README.md +++ b/double-checked-locking/README.md @@ -3,7 +3,6 @@ layout: pattern title: Double Checked Locking folder: double-checked-locking permalink: /patterns/double-checked-locking/ -pumlid: TSdH4SCW203GLTe1bFzkGv1J6qGFeLc_MI1_x-wzkv94uJ1vDVUrFm26LwxTMnonsMYgitgcEQ1BNEXeyCKVfiAxLqqBtTbqmy1z0ygCGpXHOpgv99bqTgt0JW-LmqPUCUGF categories: Concurrency tags: - Java diff --git a/double-checked-locking/etc/double-checked-locking.urm.puml b/double-checked-locking/etc/double-checked-locking.urm.puml deleted file mode 100644 index 242519fce..000000000 --- a/double-checked-locking/etc/double-checked-locking.urm.puml +++ /dev/null @@ -1,22 +0,0 @@ -@startuml -package com.iluwatar.doublechecked.locking { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } - class Inventory { - - LOGGER : Logger {static} - - inventorySize : int - - items : List - - lock : Lock - + Inventory(inventorySize : int) - + addItem(item : Item) : boolean - + getItems() : List - } - class Item { - + Item() - } -} -Inventory --> "-items" Item -@enduml \ No newline at end of file diff --git a/double-checked-locking/pom.xml b/double-checked-locking/pom.xml index e82dcd559..f32a45d37 100644 --- a/double-checked-locking/pom.xml +++ b/double-checked-locking/pom.xml @@ -27,7 +27,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT double-checked-locking diff --git a/double-dispatch/README.md b/double-dispatch/README.md index b0f2185f9..ae87208a2 100644 --- a/double-dispatch/README.md +++ b/double-dispatch/README.md @@ -3,7 +3,6 @@ layout: pattern title: Double Dispatch folder: double-dispatch permalink: /patterns/double-dispatch/ -pumlid: NSbB3iCW303HgpG70Ezx6yTOWSeOv4zp_MRTtUZDCPGa6wV9gqTiVmCOtlKQqVDCPwEbmHgLreGXUMEWmGU_M1hxkBHiZ61JXud-1BILft1fmvz37JZetshQh3kd_000 categories: Other tags: - Java diff --git a/double-dispatch/etc/double-dispatch.urm.puml b/double-dispatch/etc/double-dispatch.urm.puml deleted file mode 100644 index 447cf3081..000000000 --- a/double-dispatch/etc/double-dispatch.urm.puml +++ /dev/null @@ -1,68 +0,0 @@ -@startuml -package com.iluwatar.doubledispatch { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } - class FlamingAsteroid { - + FlamingAsteroid(left : int, top : int, right : int, bottom : int) - + collision(gameObject : GameObject) - } - abstract class GameObject { - - damaged : boolean - - onFire : boolean - + GameObject(left : int, top : int, right : int, bottom : int) - + collision(GameObject) {abstract} - + collisionResolve(FlamingAsteroid) {abstract} - + collisionResolve(Meteoroid) {abstract} - + collisionResolve(SpaceStationIss) {abstract} - + collisionResolve(SpaceStationMir) {abstract} - + isDamaged() : boolean - + isOnFire() : boolean - + setDamaged(damaged : boolean) - + setOnFire(onFire : boolean) - + toString() : String - } - class Meteoroid { - - LOGGER : Logger {static} - + Meteoroid(left : int, top : int, right : int, bottom : int) - + collision(gameObject : GameObject) - + collisionResolve(asteroid : FlamingAsteroid) - + collisionResolve(iss : SpaceStationIss) - + collisionResolve(meteoroid : Meteoroid) - + collisionResolve(mir : SpaceStationMir) - } - class Rectangle { - - bottom : int - - left : int - - right : int - - top : int - + Rectangle(left : int, top : int, right : int, bottom : int) - + getBottom() : int - + getLeft() : int - + getRight() : int - + getTop() : int - ~ intersectsWith(r : Rectangle) : boolean - + toString() : String - } - class SpaceStationIss { - + SpaceStationIss(left : int, top : int, right : int, bottom : int) - + collision(gameObject : GameObject) - } - class SpaceStationMir { - - LOGGER : Logger {static} - + SpaceStationMir(left : int, top : int, right : int, bottom : int) - + collision(gameObject : GameObject) - + collisionResolve(asteroid : FlamingAsteroid) - + collisionResolve(iss : SpaceStationIss) - + collisionResolve(meteoroid : Meteoroid) - + collisionResolve(mir : SpaceStationMir) - } -} -FlamingAsteroid --|> Meteoroid -GameObject --|> Rectangle -Meteoroid --|> GameObject -SpaceStationIss --|> SpaceStationMir -SpaceStationMir --|> GameObject -@enduml \ No newline at end of file diff --git a/double-dispatch/pom.xml b/double-dispatch/pom.xml index 90ea0a66d..44107f474 100644 --- a/double-dispatch/pom.xml +++ b/double-dispatch/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT double-dispatch diff --git a/eip-aggregator/README.md b/eip-aggregator/README.md new file mode 100644 index 000000000..a1dc18ea8 --- /dev/null +++ b/eip-aggregator/README.md @@ -0,0 +1,33 @@ +--- +layout: pattern +title: EIP Aggregator +folder: eip-aggregator +permalink: /patterns/eip-aggregator/ +categories: Integration +tags: + - Java + - Difficulty-Intermittent + - EIP +--- + +## Intent +Sometimes in enterprise systems there is a need to group incoming data in order to process it as a whole. For example +you may need to gather offers and after defined number of offers has been received you would like to choose the one with +the best parameters. + +Aggregator allows you to merge messages based on defined criteria and parameters. It gathers original messages, +applies aggregation strategy and upon fulfilling given criteria, releasing merged messages. + +![alt text](./etc/aggregator.gif "Splitter") + +## Applicability +Use the Aggregator pattern when + +* You need to combine multiple incoming messages +* You want to process grouped data + +## Credits + +* [Gregor Hohpe, Bobby Woolf - Enterprise Integration Patterns](http://www.enterpriseintegrationpatterns.com/patterns/messaging/Aggregator.html) +* [Apache Camel - Documentation](http://camel.apache.org/aggregator2.html) + diff --git a/eip-aggregator/etc/aggregator.gif b/eip-aggregator/etc/aggregator.gif new file mode 100644 index 000000000..b06cdfb0c Binary files /dev/null and b/eip-aggregator/etc/aggregator.gif differ diff --git a/eip-aggregator/pom.xml b/eip-aggregator/pom.xml new file mode 100644 index 000000000..7467cb3a8 --- /dev/null +++ b/eip-aggregator/pom.xml @@ -0,0 +1,63 @@ + + + + 4.0.0 + eip-aggregator + + com.iluwatar + java-design-patterns + 1.18.0-SNAPSHOT + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.apache.camel + camel-core + ${camel.version} + + + + org.apache.camel + camel-spring-boot + ${camel.version} + + + + + org.springframework.boot + spring-boot-starter-test + + + + org.apache.camel + camel-test-spring + ${camel.version} + + + + \ No newline at end of file diff --git a/eip-aggregator/src/main/java/com/iluwatar/eip/aggregator/App.java b/eip-aggregator/src/main/java/com/iluwatar/eip/aggregator/App.java new file mode 100644 index 000000000..d55f24e3d --- /dev/null +++ b/eip-aggregator/src/main/java/com/iluwatar/eip/aggregator/App.java @@ -0,0 +1,73 @@ +/** + * The MIT License + * Copyright (c) 2014 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.eip.aggregator; + +import org.apache.camel.CamelContext; +import org.apache.camel.builder.RouteBuilder; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.ConfigurableApplicationContext; + +/** + * Sometimes in enterprise systems there is a need to group incoming data in order to process it as a whole. For example + * you may need to gather offers and after defined number of offers has been received you would like to choose the one + * with the best parameters. + * + *

+ * Aggregator allows you to merge messages based on defined criteria and parameters. It gathers original messages, + * applies aggregation strategy and upon fulfilling given criteria, releasing merged messages. + *

+ * + */ +@SpringBootApplication +public class App { + + /** + * Program entry point. It starts Spring Boot application and using Apache Camel it auto-configures routes. + * + * @param args command line args + */ + public static void main(String[] args) throws Exception { + // Run Spring Boot application and obtain ApplicationContext + ConfigurableApplicationContext context = SpringApplication.run(App.class, args); + + // Get CamelContext from ApplicationContext + CamelContext camelContext = (CamelContext) context.getBean("camelContext"); + + // Add a new routes that will handle endpoints form SplitterRoute class. + camelContext.addRoutes(new RouteBuilder() { + + @Override + public void configure() throws Exception { + from("{{endpoint}}").log("ENDPOINT: ${body}"); + } + + }); + + // Add producer that will send test message to an entry point in WireTapRoute + String[] stringArray = {"Test item #1", "Test item #2", "Test item #3"}; + camelContext.createProducerTemplate().sendBody("{{entry}}", stringArray); + + SpringApplication.exit(context); + } +} diff --git a/eip-aggregator/src/main/java/com/iluwatar/eip/aggregator/routes/AggregatorRoute.java b/eip-aggregator/src/main/java/com/iluwatar/eip/aggregator/routes/AggregatorRoute.java new file mode 100644 index 000000000..536565339 --- /dev/null +++ b/eip-aggregator/src/main/java/com/iluwatar/eip/aggregator/routes/AggregatorRoute.java @@ -0,0 +1,60 @@ +/** + * The MIT License + * Copyright (c) 2014 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.eip.aggregator.routes; + +import org.apache.camel.builder.RouteBuilder; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * Sample aggregator route definition. + * + *

+ * It consumes messages out of the direct:entry entry point and forwards them to direct:endpoint. + * Route accepts messages containing String as a body, it aggregates the messages based on the settings and forwards + * them as CSV to the output chanel. + * + * Settings for the aggregation are: aggregate until 3 messages are bundled or wait 2000ms before sending bundled + * messages further. + *

+ * + * In this example input/output endpoints names are stored in application.properties file. + */ +@Component +public class AggregatorRoute extends RouteBuilder { + + @Autowired + private MessageAggregationStrategy aggregator; + + /** + * Configures the route + * @throws Exception in case of exception during configuration + */ + @Override + public void configure() throws Exception { + // Main route + from("{{entry}}").aggregate(constant(true), aggregator) + .completionSize(3).completionInterval(2000) + .to("{{endpoint}}"); + } +} diff --git a/eip-aggregator/src/main/java/com/iluwatar/eip/aggregator/routes/MessageAggregationStrategy.java b/eip-aggregator/src/main/java/com/iluwatar/eip/aggregator/routes/MessageAggregationStrategy.java new file mode 100644 index 000000000..4b5e4cb2f --- /dev/null +++ b/eip-aggregator/src/main/java/com/iluwatar/eip/aggregator/routes/MessageAggregationStrategy.java @@ -0,0 +1,49 @@ +/** + * The MIT License + * Copyright (c) 2014 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.eip.aggregator.routes; + +import org.apache.camel.Exchange; +import org.apache.camel.processor.aggregate.AggregationStrategy; +import org.springframework.stereotype.Component; + +/** + * Aggregation strategy joining bodies of messages. If message is first one oldMessage is null. All changes are + * made on IN messages. + */ +@Component +public class MessageAggregationStrategy implements AggregationStrategy { + + @Override + public Exchange aggregate(Exchange oldExchange, Exchange newExchange) { + if (oldExchange == null) { + return newExchange; + } + + String in1 = (String) oldExchange.getIn().getBody(); + String in2 = (String) newExchange.getIn().getBody(); + + oldExchange.getIn().setBody(in1 + ";" + in2); + + return oldExchange; + } +} diff --git a/eip-aggregator/src/main/resources/application.properties b/eip-aggregator/src/main/resources/application.properties new file mode 100644 index 000000000..044833fc1 --- /dev/null +++ b/eip-aggregator/src/main/resources/application.properties @@ -0,0 +1,25 @@ +# +# The MIT License +# Copyright (c) 2014 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. +# + +entry=direct:entry +endpoint=direct:endpoint diff --git a/eip-aggregator/src/test/java/com/iluwatar/eip/aggregator/AppTest.java b/eip-aggregator/src/test/java/com/iluwatar/eip/aggregator/AppTest.java new file mode 100644 index 000000000..39a3c1ab3 --- /dev/null +++ b/eip-aggregator/src/test/java/com/iluwatar/eip/aggregator/AppTest.java @@ -0,0 +1,37 @@ +/** + * The MIT License + * Copyright (c) 2014 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.eip.aggregator; + +import org.junit.Test; + +/** + * Test for App class + */ +public class AppTest { + + @Test + public void testMain() throws Exception { + String[] args = {}; + App.main(args); + } +} diff --git a/eip-aggregator/src/test/java/com/iluwatar/eip/aggregator/routes/AggregatorRouteTest.java b/eip-aggregator/src/test/java/com/iluwatar/eip/aggregator/routes/AggregatorRouteTest.java new file mode 100644 index 000000000..eb7846b9c --- /dev/null +++ b/eip-aggregator/src/test/java/com/iluwatar/eip/aggregator/routes/AggregatorRouteTest.java @@ -0,0 +1,84 @@ +/** + * The MIT License + * Copyright (c) 2014 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.eip.aggregator.routes; + +import org.apache.camel.EndpointInject; +import org.apache.camel.ProducerTemplate; +import org.apache.camel.component.mock.MockEndpoint; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import static org.junit.Assert.assertEquals; + +/** + * Test class for AggregatorRoute. + *

+ * In order for it to work we have to mock endpoints we want to read/write to. To mock those we need to substitute + * original endpoint names to mocks. + *

+ */ +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = AggregatorRouteTest.class) +@ActiveProfiles("test") +@EnableAutoConfiguration +@ComponentScan +public class AggregatorRouteTest { + + @EndpointInject(uri = "{{entry}}") + private ProducerTemplate entry; + + @EndpointInject(uri = "{{endpoint}}") + private MockEndpoint endpoint; + + /** + * Test if endpoint receives three separate messages. + * @throws Exception in case of en exception during the test + */ + @Test + @DirtiesContext + public void testSplitter() throws Exception { + + // Three items in one entry message + entry.sendBody("TEST1"); + entry.sendBody("TEST2"); + entry.sendBody("TEST3"); + entry.sendBody("TEST4"); + entry.sendBody("TEST5"); + + // Endpoint should have three different messages in the end order of the messages is not important + endpoint.expectedMessageCount(2); + endpoint.assertIsSatisfied(); + + String body = (String) endpoint.getReceivedExchanges().get(0).getIn().getBody(); + assertEquals(3, body.split(";").length); + + String body2 = (String) endpoint.getReceivedExchanges().get(1).getIn().getBody(); + assertEquals(2, body2.split(";").length); + } +} diff --git a/eip-aggregator/src/test/java/com/iluwatar/eip/aggregator/routes/MessageAggregationStrategyTest.java b/eip-aggregator/src/test/java/com/iluwatar/eip/aggregator/routes/MessageAggregationStrategyTest.java new file mode 100644 index 000000000..59aa2955d --- /dev/null +++ b/eip-aggregator/src/test/java/com/iluwatar/eip/aggregator/routes/MessageAggregationStrategyTest.java @@ -0,0 +1,64 @@ +/** + * The MIT License + * Copyright (c) 2014 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.eip.aggregator.routes; + +import org.apache.camel.CamelContext; +import org.apache.camel.Exchange; +import org.apache.camel.impl.DefaultExchange; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * Tests MessageAggregationStrategy + */ +public class MessageAggregationStrategyTest { + + @Test + public void testAggregate() { + MessageAggregationStrategy mas = new MessageAggregationStrategy(); + Exchange oldExchange = new DefaultExchange((CamelContext) null); + oldExchange.getIn().setBody("TEST1"); + + Exchange newExchange = new DefaultExchange((CamelContext) null); + newExchange.getIn().setBody("TEST2"); + + Exchange output = mas.aggregate(oldExchange, newExchange); + String outputBody = (String) output.getIn().getBody(); + assertEquals("TEST1;TEST2", outputBody); + } + + @Test + public void testAggregateOldNull() { + MessageAggregationStrategy mas = new MessageAggregationStrategy(); + + Exchange newExchange = new DefaultExchange((CamelContext) null); + newExchange.getIn().setBody("TEST2"); + + Exchange output = mas.aggregate(null, newExchange); + String outputBody = (String) output.getIn().getBody(); + + assertEquals(newExchange, output); + assertEquals("TEST2", outputBody); + } +} diff --git a/eip-aggregator/src/test/resources/application-test.properties b/eip-aggregator/src/test/resources/application-test.properties new file mode 100644 index 000000000..8d6ecbbd3 --- /dev/null +++ b/eip-aggregator/src/test/resources/application-test.properties @@ -0,0 +1,25 @@ +# +# The MIT License +# Copyright (c) 2014 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. +# + +entry=direct:entry +endpoint=mock:endpoint diff --git a/eip-splitter/README.md b/eip-splitter/README.md new file mode 100644 index 000000000..51a917bad --- /dev/null +++ b/eip-splitter/README.md @@ -0,0 +1,32 @@ +--- +layout: pattern +title: EIP Splitter +folder: eip-splitter +permalink: /patterns/eip-splitter/ +categories: Integration +tags: + - Java + - Difficulty-Intermittent + - EIP +--- + +## Intent +It is very common in integration systems that incoming messages consists of many items bundled together. For example +an invoice document contains multiple invoice lines describing transaction (quantity, name of provided +service/sold goods, price etc.). Such bundled messages may not be accepted by other systems. This is where splitter +pattern comes in handy. It will take the whole document, split it based on given criteria and send individual +items to the endpoint. + +![alt text](./etc/sequencer.gif "Splitter") + +## Applicability +Use the Splitter pattern when + +* You need to split received data into smaller pieces to process them individually +* You need to control the size of data batches you are able to process + +## Credits + +* [Gregor Hohpe, Bobby Woolf - Enterprise Integration Patterns](http://www.enterpriseintegrationpatterns.com/patterns/messaging/Sequencer.html) +* [Apache Camel - Documentation](http://camel.apache.org/splitter.html) + diff --git a/eip-splitter/etc/sequencer.gif b/eip-splitter/etc/sequencer.gif new file mode 100644 index 000000000..a925fa209 Binary files /dev/null and b/eip-splitter/etc/sequencer.gif differ diff --git a/eip-splitter/pom.xml b/eip-splitter/pom.xml new file mode 100644 index 000000000..fb7e4ca9b --- /dev/null +++ b/eip-splitter/pom.xml @@ -0,0 +1,63 @@ + + + + 4.0.0 + eip-splitter + + com.iluwatar + java-design-patterns + 1.18.0-SNAPSHOT + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.apache.camel + camel-core + ${camel.version} + + + + org.apache.camel + camel-spring-boot + ${camel.version} + + + + + org.springframework.boot + spring-boot-starter-test + + + + org.apache.camel + camel-test-spring + ${camel.version} + + + + \ No newline at end of file diff --git a/eip-splitter/src/main/java/com/iluwatar/eip/splitter/App.java b/eip-splitter/src/main/java/com/iluwatar/eip/splitter/App.java new file mode 100644 index 000000000..ceadb5f8d --- /dev/null +++ b/eip-splitter/src/main/java/com/iluwatar/eip/splitter/App.java @@ -0,0 +1,75 @@ +/** + * The MIT License + * Copyright (c) 2014 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.eip.splitter; + +import org.apache.camel.CamelContext; +import org.apache.camel.builder.RouteBuilder; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.ConfigurableApplicationContext; + +/** + * It is very common in integration systems that incoming messages consists of many items bundled together. For example + * an invoice document contains multiple invoice lines describing transaction (quantity, name of provided + * service/sold goods, price etc.). Such bundled messages may not be accepted by other systems. This is where splitter + * pattern comes in handy. It will take the whole document, split it based on given criteria and send individual + * items to the endpoint. + * + *

+ * Splitter allows you to split messages based on defined criteria. It takes original message, process it and send + * multiple parts to the output channel. It is not defined if it should keep the order of items though. + *

+ * + */ +@SpringBootApplication +public class App { + + /** + * Program entry point. It starts Spring Boot application and using Apache Camel it auto-configures routes. + * + * @param args command line args + */ + public static void main(String[] args) throws Exception { + // Run Spring Boot application and obtain ApplicationContext + ConfigurableApplicationContext context = SpringApplication.run(App.class, args); + + // Get CamelContext from ApplicationContext + CamelContext camelContext = (CamelContext) context.getBean("camelContext"); + + // Add a new routes that will handle endpoints form SplitterRoute class. + camelContext.addRoutes(new RouteBuilder() { + + @Override + public void configure() throws Exception { + from("{{endpoint}}").log("ENDPOINT: ${body}"); + } + + }); + + // Add producer that will send test message to an entry point in WireTapRoute + String[] stringArray = {"Test item #1", "Test item #2", "Test item #3"}; + camelContext.createProducerTemplate().sendBody("{{entry}}", stringArray); + + SpringApplication.exit(context); + } +} diff --git a/eip-splitter/src/main/java/com/iluwatar/eip/splitter/routes/SplitterRoute.java b/eip-splitter/src/main/java/com/iluwatar/eip/splitter/routes/SplitterRoute.java new file mode 100644 index 000000000..f7eb28dea --- /dev/null +++ b/eip-splitter/src/main/java/com/iluwatar/eip/splitter/routes/SplitterRoute.java @@ -0,0 +1,51 @@ +/** + * The MIT License + * Copyright (c) 2014 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.eip.splitter.routes; + +import org.apache.camel.builder.RouteBuilder; +import org.springframework.stereotype.Component; + +/** + * Sample splitter route definition. + * + *

+ * It consumes messages out of the direct:entry entry point and forwards them to direct:endpoint. + * Route accepts messages having body of array or collection of objects. Splitter component split message body and + * forwards single objects to the endpoint. + *

+ * + * In this example input/output endpoints names are stored in application.properties file. + */ +@Component +public class SplitterRoute extends RouteBuilder { + + /** + * Configures the route + * @throws Exception in case of exception during configuration + */ + @Override + public void configure() throws Exception { + // Main route + from("{{entry}}").split().body().to("{{endpoint}}"); + } +} diff --git a/eip-splitter/src/main/resources/application.properties b/eip-splitter/src/main/resources/application.properties new file mode 100644 index 000000000..044833fc1 --- /dev/null +++ b/eip-splitter/src/main/resources/application.properties @@ -0,0 +1,25 @@ +# +# The MIT License +# Copyright (c) 2014 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. +# + +entry=direct:entry +endpoint=direct:endpoint diff --git a/eip-splitter/src/test/java/com/iluwatar/eip/splitter/AppTest.java b/eip-splitter/src/test/java/com/iluwatar/eip/splitter/AppTest.java new file mode 100644 index 000000000..264e39c46 --- /dev/null +++ b/eip-splitter/src/test/java/com/iluwatar/eip/splitter/AppTest.java @@ -0,0 +1,37 @@ +/** + * The MIT License + * Copyright (c) 2014 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.eip.splitter; + +import org.junit.Test; + +/** + * Test for App class + */ +public class AppTest { + + @Test + public void testMain() throws Exception { + String[] args = {}; + App.main(args); + } +} diff --git a/eip-splitter/src/test/java/com/iluwatar/eip/splitter/routes/SplitterRouteTest.java b/eip-splitter/src/test/java/com/iluwatar/eip/splitter/routes/SplitterRouteTest.java new file mode 100644 index 000000000..5bc59cc1a --- /dev/null +++ b/eip-splitter/src/test/java/com/iluwatar/eip/splitter/routes/SplitterRouteTest.java @@ -0,0 +1,75 @@ +/** + * The MIT License + * Copyright (c) 2014 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.eip.splitter.routes; + +import org.apache.camel.EndpointInject; +import org.apache.camel.Message; +import org.apache.camel.ProducerTemplate; +import org.apache.camel.component.mock.MockEndpoint; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import static org.junit.Assert.assertEquals; + +/** + * Test class for SplitterRoute. + *

+ * In order for it to work we have to mock endpoints we want to read/write to. To mock those we need to substitute + * original endpoint names to mocks. + *

+ */ +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = SplitterRouteTest.class) +@ActiveProfiles("test") +@EnableAutoConfiguration +@ComponentScan +public class SplitterRouteTest { + + @EndpointInject(uri = "{{entry}}") + private ProducerTemplate entry; + + @EndpointInject(uri = "{{endpoint}}") + private MockEndpoint endpoint; + + /** + * Test if endpoint receives three separate messages. + * @throws Exception in case of en exception during the test + */ + @Test + @DirtiesContext + public void testSplitter() throws Exception { + + // Three items in one entry message + entry.sendBody(new String[] {"TEST1", "TEST2", "TEST3"}); + + // Endpoint should have three different messages in the end order of the messages is not important + endpoint.expectedMessageCount(3); + endpoint.assertIsSatisfied(); + } +} diff --git a/eip-splitter/src/test/resources/application-test.properties b/eip-splitter/src/test/resources/application-test.properties new file mode 100644 index 000000000..8d6ecbbd3 --- /dev/null +++ b/eip-splitter/src/test/resources/application-test.properties @@ -0,0 +1,25 @@ +# +# The MIT License +# Copyright (c) 2014 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. +# + +entry=direct:entry +endpoint=mock:endpoint diff --git a/eip-wire-tap/README.md b/eip-wire-tap/README.md new file mode 100644 index 000000000..31cbd9123 --- /dev/null +++ b/eip-wire-tap/README.md @@ -0,0 +1,29 @@ +--- +layout: pattern +title: EIP Wire Tap +folder: eip-wire-tap +permalink: /patterns/eip-wire-tap/ +categories: Integration +tags: + - Java + - Difficulty-Intermittent + - EIP +--- + +## Intent +In most integration cases there is a need to monitor the messages flowing through the system. It is usually achieved +by intercepting the message and redirecting it to a different location like console, filesystem or the database. +It is important that such functionality should not modify the original message and influence the processing path. + +![alt text](./etc/wiretap.gif "Wire Tap") + +## Applicability +Use the Wire Tap pattern when + +* You need to monitor messages flowing through the system +* You need to redirect the same, unchanged message to two different endpoints/paths + +## Credits + +* [Gregor Hohpe, Bobby Woolf - Enterprise Integration Patterns](http://www.enterpriseintegrationpatterns.com/patterns/messaging/WireTap.html) +* [Apache Camel - Documentation](http://camel.apache.org/wire-tap.html) diff --git a/eip-wire-tap/etc/wiretap.gif b/eip-wire-tap/etc/wiretap.gif new file mode 100644 index 000000000..414173716 Binary files /dev/null and b/eip-wire-tap/etc/wiretap.gif differ diff --git a/eip-wire-tap/pom.xml b/eip-wire-tap/pom.xml new file mode 100644 index 000000000..b3bc678b0 --- /dev/null +++ b/eip-wire-tap/pom.xml @@ -0,0 +1,63 @@ + + + + 4.0.0 + eip-wire-tap + + com.iluwatar + java-design-patterns + 1.18.0-SNAPSHOT + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.apache.camel + camel-core + ${camel.version} + + + + org.apache.camel + camel-spring-boot + ${camel.version} + + + + + org.springframework.boot + spring-boot-starter-test + + + + org.apache.camel + camel-test-spring + ${camel.version} + + + + \ No newline at end of file diff --git a/eip-wire-tap/src/main/java/com/iluwatar/eip/wiretap/App.java b/eip-wire-tap/src/main/java/com/iluwatar/eip/wiretap/App.java new file mode 100644 index 000000000..ca605cb78 --- /dev/null +++ b/eip-wire-tap/src/main/java/com/iluwatar/eip/wiretap/App.java @@ -0,0 +1,73 @@ +/** + * The MIT License + * Copyright (c) 2014 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.eip.wiretap; + +import org.apache.camel.CamelContext; +import org.apache.camel.builder.RouteBuilder; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.ConfigurableApplicationContext; + +/** + * In most integration cases there is a need to monitor the messages flowing through the system. It is usually achieved + * by intercepting the message and redirecting it to a different location like console, filesystem or the database. + * It is important that such functionality should not modify the original message and influence the processing path. + * + *

+ * Wire Tap allows you to route messages to a separate location while they are being forwarded to the ultimate + * destination. It basically consumes messages of the input channel and publishes the unmodified message to both + * output channels. + *

+ */ +@SpringBootApplication +public class App { + + /** + * Program entry point. It starts Spring Boot application and using Apache Camel it auto-configures routes. + * + * @param args command line args + */ + public static void main(String[] args) throws Exception { + // Run Spring Boot application and obtain ApplicationContext + ConfigurableApplicationContext context = SpringApplication.run(App.class, args); + + // Get CamelContext from ApplicationContext + CamelContext camelContext = (CamelContext) context.getBean("camelContext"); + + // Add a new routes that will handle endpoints form WireTapRoute class. + camelContext.addRoutes(new RouteBuilder() { + + @Override + public void configure() throws Exception { + from("{{endpoint}}").log("ENDPOINT: ${body}"); + from("{{wireTapEndpoint}}").log("WIRETAPPED ENDPOINT: ${body}"); + } + + }); + + // Add producer that will send test message to an entry point in WireTapRoute + camelContext.createProducerTemplate().sendBody("{{entry}}", "Test message"); + + SpringApplication.exit(context); + } +} diff --git a/eip-wire-tap/src/main/java/com/iluwatar/eip/wiretap/routes/WireTapRoute.java b/eip-wire-tap/src/main/java/com/iluwatar/eip/wiretap/routes/WireTapRoute.java new file mode 100644 index 000000000..994ceacdb --- /dev/null +++ b/eip-wire-tap/src/main/java/com/iluwatar/eip/wiretap/routes/WireTapRoute.java @@ -0,0 +1,54 @@ +/** + * The MIT License + * Copyright (c) 2014 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.eip.wiretap.routes; + +import org.apache.camel.builder.RouteBuilder; +import org.springframework.stereotype.Component; + +/** + * Sample wire tap route definition. + * + *

+ * It consumes messages out of the direct:entry entry point and forwards them to direct:endpoint. + * Wire Tap intercepts the message and sends it to direct:wireTap, which in turn forwards it to + * direct:wireTapEndpoint. + *

+ * + * In this example input/output endpoints names are stored in application.properties file. + */ +@Component +public class WireTapRoute extends RouteBuilder { + + /** + * Configures the route + * @throws Exception in case of exception during configuration + */ + @Override + public void configure() throws Exception { + // Main route + from("{{entry}}").wireTap("direct:wireTap").to("{{endpoint}}"); + + // Wire tap route + from("direct:wireTap").log("Message: ${body}").to("{{wireTapEndpoint}}"); + } +} diff --git a/eip-wire-tap/src/main/resources/application.properties b/eip-wire-tap/src/main/resources/application.properties new file mode 100644 index 000000000..90a152425 --- /dev/null +++ b/eip-wire-tap/src/main/resources/application.properties @@ -0,0 +1,26 @@ +# +# The MIT License +# Copyright (c) 2014 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. +# + +entry=direct:entry +endpoint=direct:endpoint +wireTapEndpoint=direct:wireTapEndpoint \ No newline at end of file diff --git a/eip-wire-tap/src/test/java/com/iluwatar/eip/wiretap/AppTest.java b/eip-wire-tap/src/test/java/com/iluwatar/eip/wiretap/AppTest.java new file mode 100644 index 000000000..31b443660 --- /dev/null +++ b/eip-wire-tap/src/test/java/com/iluwatar/eip/wiretap/AppTest.java @@ -0,0 +1,37 @@ +/** + * The MIT License + * Copyright (c) 2014 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.eip.wiretap; + +import org.junit.Test; + +/** + * Test for App class + */ +public class AppTest { + + @Test + public void testMain() throws Exception { + String[] args = {}; + App.main(args); + } +} diff --git a/eip-wire-tap/src/test/java/com/iluwatar/eip/wiretap/routes/WireTapRouteTest.java b/eip-wire-tap/src/test/java/com/iluwatar/eip/wiretap/routes/WireTapRouteTest.java new file mode 100644 index 000000000..71c487bd8 --- /dev/null +++ b/eip-wire-tap/src/test/java/com/iluwatar/eip/wiretap/routes/WireTapRouteTest.java @@ -0,0 +1,84 @@ +/** + * The MIT License + * Copyright (c) 2014 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.eip.wiretap.routes; + +import org.apache.camel.EndpointInject; +import org.apache.camel.Message; +import org.apache.camel.ProducerTemplate; +import org.apache.camel.component.mock.MockEndpoint; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import static org.junit.Assert.assertEquals; + +/** + * Test class for WireTapRoute. + *

+ * In order for it to work we have to mock endpoints we want to read/write to. To mock those we need to substitute + * original endpoint names to mocks. + *

+ */ +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = WireTapRouteTest.class) +@ActiveProfiles("test") +@EnableAutoConfiguration +@ComponentScan +public class WireTapRouteTest { + + @EndpointInject(uri = "{{entry}}") + private ProducerTemplate entry; + + @EndpointInject(uri = "{{endpoint}}") + private MockEndpoint endpoint; + + @EndpointInject(uri = "{{wireTapEndpoint}}") + private MockEndpoint wireTapEndpoint; + + /** + * Test if both endpoints receive exactly one message containing the same, unchanged body. + * @throws Exception in case of en exception during the test + */ + @Test + @DirtiesContext + public void testWireTap() throws Exception { + entry.sendBody("TEST"); + + endpoint.expectedMessageCount(1); + wireTapEndpoint.expectedMessageCount(1); + + endpoint.assertIsSatisfied(); + wireTapEndpoint.assertIsSatisfied(); + + Message endpointIn = endpoint.getExchanges().get(0).getIn(); + Message wireTapEndpointIn = wireTapEndpoint.getExchanges().get(0).getIn(); + + assertEquals("TEST", endpointIn.getBody()); + assertEquals("TEST", wireTapEndpointIn.getBody()); + } +} diff --git a/eip-wire-tap/src/test/resources/application-test.properties b/eip-wire-tap/src/test/resources/application-test.properties new file mode 100644 index 000000000..e76faa1fc --- /dev/null +++ b/eip-wire-tap/src/test/resources/application-test.properties @@ -0,0 +1,26 @@ +# +# The MIT License +# Copyright (c) 2014 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. +# + +entry=direct:entry +endpoint=mock:endpoint +wireTapEndpoint=mock:wireTapEndpoint \ No newline at end of file diff --git a/event-aggregator/README.md b/event-aggregator/README.md index ce7f358de..ac07869e7 100644 --- a/event-aggregator/README.md +++ b/event-aggregator/README.md @@ -3,7 +3,6 @@ layout: pattern title: Event Aggregator folder: event-aggregator permalink: /patterns/event-aggregator/ -pumlid: PSf13iCW30NHgxG70Ezx6uTOX0eCih-JwvTzTwEdUJSjFKu9wwyBMFuXCdvoRRZY21ShKo6ANEQWrkDXiD6NRqwdUAkQ5WDYwZJOTv3SUqzSgqbbp0qeVvZ3Hbun-Wy0 categories: Structural tags: - Java diff --git a/event-aggregator/etc/event-aggregator.urm.puml b/event-aggregator/etc/event-aggregator.urm.puml deleted file mode 100644 index 341d7d65e..000000000 --- a/event-aggregator/etc/event-aggregator.urm.puml +++ /dev/null @@ -1,74 +0,0 @@ -@startuml -package com.iluwatar.event.aggregator { - class App { - + App() - + main(args : String[]) {static} - } - enum Event { - + STARK_SIGHTED {static} - + TRAITOR_DETECTED {static} - + WARSHIPS_APPROACHING {static} - - description : String - + toString() : String - + valueOf(name : String) : Event {static} - + values() : Event[] {static} - } - abstract class EventEmitter { - - observers : List - + EventEmitter() - + EventEmitter(obs : EventObserver) - # notifyObservers(e : Event) - + registerObserver(obs : EventObserver) - + timePasses(Weekday) {abstract} - } - interface EventObserver { - + onEvent(Event) {abstract} - } - class KingJoffrey { - - LOGGER : Logger {static} - + KingJoffrey() - + onEvent(e : Event) - } - class KingsHand { - + KingsHand() - + KingsHand(obs : EventObserver) - + onEvent(e : Event) - + timePasses(day : Weekday) - } - class LordBaelish { - + LordBaelish() - + LordBaelish(obs : EventObserver) - + timePasses(day : Weekday) - } - class LordVarys { - + LordVarys() - + LordVarys(obs : EventObserver) - + timePasses(day : Weekday) - } - class Scout { - + Scout() - + Scout(obs : EventObserver) - + timePasses(day : Weekday) - } - enum Weekday { - + FRIDAY {static} - + MONDAY {static} - + SATURDAY {static} - + SUNDAY {static} - + THURSDAY {static} - + TUESDAY {static} - + WEDNESDAY {static} - - description : String - + toString() : String - + valueOf(name : String) : Weekday {static} - + values() : Weekday[] {static} - } -} -EventEmitter --> "-observers" EventObserver -KingJoffrey ..|> EventObserver -KingsHand ..|> EventObserver -KingsHand --|> EventEmitter -LordBaelish --|> EventEmitter -LordVarys --|> EventEmitter -Scout --|> EventEmitter -@enduml \ No newline at end of file diff --git a/event-aggregator/pom.xml b/event-aggregator/pom.xml index 19e76af84..a3e7f96cf 100644 --- a/event-aggregator/pom.xml +++ b/event-aggregator/pom.xml @@ -28,7 +28,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT event-aggregator diff --git a/event-asynchronous/etc/event-asynchronous.urm.puml b/event-asynchronous/etc/event-asynchronous.urm.puml deleted file mode 100644 index 0d683d27d..000000000 --- a/event-asynchronous/etc/event-asynchronous.urm.puml +++ /dev/null @@ -1,66 +0,0 @@ -@startuml -package com.iluwatar.event.asynchronous { - class App { - - LOGGER : Logger {static} - + PROP_FILE_NAME : String {static} - ~ interactiveMode : boolean - + App() - + main(args : String[]) {static} - + quickRun() - + run() - + runInteractiveMode() - + setUp() - } - class Event { - - LOGGER : Logger {static} - - eventId : int - - eventListener : ThreadCompleteListener - - eventTime : int - - isComplete : boolean - - isSynchronous : boolean - - thread : Thread - + Event(eventId : int, eventTime : int, isSynchronous : boolean) - + addListener(listener : ThreadCompleteListener) - - completed() - + isSynchronous() : boolean - + removeListener(listener : ThreadCompleteListener) - + run() - + start() - + status() - + stop() - } - class EventManager { - + MAX_EVENT_TIME : int {static} - + MAX_ID : int {static} - + MAX_RUNNING_EVENTS : int {static} - + MIN_ID : int {static} - - currentlyRunningSyncEvent : int - - eventPool : Map - - rand : Random - + EventManager() - + cancel(eventId : int) - + completedEventHandler(eventId : int) - + create(eventTime : int) : int - + createAsync(eventTime : int) : int - - createEvent(eventTime : int, isSynchronous : boolean) : int - - generateId() : int - + getEventPool() : Map - + numOfCurrentlyRunningSyncEvent() : int - + shutdown() - + start(eventId : int) - + status(eventId : int) - + statusOfAllEvents() - } - interface IEvent { - + start() {abstract} - + status() {abstract} - + stop() {abstract} - } - interface ThreadCompleteListener { - + completedEventHandler(int) {abstract} - } -} -Event --> "-eventListener" ThreadCompleteListener -Event ..|> IEvent -EventManager ..|> ThreadCompleteListener -@enduml \ No newline at end of file diff --git a/event-asynchronous/pom.xml b/event-asynchronous/pom.xml index 5a2d65bfe..afb3213f1 100644 --- a/event-asynchronous/pom.xml +++ b/event-asynchronous/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT event-asynchronous diff --git a/event-driven-architecture/README.md b/event-driven-architecture/README.md index a263defec..e2f06cf5a 100644 --- a/event-driven-architecture/README.md +++ b/event-driven-architecture/README.md @@ -3,7 +3,6 @@ layout: pattern title: Event Driven Architecture folder: event-driven-architecture permalink: /patterns/event-driven-architecture/ -pumlid: TOhH3SCW30LNQGS0_tSRnrZ15H1adfFromBzkfFktZQaHT7mzgh0N1yYvoUVXXf7B7Mv1dGWozN9MZmCTlhopQdeidEaoO3wMDHvRI6zzvwAssPYbsfGGRYIGlxN7DxpZDv- categories: Architectural tags: - Java diff --git a/event-driven-architecture/etc/event-driven-architecture.urm.puml b/event-driven-architecture/etc/event-driven-architecture.urm.puml deleted file mode 100644 index 2eb79e438..000000000 --- a/event-driven-architecture/etc/event-driven-architecture.urm.puml +++ /dev/null @@ -1,64 +0,0 @@ -@startuml -package com.iluwatar.eda.handler { - class UserCreatedEventHandler { - - LOGGER : Logger {static} - + UserCreatedEventHandler() - + onEvent(event : UserCreatedEvent) - } - class UserUpdatedEventHandler { - - LOGGER : Logger {static} - + UserUpdatedEventHandler() - + onEvent(event : UserUpdatedEvent) - } -} -package com.iluwatar.eda.event { - abstract class AbstractEvent { - + AbstractEvent() - + getType() : Class - } - class UserCreatedEvent { - - user : User - + UserCreatedEvent(user : User) - + getUser() : User - } - class UserUpdatedEvent { - - user : User - + UserUpdatedEvent(user : User) - + getUser() : User - } -} -package com.iluwatar.eda.framework { - interface Event { - + getType() : Class {abstract} - } - class EventDispatcher { - - handlers : Map, Handler> - + EventDispatcher() - + dispatch(event : E extends Event) - + registerHandler(eventType : Class, handler : Handler) - } - interface Handler { - + onEvent(E extends Event) {abstract} - } -} -package com.iluwatar.eda.model { - class User { - - username : String - + User(username : String) - + getUsername() : String - } -} -package com.iluwatar.eda { - class App { - + App() - + main(args : String[]) {static} - } -} -UserUpdatedEvent --> "-user" User -UserCreatedEvent --> "-user" User -AbstractEvent ..|> Event -UserCreatedEvent --|> AbstractEvent -UserUpdatedEvent --|> AbstractEvent -UserCreatedEventHandler ..|> Handler -UserUpdatedEventHandler ..|> Handler -@enduml \ No newline at end of file diff --git a/event-driven-architecture/pom.xml b/event-driven-architecture/pom.xml index 4f2c34b5e..4db6b6c0c 100644 --- a/event-driven-architecture/pom.xml +++ b/event-driven-architecture/pom.xml @@ -31,7 +31,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT event-driven-architecture diff --git a/event-queue/etc/event-queue.urm.puml b/event-queue/etc/event-queue.urm.puml deleted file mode 100644 index e2aabee31..000000000 --- a/event-queue/etc/event-queue.urm.puml +++ /dev/null @@ -1,26 +0,0 @@ -@startuml -package com.iluwatar.event.queue { - class App { - + App() - + getAudioStream(filePath : String) : AudioInputStream {static} - + main(args : String[]) {static} - } - class Audio { - - MAX_PENDING : int {static} - - headIndex : int {static} - - pendingAudio : PlayMessage[] {static} - - tailIndex : int {static} - - updateThread : Thread {static} - + Audio() - + init() {static} - + playSound(stream : AudioInputStream, volume : float) {static} - + stopService() {static} - + update() {static} - } - class PlayMessage { - ~ stream : AudioInputStream - ~ volume : float - + PlayMessage() - } -} -@enduml \ No newline at end of file diff --git a/event-queue/pom.xml b/event-queue/pom.xml index 59dfa9119..cbfc0976d 100644 --- a/event-queue/pom.xml +++ b/event-queue/pom.xml @@ -30,7 +30,7 @@ java-design-patterns com.iluwatar - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT event-queue diff --git a/event-sourcing/etc/event-sourcing.urm.puml b/event-sourcing/etc/event-sourcing.urm.puml deleted file mode 100644 index 207d238e6..000000000 --- a/event-sourcing/etc/event-sourcing.urm.puml +++ /dev/null @@ -1,184 +0,0 @@ -@startuml -package com.iluwatar.event.sourcing.journal { - class JsonFileJournal { - - aFile : File - - events : List - - index : int - + JsonFileJournal() - + readNext() : DomainEvent - + reset() - + write(domainEvent : DomainEvent) - } -} -package com.iluwatar.event.sourcing.processor { - class DomainEventProcessor { - - precessorJournal : ProcessorJournal - + DomainEventProcessor() - + process(domainEvent : DomainEvent) - + recover() - + setPrecessorJournal(precessorJournal : ProcessorJournal) - } -} -package com.iluwatar.event.sourcing.service { - class AccountService { - - eventProcessor : EventProcessor - + AccountService(eventProcessor : EventProcessor) - + createAccount(accountNo : int, owner : String) - } - class MoneyTransactionService { - - eventProcessor : EventProcessor - + MoneyTransactionService(eventProcessor : EventProcessor) - + depositMoney(accountNo : int, money : BigDecimal) - + transferMoney(accountNoFrom : int, accountNoTo : int, money : BigDecimal) - + withdrawalMoney(accountNo : int, money : BigDecimal) - } - class SequenceIdGenerator { - - sequenceId : long {static} - + SequenceIdGenerator() - + nextSequenceId() : long {static} - } -} -package com.iluwatar.event.sourcing.event { - class AccountCreateEvent { - - accountNo : int - - owner : String - + AccountCreateEvent(sequenceId : long, createdTime : long, accountNo : int, owner : String) - + getAccountNo() : int - + getOwner() : String - + process() - } - class MoneyDepositEvent { - - accountNo : int - - money : BigDecimal - + MoneyDepositEvent(sequenceId : long, createdTime : long, accountNo : int, money : BigDecimal) - + getAccountNo() : int - + getMoney() : BigDecimal - + process() - } - class MoneyTransferEvent { - - accountNoFrom : int - - accountNoTo : int - - money : BigDecimal - + MoneyTransferEvent(sequenceId : long, createdTime : long, money : BigDecimal, accountNoFrom : int, accountNoTo : int) - + getAccountNoFrom() : int - + getAccountNoTo() : int - + getMoney() : BigDecimal - + process() - } - class MoneyWithdrawalEvent { - - accountNo : int - - money : BigDecimal - + MoneyWithdrawalEvent(sequenceId : long, createdTime : long, accountNo : int, money : BigDecimal) - + getAccountNo() : int - + getMoney() : BigDecimal - + process() - } -} -package com.iluwatar.event.sourcing.gateway { - class AccountCreateContractSender { - + AccountCreateContractSender() - + sendContractInfo(account : Account) - } - class Gateways { - - accountCreateContractSender : AccountCreateContractSender {static} - - transactionLogger : TransactionLogger {static} - + Gateways() - + getAccountCreateContractSender() : AccountCreateContractSender {static} - + getTransactionLogger() : TransactionLogger {static} - } - class TransactionLogger { - + TransactionLogger() - + log(transaction : Transaction) - } -} -package com.iluwatar.event.sourcing.app { - class App { - + App() - + main(args : String[]) {static} - } -} -package com.iluwatar.event.sourcing.state { - class AccountAggregate { - - accounts : Map {static} - + AccountAggregate() - + getAccount(accountNo : int) : Account {static} - + putAccount(account : Account) {static} - + resetState() {static} - } -} -package com.iluwatar.event.sourcing.domain { - class Account { - - accountNo : int - - money : BigDecimal - - owner : String - - transactions : List - + Account(accountNo : int, owner : String) - + copy() : Account - - depositMoney(money : BigDecimal) : Transaction - + getAccountNo() : int - + getMoney() : BigDecimal - + getOwner() : String - + getTransactions() : List - - handleDeposit(money : BigDecimal, realTime : boolean) - + handleEvent(accountCreateEvent : AccountCreateEvent) - + handleEvent(moneyDepositEvent : MoneyDepositEvent) - + handleEvent(moneyWithdrawalEvent : MoneyWithdrawalEvent) - + handleTransferFromEvent(moneyTransferEvent : MoneyTransferEvent) - + handleTransferToEvent(moneyTransferEvent : MoneyTransferEvent) - - handleWithdrawal(money : BigDecimal, realTime : boolean) - + setMoney(money : BigDecimal) - + setTransactions(transactions : List) - + toString() : String - - withdrawMoney(money : BigDecimal) : Transaction - } - class Transaction { - - accountNo : int - - lastBalance : BigDecimal - - moneyIn : BigDecimal - - moneyOut : BigDecimal - + Transaction(accountNo : int, moneyIn : BigDecimal, moneyOut : BigDecimal, lastBalance : BigDecimal) - + getAccountNo() : int - + getLastBalance() : BigDecimal - + getMoneyIn() : BigDecimal - + getMoneyOut() : BigDecimal - + toString() : String - } -} -package com.iluwatar.event.sourcing.api { - abstract class DomainEvent { - - createdTime : long - - eventClassName : String - - realTime : boolean - - sequenceId : long - + DomainEvent(sequenceId : long, createdTime : long, eventClassName : String) - + getCreatedTime() : long - + getEventClassName() : String - + getSequenceId() : long - + isRealTime() : boolean - + process() {abstract} - + setRealTime(realTime : boolean) - } - interface EventProcessor { - + process(DomainEvent) {abstract} - + recover() {abstract} - + setPrecessorJournal(ProcessorJournal) {abstract} - } - interface ProcessorJournal { - + readNext() : DomainEvent {abstract} - + reset() {abstract} - + write(DomainEvent) {abstract} - } -} -Gateways --> "-accountCreateContractSender" AccountCreateContractSender -DomainEventProcessor --> "-precessorJournal" ProcessorJournal -Account --> "-transactions" Transaction -Gateways --> "-transactionLogger" TransactionLogger -AccountService --> "-eventProcessor" EventProcessor -MoneyTransactionService --> "-eventProcessor" EventProcessor -AccountCreateEvent --|> DomainEvent -MoneyDepositEvent --|> DomainEvent -MoneyTransferEvent --|> DomainEvent -MoneyWithdrawalEvent --|> DomainEvent -JsonFileJournal ..|> ProcessorJournal -DomainEventProcessor ..|> EventProcessor -@enduml \ No newline at end of file diff --git a/event-sourcing/pom.xml b/event-sourcing/pom.xml index 35d462cb1..ac7745fbe 100644 --- a/event-sourcing/pom.xml +++ b/event-sourcing/pom.xml @@ -30,7 +30,7 @@ java-design-patterns com.iluwatar - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT event-sourcing diff --git a/execute-around/README.md b/execute-around/README.md index e0ae128b5..f669f18ff 100644 --- a/execute-around/README.md +++ b/execute-around/README.md @@ -3,7 +3,6 @@ layout: pattern title: Execute Around folder: execute-around permalink: /patterns/execute-around/ -pumlid: NSZ14G8n20NGLhI0XBlT865suoGa0n_NylNixSsxTvEHJTF7xGHsF8YShtfqdFdCK9TbK4ELDQcFl1ZizE8tbwRH3okR0NKBcXm_a7vK4bhOLreZXVnLJPzrvnnV categories: Other tags: - Java diff --git a/execute-around/etc/execute-around.urm.puml b/execute-around/etc/execute-around.urm.puml deleted file mode 100644 index fd01a5fe1..000000000 --- a/execute-around/etc/execute-around.urm.puml +++ /dev/null @@ -1,14 +0,0 @@ -@startuml -package com.iluwatar.execute.around { - class App { - + App() - + main(args : String[]) {static} - } - interface FileWriterAction { - + writeFile(FileWriter) {abstract} - } - class SimpleFileWriter { - + SimpleFileWriter(filename : String, action : FileWriterAction) - } -} -@enduml \ No newline at end of file diff --git a/execute-around/pom.xml b/execute-around/pom.xml index c4b3ac504..3da4dc440 100644 --- a/execute-around/pom.xml +++ b/execute-around/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT execute-around diff --git a/extension-objects/etc/extension-objects.urm.puml b/extension-objects/etc/extension-objects.urm.puml deleted file mode 100644 index 02af47ddf..000000000 --- a/extension-objects/etc/extension-objects.urm.puml +++ /dev/null @@ -1,2 +0,0 @@ -@startuml -@enduml \ No newline at end of file diff --git a/extension-objects/pom.xml b/extension-objects/pom.xml index c5ee535fe..2215834d7 100644 --- a/extension-objects/pom.xml +++ b/extension-objects/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT 4.0.0 diff --git a/facade/README.md b/facade/README.md index 66ca84256..7caa89d94 100644 --- a/facade/README.md +++ b/facade/README.md @@ -3,7 +3,6 @@ layout: pattern title: Facade folder: facade permalink: /patterns/facade/ -pumlid: BSP15eCm20N0gxG7CEoz3ILKqvTW7dpq-hhehERTJ7fMJU-l7PYn4ZbVPMlOyvEXBeT13KMEGQtdnM2d7v-yL8sssJ8PKBUWmV64lYnSbHJoRqaVPUReDm00 categories: Structural tags: - Java @@ -203,7 +202,7 @@ Use the Facade pattern when * you want to provide a simple interface to a complex subsystem. Subsystems often get more complex as they evolve. Most patterns, when applied, result in more and smaller classes. This makes the subsystem more reusable and easier to customize, but it also becomes harder to use for clients that don't need to customize it. A facade can provide a simple default view of the subsystem that is good enough for most clients. Only clients needing more customizability will need to look beyond the facade. * there are many dependencies between clients and the implementation classes of an abstraction. Introduce a facade to decouple the subsystem from clients and other subsystems, thereby promoting subsystem independence and portability. -* you want to layer your subsystems. Use a facade to define an entry point to each subsystem level. If subsystems are dependent, the you can simplify the dependencies between them by making them communicate with each other solely through their facades +* you want to layer your subsystems. Use a facade to define an entry point to each subsystem level. If subsystems are dependent, then you can simplify the dependencies between them by making them communicate with each other solely through their facades. ## Credits diff --git a/facade/pom.xml b/facade/pom.xml index d699ac8fe..7a6021530 100644 --- a/facade/pom.xml +++ b/facade/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT facade diff --git a/factory-kit/README.md b/factory-kit/README.md index b47cbff76..c25701047 100644 --- a/factory-kit/README.md +++ b/factory-kit/README.md @@ -3,7 +3,6 @@ layout: pattern title: Factory Kit folder: factory-kit permalink: /patterns/factory-kit/ -pumlid: JST15i8m20N0g-W14lRU1YcsQ4BooCS-RwzBTpDNSscvQKQx7C1SDwBWi-w68--vD6Gur55bTBAM9uE3dlpcikcotSjaGCCNTLu_q8C58pxbPI25_Bzcz3gpjoy0 categories: Creational tags: - Java diff --git a/factory-kit/etc/factory-kit.urm.puml b/factory-kit/etc/factory-kit.urm.puml deleted file mode 100644 index 23cf658f4..000000000 --- a/factory-kit/etc/factory-kit.urm.puml +++ /dev/null @@ -1,46 +0,0 @@ -@startuml -package com.iluwatar.factorykit { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } - class Axe { - + Axe() - + toString() : String - } - class Bow { - + Bow() - + toString() : String - } - interface Builder { - + add(WeaponType, Supplier) {abstract} - } - class Spear { - + Spear() - + toString() : String - } - class Sword { - + Sword() - + toString() : String - } - interface Weapon { - } - interface WeaponFactory { - + create(WeaponType) : Weapon {abstract} - + factory(consumer : Consumer) : WeaponFactory {static} - } - enum WeaponType { - + AXE {static} - + BOW {static} - + SPEAR {static} - + SWORD {static} - + valueOf(name : String) : WeaponType {static} - + values() : WeaponType[] {static} - } -} -Axe ..|> Weapon -Bow ..|> Weapon -Spear ..|> Weapon -Sword ..|> Weapon -@enduml \ No newline at end of file diff --git a/factory-kit/pom.xml b/factory-kit/pom.xml index 50942b3a0..eee0cd734 100644 --- a/factory-kit/pom.xml +++ b/factory-kit/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT factory-kit diff --git a/factory-method/README.md b/factory-method/README.md index 07c92d0e5..ab3739ac3 100644 --- a/factory-method/README.md +++ b/factory-method/README.md @@ -3,7 +3,6 @@ layout: pattern title: Factory Method folder: factory-method permalink: /patterns/factory-method/ -pumlid: NSZB3G8n30N0Lg20n7UwCOxPP9MVx6TMT0zdRgEvjoazYeRrMmMsFuYChtmqr7Y6gycQq8aiQr3hSJ7OwEGtfwBUZfas0shJQR3_G2yMBFkaeQYha4B-AeUDl6FqBm00 categories: Creational tags: - Java @@ -70,7 +69,11 @@ Use the Factory Method pattern when * a class wants its subclasses to specify the objects it creates * classes delegate responsibility to one of several helper subclasses, and you want to localize the knowledge of which helper subclass is the delegate -## Known uses +## Presentations + +* [Factory Method Pattern](etc/presentation.html) + +## Real world examples * [java.util.Calendar](http://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html#getInstance--) * [java.util.ResourceBundle](http://docs.oracle.com/javase/8/docs/api/java/util/ResourceBundle.html#getBundle-java.lang.String-) diff --git a/factory-method/etc/diagram1.png b/factory-method/etc/diagram1.png new file mode 100644 index 000000000..fa325edf0 Binary files /dev/null and b/factory-method/etc/diagram1.png differ diff --git a/factory-method/etc/presentation.html b/factory-method/etc/presentation.html new file mode 100644 index 000000000..a78057836 --- /dev/null +++ b/factory-method/etc/presentation.html @@ -0,0 +1,185 @@ + + + + + Design Patterns - Factory Method Presentation + + + + + + + + + \ No newline at end of file diff --git a/factory-method/pom.xml b/factory-method/pom.xml index 61d0058ae..8c54f63a1 100644 --- a/factory-method/pom.xml +++ b/factory-method/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT factory-method diff --git a/factory-method/src/test/java/com/iluwatar/factory/method/FactoryMethodTest.java b/factory-method/src/test/java/com/iluwatar/factory/method/FactoryMethodTest.java index 4f3a5930d..71afc5549 100644 --- a/factory-method/src/test/java/com/iluwatar/factory/method/FactoryMethodTest.java +++ b/factory-method/src/test/java/com/iluwatar/factory/method/FactoryMethodTest.java @@ -53,7 +53,7 @@ public class FactoryMethodTest { } /** - * Testing {@link OrcBlacksmith} to produce a AXE asserting that the Weapon is an instance + * Testing {@link OrcBlacksmith} to produce an AXE asserting that the Weapon is an instance * of {@link OrcWeapon}. */ @Test @@ -95,7 +95,7 @@ public class FactoryMethodTest { */ private void verifyWeapon(Weapon weapon, WeaponType expectedWeaponType, Class clazz) { assertTrue("Weapon must be an object of: " + clazz.getName(), clazz.isInstance(weapon)); - assertEquals("Weapon must be of weaponType: " + clazz.getName(), expectedWeaponType, + assertEquals("Weapon must be of weaponType: " + expectedWeaponType, expectedWeaponType, weapon.getWeaponType()); } } diff --git a/feature-toggle/README.md b/feature-toggle/README.md index 06d956178..c466b8a94 100644 --- a/feature-toggle/README.md +++ b/feature-toggle/README.md @@ -3,7 +3,6 @@ layout: pattern title: Feature Toggle folder: feature-toggle permalink: /patterns/feature-toggle/ -pumlid: NSZ14G8X30NGLhG0oDrk8XjPd12OvCTjNy_UthpxiAPvIBhUJc37WyZvgdtWp6U6U5i6CTIs9WtDYy5ER_vmEIH6jx8P4BUWoV43lOIHBWMhTnKIjB-gwRFkdFe5 categories: Behavioral tags: - Java diff --git a/feature-toggle/etc/feature-toggle.urm.puml b/feature-toggle/etc/feature-toggle.urm.puml deleted file mode 100644 index 0febb2631..000000000 --- a/feature-toggle/etc/feature-toggle.urm.puml +++ /dev/null @@ -1,48 +0,0 @@ -@startuml -package com.iluwatar.featuretoggle.pattern { - interface Service { - + getWelcomeMessage(User) : String {abstract} - + isEnhanced() : boolean {abstract} - } -} -package com.iluwatar.featuretoggle.user { - class User { - - name : String - + User(name : String) - + toString() : String - } - class UserGroup { - - freeGroup : List {static} - - paidGroup : List {static} - + UserGroup() - + addUserToFreeGroup(user : User) {static} - + addUserToPaidGroup(user : User) {static} - + isPaid(user : User) : boolean {static} - } -} -package com.iluwatar.featuretoggle.pattern.tieredversion { - class TieredFeatureToggleVersion { - + TieredFeatureToggleVersion() - + getWelcomeMessage(user : User) : String - + isEnhanced() : boolean - } -} -package com.iluwatar.featuretoggle.pattern.propertiesversion { - class PropertiesFeatureToggleVersion { - - isEnhanced : boolean - + PropertiesFeatureToggleVersion(properties : Properties) - + getWelcomeMessage(user : User) : String - + isEnhanced() : boolean - } -} -package com.iluwatar.featuretoggle { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } -} -UserGroup --> "-freeGroup" User -PropertiesFeatureToggleVersion ..|> Service -TieredFeatureToggleVersion ..|> Service -@enduml \ No newline at end of file diff --git a/feature-toggle/pom.xml b/feature-toggle/pom.xml index b8201aa4f..6536710ba 100644 --- a/feature-toggle/pom.xml +++ b/feature-toggle/pom.xml @@ -30,7 +30,7 @@ java-design-patterns com.iluwatar - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT 4.0.0 diff --git a/fluentinterface/README.md b/fluentinterface/README.md index 8bf43d974..767792da7 100644 --- a/fluentinterface/README.md +++ b/fluentinterface/README.md @@ -3,7 +3,6 @@ layout: pattern title: Fluent Interface folder: fluentinterface permalink: /patterns/fluentinterface/ -pumlid: NOj93eCm302_KXv0VEzlN6F0bMCYB_3zvjpRQ3IpY97MnkNwEZD7l04SdtP8dlMfOAVBaYqRNHr4wy54Xo_Uk6uSSjWwC9FT0Zh61DYrPY_pyXs9WPF-NIllRLJN7m00 categories: Other tags: - Java diff --git a/fluentinterface/etc/fluentinterface.urm.puml b/fluentinterface/etc/fluentinterface.urm.puml deleted file mode 100644 index ef71a0f4b..000000000 --- a/fluentinterface/etc/fluentinterface.urm.puml +++ /dev/null @@ -1,72 +0,0 @@ -@startuml -package com.iluwatar.fluentinterface.fluentiterable.simple { - class SimpleFluentIterable { - - iterable : Iterable - # SimpleFluentIterable(iterable : Iterable) - + asList() : List - + filter(predicate : Predicate) : FluentIterable - + first() : Optional - + first(count : int) : FluentIterable - + forEach(action : Consumer) - + from(iterable : Iterable) : FluentIterable {static} - + fromCopyOf(iterable : Iterable) : FluentIterable {static} - + getRemainingElementsCount() : int - + iterator() : Iterator - + last() : Optional - + last(count : int) : FluentIterable - + map(function : Function) : FluentIterable - + spliterator() : Spliterator - + toList(iterator : Iterator) : List {static} - } -} -package com.iluwatar.fluentinterface.app { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - - negatives() : Predicate {static} - - positives() : Predicate {static} - - prettyPrint(delimiter : String, prefix : String, iterable : Iterable) {static} - - prettyPrint(prefix : String, iterable : Iterable) {static} - - transformToString() : Function {static} - } -} -package com.iluwatar.fluentinterface.fluentiterable.lazy { - abstract class DecoratingIterator { - # fromIterator : Iterator - - next : E - + DecoratingIterator(fromIterator : Iterator) - + computeNext() : E {abstract} - + hasNext() : boolean - + next() : E - } - class LazyFluentIterable { - - iterable : Iterable - # LazyFluentIterable() - # LazyFluentIterable(iterable : Iterable) - + asList() : List - + filter(predicate : Predicate) : FluentIterable - + first() : Optional - + first(count : int) : FluentIterable - + from(iterable : Iterable) : FluentIterable {static} - + iterator() : Iterator - + last() : Optional - + last(count : int) : FluentIterable - + map(function : Function) : FluentIterable - } -} -package com.iluwatar.fluentinterface.fluentiterable { - interface FluentIterable { - + asList() : List {abstract} - + copyToList(iterable : Iterable) : List {static} - + filter(Predicate) : FluentIterable {abstract} - + first() : Optional {abstract} - + first(int) : FluentIterable {abstract} - + last() : Optional {abstract} - + last(int) : FluentIterable {abstract} - + map(Function) : FluentIterable {abstract} - } -} -LazyFluentIterable ..|> FluentIterable -SimpleFluentIterable ..|> FluentIterable -@enduml \ No newline at end of file diff --git a/fluentinterface/pom.xml b/fluentinterface/pom.xml index 9c352f1a9..11318e295 100644 --- a/fluentinterface/pom.xml +++ b/fluentinterface/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT 4.0.0 diff --git a/flux/README.md b/flux/README.md index e36b73900..7ac312c44 100644 --- a/flux/README.md +++ b/flux/README.md @@ -3,7 +3,6 @@ layout: pattern title: Flux folder: flux permalink: /patterns/flux/ -pumlid: 7SP14eCm20NGg-W13FlU1YFLE0GpyAazVZk-rPkRLSrDqdKwW14l8kUxx0r7hXdYzJA8eTIhKzEy6UnqyeUNJQBjjWm6n2seS_n3Ryql2UgJajxBoAu_ categories: Presentation Tier tags: - Java diff --git a/flux/etc/flux.urm.puml b/flux/etc/flux.urm.puml deleted file mode 100644 index 11ac26d60..000000000 --- a/flux/etc/flux.urm.puml +++ /dev/null @@ -1,117 +0,0 @@ -@startuml -package com.iluwatar.flux.view { - class ContentView { - - LOGGER : Logger {static} - - content : Content - + ContentView() - + render() - + storeChanged(store : Store) - } - class MenuView { - - LOGGER : Logger {static} - - selected : MenuItem - + MenuView() - + itemClicked(item : MenuItem) - + render() - + storeChanged(store : Store) - } - interface View { - + render() {abstract} - + storeChanged(Store) {abstract} - } -} -package com.iluwatar.flux.action { - abstract class Action { - - type : ActionType - + Action(type : ActionType) - + getType() : ActionType - } - enum ActionType { - + CONTENT_CHANGED {static} - + MENU_ITEM_SELECTED {static} - + valueOf(name : String) : ActionType {static} - + values() : ActionType[] {static} - } - enum Content { - + COMPANY {static} - + PRODUCTS {static} - - title : String - + toString() : String - + valueOf(name : String) : Content {static} - + values() : Content[] {static} - } - class ContentAction { - - content : Content - + ContentAction(content : Content) - + getContent() : Content - } - class MenuAction { - - menuItem : MenuItem - + MenuAction(menuItem : MenuItem) - + getMenuItem() : MenuItem - } - enum MenuItem { - + COMPANY {static} - + HOME {static} - + PRODUCTS {static} - - title : String - + toString() : String - + valueOf(name : String) : MenuItem {static} - + values() : MenuItem[] {static} - } -} -package com.iluwatar.flux.app { - class App { - + App() - + main(args : String[]) {static} - } -} -package com.iluwatar.flux.store { - class ContentStore { - - content : Content - + ContentStore() - + getContent() : Content - + onAction(action : Action) - } - class MenuStore { - - selected : MenuItem - + MenuStore() - + getSelected() : MenuItem - + onAction(action : Action) - } - abstract class Store { - - views : List - + Store() - # notifyChange() - + onAction(Action) {abstract} - + registerView(view : View) - } -} -package com.iluwatar.flux.dispatcher { - class Dispatcher { - - instance : Dispatcher {static} - - stores : List - - Dispatcher() - - dispatchAction(action : Action) - + getInstance() : Dispatcher {static} - + menuItemSelected(menuItem : MenuItem) - + registerStore(store : Store) - } -} -MenuAction --> "-menuItem" MenuItem -Action --> "-type" ActionType -Dispatcher --> "-instance" Dispatcher -MenuStore --> "-selected" MenuItem -ContentView --> "-content" Content -Dispatcher --> "-stores" Store -MenuView --> "-selected" MenuItem -Store --> "-views" View -ContentAction --> "-content" Content -ContentStore --> "-content" Content -ContentAction --|> Action -MenuAction --|> Action -ContentStore --|> Store -MenuStore --|> Store -ContentView ..|> View -MenuView ..|> View -@enduml \ No newline at end of file diff --git a/flux/pom.xml b/flux/pom.xml index 01e3c4a90..779bd3e97 100644 --- a/flux/pom.xml +++ b/flux/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT flux diff --git a/flyweight/README.md b/flyweight/README.md index 9a0e13e19..d65995755 100644 --- a/flyweight/README.md +++ b/flyweight/README.md @@ -3,7 +3,6 @@ layout: pattern title: Flyweight folder: flyweight permalink: /patterns/flyweight/ -pumlid: HSV94S8m3030Lg20M7-w4OvYAoCh7Xtnq3ty-Eq-MQlaJcdow17JNm26gpIEdkzqidffa4Qfrm2MN1XeSEADsqxEJRU94MJgCD1_W4C-YxZr08hwNqaRPUQGBm00 categories: Structural tags: - Java diff --git a/flyweight/pom.xml b/flyweight/pom.xml index d93f66681..9814dc2df 100644 --- a/flyweight/pom.xml +++ b/flyweight/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT flyweight diff --git a/front-controller/README.md b/front-controller/README.md index c832674dc..a462a08e0 100644 --- a/front-controller/README.md +++ b/front-controller/README.md @@ -3,7 +3,6 @@ layout: pattern title: Front Controller folder: front-controller permalink: /patterns/front-controller/ -pumlid: PSlB3OGm303HLfO24j-t6nCC13bEvC_IFk6yjz6JPgbIE3OAvS_fFkmBe7Zde_ePQnXfwU8adajlK3bkT5Iuy8Tf8wk7f87kf6BGq6R0hlD8xwQTUG9v-SCSslA8nWy0 categories: Presentation Tier tags: - Java diff --git a/front-controller/etc/front-controller.urm.puml b/front-controller/etc/front-controller.urm.puml deleted file mode 100644 index 246e7657c..000000000 --- a/front-controller/etc/front-controller.urm.puml +++ /dev/null @@ -1,53 +0,0 @@ -@startuml -package com.iluwatar.front.controller { - class App { - + App() - + main(args : String[]) {static} - } - class ArcherCommand { - + ArcherCommand() - + process() - } - class ArcherView { - - LOGGER : Logger {static} - + ArcherView() - + display() - } - class CatapultCommand { - + CatapultCommand() - + process() - } - class CatapultView { - - LOGGER : Logger {static} - + CatapultView() - + display() - } - interface Command { - + process() {abstract} - } - class ErrorView { - - LOGGER : Logger {static} - + ErrorView() - + display() - } - class FrontController { - + FrontController() - - getCommand(request : String) : Command - - getCommandClass(request : String) : Class {static} - + handleRequest(request : String) - } - class UnknownCommand { - + UnknownCommand() - + process() - } - interface View { - + display() {abstract} - } -} -ArcherCommand ..|> Command -ArcherView ..|> View -CatapultCommand ..|> Command -CatapultView ..|> View -ErrorView ..|> View -UnknownCommand ..|> Command -@enduml \ No newline at end of file diff --git a/front-controller/pom.xml b/front-controller/pom.xml index 720f6d2ee..b9080bda7 100644 --- a/front-controller/pom.xml +++ b/front-controller/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT front-controller diff --git a/guarded-suspension/README.md b/guarded-suspension/README.md index 3e00539a2..35044f9b2 100644 --- a/guarded-suspension/README.md +++ b/guarded-suspension/README.md @@ -3,7 +3,6 @@ layout: pattern title: Guarded Suspension folder: guarded-suspension permalink: /patterns/guarded-suspension/ -pumlid: ROux3W8n30LxJW47IDnJxLLCOcMD4YVoXxq-eQTwev56UeSvgiVejmTBwL4fjDzFzsLF0CKhD_OpNc6aPOgJU2vp0FUuSAVmnW-cIiPDqa9tKZ4OQ1kW1MgbcYniaHXF0VBoH-VGaTVlnK5Iztu1 categories: Concurrency tags: - Java diff --git a/guarded-suspension/etc/guarded-suspension.urm.puml b/guarded-suspension/etc/guarded-suspension.urm.puml deleted file mode 100644 index 45a7d3790..000000000 --- a/guarded-suspension/etc/guarded-suspension.urm.puml +++ /dev/null @@ -1,15 +0,0 @@ -@startuml -package com.iluwatar.guarded.suspension { - class App { - + App() - + main(args : String[]) {static} - } - class GuardedQueue { - - LOGGER : Logger {static} - - sourceList : Queue - + GuardedQueue() - + get() : Integer - + put(e : Integer) - } -} -@enduml \ No newline at end of file diff --git a/guarded-suspension/pom.xml b/guarded-suspension/pom.xml index 9b6d70ef8..bcc9ead06 100644 --- a/guarded-suspension/pom.xml +++ b/guarded-suspension/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT jar guarded-suspension diff --git a/half-sync-half-async/README.md b/half-sync-half-async/README.md index 55891e770..8a091f813 100644 --- a/half-sync-half-async/README.md +++ b/half-sync-half-async/README.md @@ -3,7 +3,6 @@ layout: pattern title: Half-Sync/Half-Async folder: half-sync-half-async permalink: /patterns/half-sync-half-async/ -pumlid: RScv3SCm3030LU819FRPXg5fIm552tnYPFiyjRi3RkbAaYkdoQr5JBy369vrxz7oaSv6XmPhL3e6TCaJ0msU-CAoilTToyG8DdKOw5z0GzcAlvNAN_WZSD1brBHHPmxv0000 categories: Concurrency tags: - Java diff --git a/half-sync-half-async/etc/half-sync-half-async.urm.puml b/half-sync-half-async/etc/half-sync-half-async.urm.puml deleted file mode 100644 index 1dd9c1d83..000000000 --- a/half-sync-half-async/etc/half-sync-half-async.urm.puml +++ /dev/null @@ -1,31 +0,0 @@ -@startuml -package com.iluwatar.halfsynchalfasync { - class App { - - LOGGER : Logger {static} - + App() - - ap(i : long) : long {static} - + main(args : String[]) {static} - } - ~class ArithmeticSumTask { - - n : long - + ArithmeticSumTask(n : long) - + call() : Long - + onError(throwable : Throwable) - + onPostCall(result : Long) - + onPreCall() - } - interface AsyncTask { - + call() : O {abstract} - + onError(Throwable) {abstract} - + onPostCall(O) {abstract} - + onPreCall() {abstract} - } - class AsynchronousService { - - service : ExecutorService - + AsynchronousService(workQueue : BlockingQueue) - + execute(task : AsyncTask) - } -} -ArithmeticSumTask ..+ App -ArithmeticSumTask ..|> AsyncTask -@enduml \ No newline at end of file diff --git a/half-sync-half-async/pom.xml b/half-sync-half-async/pom.xml index 16940cefa..ac8464d75 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.17.0-SNAPSHOT + 1.18.0-SNAPSHOT half-sync-half-async diff --git a/hexagonal/README.md b/hexagonal/README.md index dc1566625..7d27f4b62 100644 --- a/hexagonal/README.md +++ b/hexagonal/README.md @@ -3,7 +3,6 @@ layout: pattern title: Hexagonal Architecture folder: hexagonal permalink: /patterns/hexagonal/ -pumlid: HSTB4W8X30N0g-W1XkozpPD90LO8L3wEnzUTk-xxq2fvSfhSUiJs1v7XAcr4psSwMrqQh57gcZGaBmICNdZZEDb7qsCZWasT9lm7wln1MmeXZlfVIPjbvvGl pumlformat: svg categories: Architectural tags: diff --git a/hexagonal/etc/hexagonal.urm.puml b/hexagonal/etc/hexagonal.urm.puml deleted file mode 100644 index 9ca6e6f9f..000000000 --- a/hexagonal/etc/hexagonal.urm.puml +++ /dev/null @@ -1,279 +0,0 @@ -@startuml -package com.iluwatar.hexagonal.sampledata { - class SampleData { - - PLAYERS : List {static} - + SampleData() - - getRandomPlayerDetails() : PlayerDetails {static} - + submitTickets(lotteryService : LotteryService, numTickets : int) {static} - } -} -package com.iluwatar.hexagonal.service { - class ConsoleLottery { - - LOGGER : Logger {static} - + ConsoleLottery() - - addFundsToLotteryAccount(bank : WireTransfers, scanner : Scanner) {static} - - checkTicket(service : LotteryService, scanner : Scanner) {static} - + main(args : String[]) {static} - - printMainMenu() {static} - - queryLotteryAccountFunds(bank : WireTransfers, scanner : Scanner) {static} - - readString(scanner : Scanner) : String {static} - - submitTicket(service : LotteryService, scanner : Scanner) {static} - } -} -package com.iluwatar.hexagonal.mongo { - class MongoConnectionPropertiesLoader { - - DEFAULT_HOST : String {static} - - DEFAULT_PORT : int {static} - + MongoConnectionPropertiesLoader() - + load() {static} - } -} -package com.iluwatar.hexagonal.domain { - class LotteryAdministration { - - notifications : LotteryEventLog - - repository : LotteryTicketRepository - - wireTransfers : WireTransfers - + LotteryAdministration(repository : LotteryTicketRepository, notifications : LotteryEventLog, wireTransfers : WireTransfers) - + getAllSubmittedTickets() : Map - + performLottery() : LotteryNumbers - + resetLottery() - } - class LotteryConstants { - + PLAYER_MAX_SALDO : int {static} - + PRIZE_AMOUNT : int {static} - + SERVICE_BANK_ACCOUNT : String {static} - + SERVICE_BANK_ACCOUNT_SALDO : int {static} - + TICKET_PRIZE : int {static} - - LotteryConstants() - } - class LotteryNumbers { - + MAX_NUMBER : int {static} - + MIN_NUMBER : int {static} - + NUM_NUMBERS : int {static} - - numbers : Set - - LotteryNumbers() - - LotteryNumbers(givenNumbers : Set) - + create(givenNumbers : Set) : LotteryNumbers {static} - + createRandom() : LotteryNumbers {static} - + equals(obj : Object) : boolean - - generateRandomNumbers() - + getNumbers() : Set - + getNumbersAsString() : String - + hashCode() : int - + toString() : String - } - -class RandomNumberGenerator { - - randomIterator : OfInt - + RandomNumberGenerator(min : int, max : int) - + nextInt() : int - } - class LotteryService { - - notifications : LotteryEventLog - - repository : LotteryTicketRepository - - wireTransfers : WireTransfers - + LotteryService(repository : LotteryTicketRepository, notifications : LotteryEventLog, wireTransfers : WireTransfers) - + checkTicketForPrize(id : LotteryTicketId, winningNumbers : LotteryNumbers) : LotteryTicketCheckResult - + submitTicket(ticket : LotteryTicket) : Optional - } - class LotteryTicket { - - id : LotteryTicketId - - lotteryNumbers : LotteryNumbers - - playerDetails : PlayerDetails - + LotteryTicket(id : LotteryTicketId, details : PlayerDetails, numbers : LotteryNumbers) - + equals(obj : Object) : boolean - + getId() : LotteryTicketId - + getNumbers() : LotteryNumbers - + getPlayerDetails() : PlayerDetails - + hashCode() : int - + setId(id : LotteryTicketId) - + toString() : String - } - class LotteryTicketCheckResult { - - checkResult : CheckResult - - prizeAmount : int - + LotteryTicketCheckResult(result : CheckResult) - + LotteryTicketCheckResult(result : CheckResult, amount : int) - + equals(obj : Object) : boolean - + getPrizeAmount() : int - + getResult() : CheckResult - + hashCode() : int - } - enum CheckResult { - + NO_PRIZE {static} - + TICKET_NOT_SUBMITTED {static} - + WIN_PRIZE {static} - + valueOf(name : String) : CheckResult {static} - + values() : CheckResult[] {static} - } - class LotteryTicketId { - - id : int - - numAllocated : int {static} - + LotteryTicketId() - + LotteryTicketId(id : int) - + equals(o : Object) : boolean - + getId() : int - + hashCode() : int - + toString() : String - } - class LotteryUtils { - - LotteryUtils() - + checkTicketForPrize(repository : LotteryTicketRepository, id : LotteryTicketId, winningNumbers : LotteryNumbers) : LotteryTicketCheckResult {static} - } - class PlayerDetails { - - bankAccountNumber : String - - emailAddress : String - - phoneNumber : String - + PlayerDetails(email : String, bankAccount : String, phone : String) - + equals(obj : Object) : boolean - + getBankAccount() : String - + getEmail() : String - + getPhoneNumber() : String - + hashCode() : int - + toString() : String - } -} -package com.iluwatar.hexagonal.banking { - class InMemoryBank { - - accounts : Map {static} - + InMemoryBank() - + getFunds(bankAccount : String) : int - + setFunds(bankAccount : String, amount : int) - + transferFunds(amount : int, sourceBackAccount : String, destinationBankAccount : String) : boolean - } - class MongoBank { - - DEFAULT_ACCOUNTS_COLLECTION : String {static} - - DEFAULT_DB : String {static} - - accountsCollection : MongoCollection - - database : MongoDatabase - - mongoClient : MongoClient - + MongoBank() - + MongoBank(dbName : String, accountsCollectionName : String) - + connect() - + connect(dbName : String, accountsCollectionName : String) - + getAccountsCollection() : MongoCollection - + getFunds(bankAccount : String) : int - + getMongoClient() : MongoClient - + getMongoDatabase() : MongoDatabase - + setFunds(bankAccount : String, amount : int) - + transferFunds(amount : int, sourceBackAccount : String, destinationBankAccount : String) : boolean - } - interface WireTransfers { - + getFunds(String) : int {abstract} - + setFunds(String, int) {abstract} - + transferFunds(int, String, String) : boolean {abstract} - } -} -package com.iluwatar.hexagonal.database { - class InMemoryTicketRepository { - - tickets : Map {static} - + InMemoryTicketRepository() - + deleteAll() - + findAll() : Map - + findById(id : LotteryTicketId) : Optional - + save(ticket : LotteryTicket) : Optional - } - interface LotteryTicketRepository { - + deleteAll() {abstract} - + findAll() : Map {abstract} - + findById(LotteryTicketId) : Optional {abstract} - + save(LotteryTicket) : Optional {abstract} - } - class MongoTicketRepository { - - DEFAULT_COUNTERS_COLLECTION : String {static} - - DEFAULT_DB : String {static} - - DEFAULT_TICKETS_COLLECTION : String {static} - - countersCollection : MongoCollection - - database : MongoDatabase - - mongoClient : MongoClient - - ticketsCollection : MongoCollection - + MongoTicketRepository() - + MongoTicketRepository(dbName : String, ticketsCollectionName : String, countersCollectionName : String) - + connect() - + connect(dbName : String, ticketsCollectionName : String, countersCollectionName : String) - + deleteAll() - - docToTicket(doc : Document) : LotteryTicket - + findAll() : Map - + findById(id : LotteryTicketId) : Optional - + getCountersCollection() : MongoCollection - + getMongoClient() : MongoClient - + getMongoDatabase() : MongoDatabase - + getNextId() : int - + getTicketsCollection() : MongoCollection - - initCounters() - + save(ticket : LotteryTicket) : Optional - } -} -package com.iluwatar.hexagonal { - class App { - + App() - + main(args : String[]) {static} - } -} -package com.iluwatar.hexagonal.administration { - class ConsoleAdministration { - - LOGGER : Logger {static} - + ConsoleAdministration() - + main(args : String[]) {static} - - printMainMenu() {static} - - readString(scanner : Scanner) : String {static} - } -} -package com.iluwatar.hexagonal.eventlog { - interface LotteryEventLog { - + prizeError(PlayerDetails, int) {abstract} - + ticketDidNotWin(PlayerDetails) {abstract} - + ticketSubmitError(PlayerDetails) {abstract} - + ticketSubmitted(PlayerDetails) {abstract} - + ticketWon(PlayerDetails, int) {abstract} - } - class MongoEventLog { - - DEFAULT_DB : String {static} - - DEFAULT_EVENTS_COLLECTION : String {static} - - database : MongoDatabase - - eventsCollection : MongoCollection - - mongoClient : MongoClient - - stdOutEventLog : StdOutEventLog - + MongoEventLog() - + MongoEventLog(dbName : String, eventsCollectionName : String) - + connect() - + connect(dbName : String, eventsCollectionName : String) - + getEventsCollection() : MongoCollection - + getMongoClient() : MongoClient - + getMongoDatabase() : MongoDatabase - + prizeError(details : PlayerDetails, prizeAmount : int) - + ticketDidNotWin(details : PlayerDetails) - + ticketSubmitError(details : PlayerDetails) - + ticketSubmitted(details : PlayerDetails) - + ticketWon(details : PlayerDetails, prizeAmount : int) - } - class StdOutEventLog { - - LOGGER : Logger {static} - + StdOutEventLog() - + prizeError(details : PlayerDetails, prizeAmount : int) - + ticketDidNotWin(details : PlayerDetails) - + ticketSubmitError(details : PlayerDetails) - + ticketSubmitted(details : PlayerDetails) - + ticketWon(details : PlayerDetails, prizeAmount : int) - } -} -LotteryTicket --> "-playerDetails" PlayerDetails -MongoEventLog --> "-stdOutEventLog" StdOutEventLog -LotteryService --> "-wireTransfers" WireTransfers -LotteryAdministration --> "-notifications" LotteryEventLog -LotteryAdministration --> "-wireTransfers" WireTransfers -LotteryService --> "-notifications" LotteryEventLog -LotteryTicket --> "-id" LotteryTicketId -LotteryAdministration --> "-repository" LotteryTicketRepository -LotteryTicket --> "-lotteryNumbers" LotteryNumbers -SampleData --> "-PLAYERS" PlayerDetails -RandomNumberGenerator ..+ LotteryNumbers -LotteryService --> "-repository" LotteryTicketRepository -CheckResult ..+ LotteryTicketCheckResult -LotteryTicketCheckResult --> "-checkResult" CheckResult -InMemoryBank ..|> WireTransfers -MongoBank ..|> WireTransfers -InMemoryTicketRepository ..|> LotteryTicketRepository -MongoTicketRepository ..|> LotteryTicketRepository -MongoEventLog ..|> LotteryEventLog -StdOutEventLog ..|> LotteryEventLog -@enduml \ No newline at end of file diff --git a/hexagonal/pom.xml b/hexagonal/pom.xml index b18127f4b..940a7fc61 100644 --- a/hexagonal/pom.xml +++ b/hexagonal/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT hexagonal diff --git a/intercepting-filter/README.md b/intercepting-filter/README.md index 4981299ad..7d53472a0 100644 --- a/intercepting-filter/README.md +++ b/intercepting-filter/README.md @@ -3,7 +3,6 @@ layout: pattern title: Intercepting Filter folder: intercepting-filter permalink: /patterns/intercepting-filter/ -pumlid: RSfB3i8m303Hgy014k-vZN5DQkIuaJ_q-fGzkz7JtCL8Q-DolUsPAnu0ZcSVadizAzZfi6JBJiS4qJenqU6D7smRXmnh2pFPBM1YN05o_KwyKcoqb-ZFEEcVz_BPLqtz0W00 categories: Behavioral tags: - Java diff --git a/intercepting-filter/etc/intercepting-filter.urm.puml b/intercepting-filter/etc/intercepting-filter.urm.puml deleted file mode 100644 index 74444c2d0..000000000 --- a/intercepting-filter/etc/intercepting-filter.urm.puml +++ /dev/null @@ -1,89 +0,0 @@ -@startuml -left to right direction -package com.iluwatar.intercepting.filter { - abstract class AbstractFilter { - - next : Filter - + AbstractFilter() - + AbstractFilter(next : Filter) - + execute(order : Order) : String - + getLast() : Filter - + getNext() : Filter - + setNext(filter : Filter) - } - class AddressFilter { - + AddressFilter() - + execute(order : Order) : String - } - class App { - + App() - + main(args : String[]) {static} - } - class ContactFilter { - + ContactFilter() - + execute(order : Order) : String - } - class DepositFilter { - + DepositFilter() - + execute(order : Order) : String - } - interface Filter { - + execute(Order) : String {abstract} - + getLast() : Filter {abstract} - + getNext() : Filter {abstract} - + setNext(Filter) {abstract} - } - class FilterChain { - - chain : Filter - + FilterChain() - + addFilter(filter : Filter) - + execute(order : Order) : String - } - class FilterManager { - - filterChain : FilterChain - + FilterManager() - + addFilter(filter : Filter) - + filterRequest(order : Order) : String - } - class NameFilter { - + NameFilter() - + execute(order : Order) : String - } - class Order { - - address : String - - contactNumber : String - - depositNumber : String - - name : String - - order : String - + Order() - + Order(name : String, contactNumber : String, address : String, depositNumber : String, order : String) - + getAddress() : String - + getContactNumber() : String - + getDepositNumber() : String - + getName() : String - + getOrder() : String - + setAddress(address : String) - + setContactNumber(contactNumber : String) - + setDepositNumber(depositNumber : String) - + setName(name : String) - + setOrder(order : String) - } - class OrderFilter { - + OrderFilter() - + execute(order : Order) : String - } - ~class DListener { - ~ DListener() - + actionPerformed(e : ActionEvent) - } -} -AbstractFilter --> "-next" Filter -DListener --+ Target -FilterChain --> "-chain" Filter -FilterManager --> "-filterChain" FilterChain -AbstractFilter ..|> Filter -AddressFilter --|> AbstractFilter -ContactFilter --|> AbstractFilter -DepositFilter --|> AbstractFilter -NameFilter --|> AbstractFilter -OrderFilter --|> AbstractFilter -@enduml diff --git a/intercepting-filter/pom.xml b/intercepting-filter/pom.xml index 91f61489c..40888b7f3 100644 --- a/intercepting-filter/pom.xml +++ b/intercepting-filter/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT intercepting-filter diff --git a/interpreter/README.md b/interpreter/README.md index 8600f0300..be6517962 100644 --- a/interpreter/README.md +++ b/interpreter/README.md @@ -3,7 +3,6 @@ layout: pattern title: Interpreter folder: interpreter permalink: /patterns/interpreter/ -pumlid: JSf13eCm30NHgz034E-vZGaM62Kcih_BzQ6xxjv8yr6hBJT9RzC1Z5Y8dE-oAuvSCyJhPH13gLSdRNapsEdaBy-RXEus3mR4BQXpl21zVnykFmlgVvVqNaRszW00 categories: Behavioral tags: - Java diff --git a/interpreter/etc/interpreter.urm.puml b/interpreter/etc/interpreter.urm.puml deleted file mode 100644 index e1286a2a9..000000000 --- a/interpreter/etc/interpreter.urm.puml +++ /dev/null @@ -1,52 +0,0 @@ -@startuml -left to right direction -package com.iluwatar.interpreter { - class App { - - LOGGER : Logger {static} - + App() - + getOperatorInstance(s : String, left : Expression, right : Expression) : Expression {static} - + isOperator(s : String) : boolean {static} - + main(args : String[]) {static} - } - abstract class Expression { - + Expression() - + interpret() : int {abstract} - + toString() : String {abstract} - } - class MinusExpression { - - leftExpression : Expression - - rightExpression : Expression - + MinusExpression(leftExpression : Expression, rightExpression : Expression) - + interpret() : int - + toString() : String - } - class MultiplyExpression { - - leftExpression : Expression - - rightExpression : Expression - + MultiplyExpression(leftExpression : Expression, rightExpression : Expression) - + interpret() : int - + toString() : String - } - class NumberExpression { - - number : int - + NumberExpression(number : int) - + NumberExpression(s : String) - + interpret() : int - + toString() : String - } - class PlusExpression { - - leftExpression : Expression - - rightExpression : Expression - + PlusExpression(leftExpression : Expression, rightExpression : Expression) - + interpret() : int - + toString() : String - } -} -MultiplyExpression --> "-leftExpression" Expression -MinusExpression --> "-leftExpression" Expression -PlusExpression --> "-leftExpression" Expression -MinusExpression --|> Expression -MultiplyExpression --|> Expression -NumberExpression --|> Expression -PlusExpression --|> Expression -@enduml diff --git a/interpreter/pom.xml b/interpreter/pom.xml index 2fda838ea..8c0ab09a0 100644 --- a/interpreter/pom.xml +++ b/interpreter/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT interpreter diff --git a/iterator/README.md b/iterator/README.md index 61bd8f6f5..723e7f03c 100644 --- a/iterator/README.md +++ b/iterator/README.md @@ -3,7 +3,6 @@ layout: pattern title: Iterator folder: iterator permalink: /patterns/iterator/ -pumlid: FSV13OGm30NHLg00uljsOu85HeaJsTzB-yjfBwCtgrfjUKXwMovWneV8-IcduiezGxmEWnXA7PsqvSDWfvk_l1qIUjes6H2teCxnWlGDOpW9wdzAUYypU_i1 categories: Behavioral tags: - Java diff --git a/iterator/etc/iterator.urm.puml b/iterator/etc/iterator.urm.puml deleted file mode 100644 index 881b9a6d4..000000000 --- a/iterator/etc/iterator.urm.puml +++ /dev/null @@ -1,49 +0,0 @@ -@startuml -package com.iluwatar.iterator { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } - class Item { - - name : String - - type : ItemType - + Item(type : ItemType, name : String) - + getType() : ItemType - + setType(type : ItemType) - + toString() : String - } - interface ItemIterator { - + hasNext() : boolean {abstract} - + next() : Item {abstract} - } - enum ItemType { - + ANY {static} - + POTION {static} - + RING {static} - + WEAPON {static} - + valueOf(name : String) : ItemType {static} - + values() : ItemType[] {static} - } - class TreasureChest { - - items : List - + TreasureChest() - + getItems() : List - ~ iterator(itemType : ItemType) : ItemIterator - } - class TreasureChestItemIterator { - - chest : TreasureChest - - idx : int - - type : ItemType - + TreasureChestItemIterator(chest : TreasureChest, type : ItemType) - - findNextIdx() : int - + hasNext() : boolean - + next() : Item - } -} -Item --> "-type" ItemType -TreasureChest --> "-items" Item -TreasureChestItemIterator --> "-type" ItemType -TreasureChestItemIterator --> "-chest" TreasureChest -TreasureChestItemIterator ..|> ItemIterator -@enduml \ No newline at end of file diff --git a/iterator/pom.xml b/iterator/pom.xml index 5a751db9c..2233e0b32 100644 --- a/iterator/pom.xml +++ b/iterator/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT iterator diff --git a/layers/README.md b/layers/README.md index 62b562938..49b74c175 100644 --- a/layers/README.md +++ b/layers/README.md @@ -3,7 +3,6 @@ layout: pattern title: Layers folder: layers permalink: /patterns/layers/ -pumlid: BSR13OCm30NGLSe0n7UsCS62L8w9x6yGszD3t-bDpQhc9kdwEO0H2v7pNVQ68zSCyNeQn53gsQbftWns-lB5yoRHTfi70-8Mr3b-8UL7F4XG_otflOpi-W80 pumlformat: svg categories: Architectural tags: diff --git a/layers/etc/layers.urm.puml b/layers/etc/layers.urm.puml deleted file mode 100644 index e597c7546..000000000 --- a/layers/etc/layers.urm.puml +++ /dev/null @@ -1,126 +0,0 @@ -@startuml -package com.iluwatar.layers { - class App { - - cakeBakingService : CakeBakingService {static} - + App() - - initializeData(cakeBakingService : CakeBakingService) {static} - + main(args : String[]) {static} - } - class Cake { - - id : Long - - layers : Set - - topping : CakeTopping - + Cake() - + addLayer(layer : CakeLayer) - + getId() : Long - + getLayers() : Set - + getTopping() : CakeTopping - + setId(id : Long) - + setLayers(layers : Set) - + setTopping(topping : CakeTopping) - + toString() : String - } - interface CakeBakingService { - + bakeNewCake(CakeInfo) {abstract} - + getAllCakes() : List {abstract} - + getAvailableLayers() : List {abstract} - + getAvailableToppings() : List {abstract} - + saveNewLayer(CakeLayerInfo) {abstract} - + saveNewTopping(CakeToppingInfo) {abstract} - } - class CakeBakingServiceImpl { - - context : AbstractApplicationContext - + CakeBakingServiceImpl() - + bakeNewCake(cakeInfo : CakeInfo) - + getAllCakes() : List - - getAvailableLayerEntities() : List - + getAvailableLayers() : List - - getAvailableToppingEntities() : List - + getAvailableToppings() : List - + saveNewLayer(layerInfo : CakeLayerInfo) - + saveNewTopping(toppingInfo : CakeToppingInfo) - } - interface CakeDao { - } - class CakeInfo { - + cakeLayerInfos : List - + cakeToppingInfo : CakeToppingInfo - + id : Optional - + CakeInfo(cakeToppingInfo : CakeToppingInfo, cakeLayerInfos : List) - + CakeInfo(id : Long, cakeToppingInfo : CakeToppingInfo, cakeLayerInfos : List) - + calculateTotalCalories() : int - + toString() : String - } - class CakeLayer { - - cake : Cake - - calories : int - - id : Long - - name : String - + CakeLayer() - + CakeLayer(name : String, calories : int) - + getCake() : Cake - + getCalories() : int - + getId() : Long - + getName() : String - + setCake(cake : Cake) - + setCalories(calories : int) - + setId(id : Long) - + setName(name : String) - + toString() : String - } - interface CakeLayerDao { - } - class CakeLayerInfo { - + calories : int - + id : Optional - + name : String - + CakeLayerInfo(id : Long, name : String, calories : int) - + CakeLayerInfo(name : String, calories : int) - + toString() : String - } - class CakeTopping { - - cake : Cake - - calories : int - - id : Long - - name : String - + CakeTopping() - + CakeTopping(name : String, calories : int) - + getCake() : Cake - + getCalories() : int - + getId() : Long - + getName() : String - + setCake(cake : Cake) - + setCalories(calories : int) - + setId(id : Long) - + setName(name : String) - + toString() : String - } - interface CakeToppingDao { - } - class CakeToppingInfo { - + calories : int - + id : Optional - + name : String - + CakeToppingInfo(id : Long, name : String, calories : int) - + CakeToppingInfo(name : String, calories : int) - + toString() : String - } - class CakeViewImpl { - - LOGGER : Logger {static} - - cakeBakingService : CakeBakingService - + CakeViewImpl(cakeBakingService : CakeBakingService) - + render() - } - interface View { - + render() {abstract} - } -} -CakeViewImpl --> "-cakeBakingService" CakeBakingService -CakeInfo --> "-cakeToppingInfo" CakeToppingInfo -CakeInfo --> "-cakeLayerInfos" CakeLayerInfo -App --> "-cakeBakingService" CakeBakingService -CakeLayer --> "-cake" Cake -Cake --> "-topping" CakeTopping -CakeBakingServiceImpl ..|> CakeBakingService -CakeViewImpl ..|> View -@enduml \ No newline at end of file diff --git a/layers/pom.xml b/layers/pom.xml index 084795acd..d15b524de 100644 --- a/layers/pom.xml +++ b/layers/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT com.iluwatar.layers layers diff --git a/lazy-loading/README.md b/lazy-loading/README.md index 4b7a580c3..d40061293 100644 --- a/lazy-loading/README.md +++ b/lazy-loading/README.md @@ -3,7 +3,6 @@ layout: pattern title: Lazy Loading folder: lazy-loading permalink: /patterns/lazy-loading/ -pumlid: LSXB3W8X303Gg-W1e7jlqu66gIc5zED4JwzRTo_lpjeaEwN9xOpO_W0mlEhWEFD89sjBWpHgMnDOyi90WoU-i7Ho7besHf2fmqJ_0GG_xo8BE-i0YlONDMtMdLE- categories: Other tags: - Java diff --git a/lazy-loading/etc/lazy-loading.urm.puml b/lazy-loading/etc/lazy-loading.urm.puml deleted file mode 100644 index aaf49f1df..000000000 --- a/lazy-loading/etc/lazy-loading.urm.puml +++ /dev/null @@ -1,40 +0,0 @@ -@startuml -package com.iluwatar.lazy.loading { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } - class Heavy { - - LOGGER : Logger {static} - + Heavy() - } - class HolderNaive { - - LOGGER : Logger {static} - - heavy : Heavy - + HolderNaive() - + getHeavy() : Heavy - } - class HolderThreadSafe { - - LOGGER : Logger {static} - - heavy : Heavy - + HolderThreadSafe() - + getHeavy() : Heavy - } - class Java8Holder { - - LOGGER : Logger {static} - - heavy : Supplier - + Java8Holder() - - createAndCacheHeavy() : Heavy - + getHeavy() : Heavy - } - ~class HeavyFactory { - - heavyInstance : Heavy - ~ HeavyFactory() - + get() : Heavy - } -} -HolderThreadSafe --> "-heavy" Heavy -HolderNaive --> "-heavy" Heavy -HeavyFactory --> "-heavyInstance" Heavy -@enduml \ No newline at end of file diff --git a/lazy-loading/pom.xml b/lazy-loading/pom.xml index 0e54e6869..9d3652feb 100644 --- a/lazy-loading/pom.xml +++ b/lazy-loading/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT lazy-loading diff --git a/marker/README.md b/marker/README.md index 5bcdf9664..6f5fc1e91 100644 --- a/marker/README.md +++ b/marker/README.md @@ -3,7 +3,7 @@ layout: pattern title: Marker Interface folder: marker permalink: /patterns/marker/ -categories: Design +categories: Other tags: - Java - Difficulty-Beginner diff --git a/marker/etc/marker.urm.puml b/marker/etc/marker.urm.puml deleted file mode 100644 index 02af47ddf..000000000 --- a/marker/etc/marker.urm.puml +++ /dev/null @@ -1,2 +0,0 @@ -@startuml -@enduml \ No newline at end of file diff --git a/marker/pom.xml b/marker/pom.xml index ba68b825b..91cf2c48a 100644 --- a/marker/pom.xml +++ b/marker/pom.xml @@ -24,7 +24,7 @@ java-design-patterns com.iluwatar - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT 4.0.0 diff --git a/mediator/README.md b/mediator/README.md index 084e59256..3452082ef 100644 --- a/mediator/README.md +++ b/mediator/README.md @@ -3,7 +3,6 @@ layout: pattern title: Mediator folder: mediator permalink: /patterns/mediator/ -pumlid: FSV14SCm20J0Lk82BFxf1akCJKOW3JhizfDNVhkRUktP9AE_Bc2kDr7mKqx5bKSkYJeSuYXr66dFXy517xvvRxBqz7qo8E6BZDSFPDAKCO84zP-IOMMczIy0 categories: Behavioral tags: - Java diff --git a/mediator/etc/mediator.urm.puml b/mediator/etc/mediator.urm.puml deleted file mode 100644 index 04e75d2b8..000000000 --- a/mediator/etc/mediator.urm.puml +++ /dev/null @@ -1,69 +0,0 @@ -@startuml -package com.iluwatar.mediator { - enum Action { - + ENEMY {static} - + GOLD {static} - + HUNT {static} - + NONE {static} - + TALE {static} - - description : String - - title : String - + getDescription() : String - + toString() : String - + valueOf(name : String) : Action {static} - + values() : Action[] {static} - } - class App { - + App() - + main(args : String[]) {static} - } - class Hobbit { - + Hobbit() - + toString() : String - } - class Hunter { - + Hunter() - + toString() : String - } - interface Party { - + act(PartyMember, Action) {abstract} - + addMember(PartyMember) {abstract} - } - class PartyImpl { - - members : List - + PartyImpl() - + act(actor : PartyMember, action : Action) - + addMember(member : PartyMember) - } - interface PartyMember { - + act(Action) {abstract} - + joinedParty(Party) {abstract} - + partyAction(Action) {abstract} - } - abstract class PartyMemberBase { - - LOGGER : Logger {static} - # party : Party - + PartyMemberBase() - + act(action : Action) - + joinedParty(party : Party) - + partyAction(action : Action) - + toString() : String {abstract} - } - class Rogue { - + Rogue() - + toString() : String - } - class Wizard { - + Wizard() - + toString() : String - } -} -PartyImpl --> "-members" PartyMember -PartyMemberBase --> "-party" Party -Hobbit --|> PartyMemberBase -Hunter --|> PartyMemberBase -PartyImpl ..|> Party -PartyMemberBase ..|> PartyMember -Rogue --|> PartyMemberBase -Wizard --|> PartyMemberBase -@enduml \ No newline at end of file diff --git a/mediator/pom.xml b/mediator/pom.xml index a15134368..978aa7da6 100644 --- a/mediator/pom.xml +++ b/mediator/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT mediator diff --git a/memento/README.md b/memento/README.md index f43849329..463b5fec0 100644 --- a/memento/README.md +++ b/memento/README.md @@ -3,7 +3,6 @@ layout: pattern title: Memento folder: memento permalink: /patterns/memento/ -pumlid: DSgn4OCm30NGLM00h3xR2AC3SvRiaxx2-g59zugtDgiz3qdlomNC-10vF-Lik7BF4A_388PIXrBh-J3OwUOlRuT4EssR38XRa7Ay81Lz_o11_RkaQvcf_GS0 categories: Behavioral tags: - Java diff --git a/memento/etc/memento.urm.puml b/memento/etc/memento.urm.puml deleted file mode 100644 index 319227ad2..000000000 --- a/memento/etc/memento.urm.puml +++ /dev/null @@ -1,49 +0,0 @@ -@startuml -package com.iluwatar.memento { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } - class Star { - - ageYears : int - - massTons : int - - type : StarType - + Star(startType : StarType, startAge : int, startMass : int) - ~ getMemento() : StarMemento - ~ setMemento(memento : StarMemento) - + timePasses() - + toString() : String - } - -class StarMementoInternal { - - ageYears : int - - massTons : int - - type : StarType - - StarMementoInternal() - + getAgeYears() : int - + getMassTons() : int - + getType() : StarType - + setAgeYears(ageYears : int) - + setMassTons(massTons : int) - + setType(type : StarType) - } - interface StarMemento { - } - enum StarType { - + DEAD {static} - + RED_GIANT {static} - + SUN {static} - + SUPERNOVA {static} - + UNDEFINED {static} - + WHITE_DWARF {static} - - title : String - + toString() : String - + valueOf(name : String) : StarType {static} - + values() : StarType[] {static} - } -} -StarMementoInternal --> "-type" StarType -Star --> "-type" StarType -StarMementoInternal ..+ Star -StarMementoInternal ..|> StarMemento -@enduml \ No newline at end of file diff --git a/memento/pom.xml b/memento/pom.xml index 8d95f32bb..858b75544 100644 --- a/memento/pom.xml +++ b/memento/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT memento diff --git a/message-channel/etc/message-channel.urm.puml b/message-channel/etc/message-channel.urm.puml deleted file mode 100644 index 852f190b4..000000000 --- a/message-channel/etc/message-channel.urm.puml +++ /dev/null @@ -1,9 +0,0 @@ -@startuml -package com.iluwatar.message.channel { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } -} -@enduml \ No newline at end of file diff --git a/message-channel/pom.xml b/message-channel/pom.xml index f73214855..091c35f85 100644 --- a/message-channel/pom.xml +++ b/message-channel/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT message-channel diff --git a/model-view-controller/README.md b/model-view-controller/README.md index 9907b98bd..bc96f7ab1 100644 --- a/model-view-controller/README.md +++ b/model-view-controller/README.md @@ -3,7 +3,6 @@ layout: pattern title: Model-View-Controller folder: model-view-controller permalink: /patterns/model-view-controller/ -pumlid: ROl13SCm201NQGUm-NSRQgE42h258Lw_wR-_qvtkoTOaEwNBuuoOwmNWkEl1SUOx5taR5cHHsr1WoOs13X-yi7HQV5YP645k2nJN3Q2ZavIBQPVVwqFajXJjVwdfMcUgV040 categories: Presentation Tier tags: - Java diff --git a/model-view-controller/etc/model-view-controller.urm.puml b/model-view-controller/etc/model-view-controller.urm.puml deleted file mode 100644 index 92ec1e949..000000000 --- a/model-view-controller/etc/model-view-controller.urm.puml +++ /dev/null @@ -1,70 +0,0 @@ -@startuml -package com.iluwatar.model.view.controller { - class App { - + App() - + main(args : String[]) {static} - } - enum Fatigue { - + ALERT {static} - + SLEEPING {static} - + TIRED {static} - - title : String - + toString() : String - + valueOf(name : String) : Fatigue {static} - + values() : Fatigue[] {static} - } - class GiantController { - - giant : GiantModel - - view : GiantView - + GiantController(giant : GiantModel, view : GiantView) - + getFatigue() : Fatigue - + getHealth() : Health - + getNourishment() : Nourishment - + setFatigue(fatigue : Fatigue) - + setHealth(health : Health) - + setNourishment(nourishment : Nourishment) - + updateView() - } - class GiantModel { - - fatigue : Fatigue - - health : Health - - nourishment : Nourishment - ~ GiantModel(health : Health, fatigue : Fatigue, nourishment : Nourishment) - + getFatigue() : Fatigue - + getHealth() : Health - + getNourishment() : Nourishment - + setFatigue(fatigue : Fatigue) - + setHealth(health : Health) - + setNourishment(nourishment : Nourishment) - + toString() : String - } - class GiantView { - - LOGGER : Logger {static} - + GiantView() - + displayGiant(giant : GiantModel) - } - enum Health { - + DEAD {static} - + HEALTHY {static} - + WOUNDED {static} - - title : String - + toString() : String - + valueOf(name : String) : Health {static} - + values() : Health[] {static} - } - enum Nourishment { - + HUNGRY {static} - + SATURATED {static} - + STARVING {static} - - title : String - + toString() : String - + valueOf(name : String) : Nourishment {static} - + values() : Nourishment[] {static} - } -} -GiantModel --> "-nourishment" Nourishment -GiantController --> "-giant" GiantModel -GiantModel --> "-fatigue" Fatigue -GiantModel --> "-health" Health -GiantController --> "-view" GiantView -@enduml \ No newline at end of file diff --git a/model-view-controller/pom.xml b/model-view-controller/pom.xml index 4aeb69715..385953d0a 100644 --- a/model-view-controller/pom.xml +++ b/model-view-controller/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT model-view-controller diff --git a/model-view-presenter/README.md b/model-view-presenter/README.md index 04a1fa559..a3b921ce4 100644 --- a/model-view-presenter/README.md +++ b/model-view-presenter/README.md @@ -3,7 +3,6 @@ layout: pattern title: Model-View-Presenter folder: model-view-presenter permalink: /patterns/model-view-presenter/ -pumlid: ROlR3SGW3C1MkGu0-RzjKeXQJWcWFChwPO3xispvQBrmL0hbp-q-xGkWkFBL_8upZBICxjGzbo7GE1OwAlpmmLJ9sjNJH7VIRY1e6q169KvFevMcakrtI_BoD-HGoJE4Nm00 categories: Presentation Tier tags: - Java diff --git a/model-view-presenter/etc/model-view-presenter.urm.puml b/model-view-presenter/etc/model-view-presenter.urm.puml deleted file mode 100644 index 188b3fb4d..000000000 --- a/model-view-presenter/etc/model-view-presenter.urm.puml +++ /dev/null @@ -1,87 +0,0 @@ -@startuml -package com.iluwatar.model.view.presenter { - class App { - + App() - + main(args : String[]) {static} - } - class FileLoader { - - fileName : String - - loaded : boolean - + FileLoader() - + fileExists() : boolean - + getFileName() : String - + isLoaded() : boolean - + loadData() : String - + setFileName(fileName : String) - } - class FileSelectorJFrame { - - area : JTextArea - - cancel : JButton - - contents : JLabel - - fileName : String - - info : JLabel - - input : JTextField - - ok : JButton - - panel : JPanel - - presenter : FileSelectorPresenter - - serialVersionUID : long {static} - + FileSelectorJFrame() - + actionPerformed(e : ActionEvent) - + close() - + displayData(data : String) - + getFileName() : String - + getPresenter() : FileSelectorPresenter - + isOpened() : boolean - + open() - + setFileName(name : String) - + setPresenter(presenter : FileSelectorPresenter) - + showMessage(message : String) - } - class FileSelectorPresenter { - - loader : FileLoader - - view : FileSelectorView - + FileSelectorPresenter(view : FileSelectorView) - + cancelled() - + confirmed() - + fileNameChanged() - + setLoader(loader : FileLoader) - + start() - } - class FileSelectorStub { - - dataDisplayed : boolean - - name : String - - numOfMessageSent : int - - opened : boolean - - presenter : FileSelectorPresenter - + FileSelectorStub() - + close() - + dataDisplayed() : boolean - + displayData(data : String) - + getFileName() : String - + getMessagesSent() : int - + getPresenter() : FileSelectorPresenter - + isOpened() : boolean - + open() - + setFileName(name : String) - + setPresenter(presenter : FileSelectorPresenter) - + showMessage(message : String) - } - interface FileSelectorView { - + close() {abstract} - + displayData(String) {abstract} - + getFileName() : String {abstract} - + getPresenter() : FileSelectorPresenter {abstract} - + isOpened() : boolean {abstract} - + open() {abstract} - + setFileName(String) {abstract} - + setPresenter(FileSelectorPresenter) {abstract} - + showMessage(String) {abstract} - } -} -FileSelectorStub --> "-presenter" FileSelectorPresenter -FileSelectorJFrame --> "-presenter" FileSelectorPresenter -FileSelectorPresenter --> "-loader" FileLoader -FileSelectorPresenter --> "-view" FileSelectorView -FileSelectorJFrame ..|> FileSelectorView -FileSelectorStub ..|> FileSelectorView -@enduml \ No newline at end of file diff --git a/model-view-presenter/pom.xml b/model-view-presenter/pom.xml index ec6f570ee..5c91846bf 100644 --- a/model-view-presenter/pom.xml +++ b/model-view-presenter/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT model-view-presenter model-view-presenter 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 f5606e638..5952cf5f1 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 @@ -36,7 +36,7 @@ import org.slf4j.LoggerFactory; *

* It is responsible for reading and loading the contents of a given file. */ -public class FileLoader implements Serializable{ +public class FileLoader implements Serializable { /** * Generated serial version UID 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 560a8d274..233b1dcf7 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 @@ -30,7 +30,7 @@ import java.io.Serializable; *

* It is responsible for reacting to the user's actions and update the View component. */ -public class FileSelectorPresenter implements Serializable{ +public class FileSelectorPresenter implements Serializable { /** * Generated serial version UID 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 5272ea0b7..e6ab93f66 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 @@ -28,7 +28,7 @@ import java.io.Serializable; * This interface represents the View component in the Model-View-Presenter pattern. It can be * implemented by either the GUI components, or by the Stub. */ -public interface FileSelectorView extends Serializable{ +public interface FileSelectorView extends Serializable { /** * Opens the view. diff --git a/module/README.md b/module/README.md index 24bd3f543..39f4dbffd 100644 --- a/module/README.md +++ b/module/README.md @@ -3,7 +3,6 @@ layout: pattern title: Module folder: module permalink: /patterns/module/ -pumlid: JShB3OGm303HLg20nFVjnYGM1CN6ycTfVtFSsnjfzY5jPgUqkLqHwXy0mxUU8wuyqidQ8q4IjJqCO-QBWGOtVh5qyd5AKOmW4mT6Nu2-ZiAekapH_hkcSTNa-GC0 categories: Creational Pattern tags: - Java diff --git a/module/etc/module.urm.puml b/module/etc/module.urm.puml deleted file mode 100644 index 233691cf7..000000000 --- a/module/etc/module.urm.puml +++ /dev/null @@ -1,43 +0,0 @@ -@startuml -package com.iluwatar.module { - class App { - + consoleLoggerModule : ConsoleLoggerModule {static} - + fileLoggerModule : FileLoggerModule {static} - - App() - + execute(args : String[]) {static} - + main(args : String[]) {static} - + prepare() {static} - + unprepare() {static} - } - class ConsoleLoggerModule { - - LOGGER : Logger {static} - + error : PrintStream - + output : PrintStream - - singleton : ConsoleLoggerModule {static} - - ConsoleLoggerModule() - + getSingleton() : ConsoleLoggerModule {static} - + prepare() : ConsoleLoggerModule - + printErrorString(value : String) - + printString(value : String) - + unprepare() - } - class FileLoggerModule { - - ERROR_FILE : String {static} - - LOGGER : Logger {static} - - OUTPUT_FILE : String {static} - + error : PrintStream - + output : PrintStream - - singleton : FileLoggerModule {static} - - FileLoggerModule() - + getSingleton() : FileLoggerModule {static} - + prepare() : FileLoggerModule - + printErrorString(value : String) - + printString(value : String) - + unprepare() - } -} -FileLoggerModule --> "-singleton" FileLoggerModule -App --> "-consoleLoggerModule" ConsoleLoggerModule -ConsoleLoggerModule --> "-singleton" ConsoleLoggerModule -App --> "-fileLoggerModule" FileLoggerModule -@enduml \ No newline at end of file diff --git a/module/pom.xml b/module/pom.xml index b86069b16..1d45a77a5 100644 --- a/module/pom.xml +++ b/module/pom.xml @@ -28,7 +28,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT module diff --git a/monad/README.md b/monad/README.md index bf6ee58b8..41edd3d92 100644 --- a/monad/README.md +++ b/monad/README.md @@ -3,7 +3,6 @@ layout: pattern title: Monad folder: monad permalink: /patterns/monad/ -pumlid: 9SR13SCm20NGLPe1OkxTXjWeSMMm1Pza_LRgExsjMntP97syBc35cyZvAMV7bKU6U9q6CPGwbVh8Xy5E7xvvRnBzj7qn86v1ol4BwJHk9AZ_bNGjAtLy0G00 categories: Other tags: - Java diff --git a/monad/etc/monad.urm.puml b/monad/etc/monad.urm.puml deleted file mode 100644 index c9dcc8db6..000000000 --- a/monad/etc/monad.urm.puml +++ /dev/null @@ -1,36 +0,0 @@ -@startuml -package com.iluwatar.monad { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } - enum Sex { - + FEMALE {static} - + MALE {static} - + valueOf(name : String) : Sex {static} - + values() : Sex[] {static} - } - class User { - - age : int - - email : String - - name : String - - sex : Sex - + User(name : String, age : int, sex : Sex, email : String) - + getAge() : int - + getEmail() : String - + getName() : String - + getSex() : Sex - } - class Validator { - - exceptions : List - - t : T - - Validator(t : T) - + get() : T - + of(t : T) : Validator {static} - + validate(projection : Function, validation : Predicate, message : String) : Validator - + validate(validation : Predicate, message : String) : Validator - } -} -User --> "-sex" Sex -@enduml \ No newline at end of file diff --git a/monad/pom.xml b/monad/pom.xml index 23d5e0c0e..26cb21b97 100644 --- a/monad/pom.xml +++ b/monad/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT monad diff --git a/monostate/README.md b/monostate/README.md index 8c47b5da4..3576dc659 100644 --- a/monostate/README.md +++ b/monostate/README.md @@ -3,7 +3,6 @@ layout: pattern title: MonoState folder: monostate permalink: /patterns/monostate/ -pumlid: HSV14OGm20NGLjO23FVj1YEZsGaa0nzjVxrvUszfLdlkaju_9p3ZI-HybwFXp2r3l0w364eTIgtdpM2d7r-yxXBji7Ko86v1ol60TDW8C8G4zLr9rp9J-ny0 categories: Creational tags: - Java diff --git a/monostate/etc/monostate.urm.puml b/monostate/etc/monostate.urm.puml deleted file mode 100644 index b7797d5e4..000000000 --- a/monostate/etc/monostate.urm.puml +++ /dev/null @@ -1,33 +0,0 @@ -@startuml -package com.iluwatar.monostate { - class App { - + App() - + main(args : String[]) {static} - } - class LoadBalancer { - - id : int {static} - - lastServedId : int {static} - - servers : List {static} - + LoadBalancer() - + addServer(server : Server) - + getLastServedId() : int {static} - + getNoOfServers() : int - + serverRequest(request : Request) - } - class Request { - + value : String - + Request(value : String) - } - class Server { - - LOGGER : Logger {static} - + host : String - + id : int - + port : int - + Server(host : String, port : int, id : int) - + getHost() : String - + getPort() : int - + serve(request : Request) - } -} -LoadBalancer --> "-servers" Server -@enduml \ No newline at end of file diff --git a/monostate/pom.xml b/monostate/pom.xml index 5343d2094..c4dc213da 100644 --- a/monostate/pom.xml +++ b/monostate/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT monostate diff --git a/monostate/src/main/java/com/iluwatar/monostate/LoadBalancer.java b/monostate/src/main/java/com/iluwatar/monostate/LoadBalancer.java index e440dfba2..b280de767 100644 --- a/monostate/src/main/java/com/iluwatar/monostate/LoadBalancer.java +++ b/monostate/src/main/java/com/iluwatar/monostate/LoadBalancer.java @@ -35,10 +35,10 @@ import java.util.List; public class LoadBalancer { private static List servers = new ArrayList<>(); - private static int id; private static int lastServedId; static { + int id = 0; servers.add(new Server("localhost", 8081, ++id)); servers.add(new Server("localhost", 8080, ++id)); servers.add(new Server("localhost", 8082, ++id)); @@ -67,14 +67,12 @@ public class LoadBalancer { /** * Handle request */ - public void serverRequest(Request request) { + public synchronized void serverRequest(Request request) { if (lastServedId >= servers.size()) { lastServedId = 0; } Server server = servers.get(lastServedId++); server.serve(request); } - - - + } diff --git a/multiton/README.md b/multiton/README.md index a1154e7bb..0462ff0ec 100644 --- a/multiton/README.md +++ b/multiton/README.md @@ -3,7 +3,6 @@ layout: pattern title: Multiton folder: multiton permalink: /patterns/multiton/ -pumlid: FST14i8m20NGg-W16lRUXgPCYnD81Zxs-hfozzvJlOywf68yBc3bYoZuRgVYghrIea-7E5gVHZhgPd3Gcp-y7P9w-hOOaF0au_o1h0OKqqdG_saLrbRP-080 categories: Creational tags: - Java diff --git a/multiton/etc/multiton.urm.puml b/multiton/etc/multiton.urm.puml deleted file mode 100644 index 63a74b1f1..000000000 --- a/multiton/etc/multiton.urm.puml +++ /dev/null @@ -1,30 +0,0 @@ -@startuml -package com.iluwatar.multiton { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } - class Nazgul { - - name : NazgulName - - nazguls : Map {static} - - Nazgul(name : NazgulName) - + getInstance(name : NazgulName) : Nazgul {static} - + getName() : NazgulName - } - enum NazgulName { - + ADUNAPHEL {static} - + AKHORAHIL {static} - + DWAR {static} - + HOARMURATH {static} - + JI_INDUR {static} - + KHAMUL {static} - + MURAZOR {static} - + REN {static} - + UVATHA {static} - + valueOf(name : String) : NazgulName {static} - + values() : NazgulName[] {static} - } -} -Nazgul --> "-name" NazgulName -@enduml \ No newline at end of file diff --git a/multiton/pom.xml b/multiton/pom.xml index 2e5553588..af75e5ebe 100644 --- a/multiton/pom.xml +++ b/multiton/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT multiton diff --git a/mute-idiom/README.md b/mute-idiom/README.md index 5c3dbf10b..bb674b648 100644 --- a/mute-idiom/README.md +++ b/mute-idiom/README.md @@ -3,7 +3,6 @@ layout: pattern title: Mute Idiom folder: mute-idiom permalink: /patterns/mute-idiom/ -pumlid: JSf13iCm20NHgxG7iDdtDjH62PKX5luarq-MtSsJvgtUHdR96AyTcEj357pLJR7dDvT4EnpYgEqmqf4NWuD-V7BfidJpCXcGy4N6wmcoX1Jj-lo2ziUQONMcZHi0 categories: Other tags: - Java diff --git a/mute-idiom/etc/mute-idiom.urm.puml b/mute-idiom/etc/mute-idiom.urm.puml deleted file mode 100644 index 32d036bc8..000000000 --- a/mute-idiom/etc/mute-idiom.urm.puml +++ /dev/null @@ -1,24 +0,0 @@ -@startuml -package com.iluwatar.mute { - class App { - - LOGGER : Logger {static} - + App() - - acquireResource() : Resource {static} - - closeResource(resource : Resource) {static} - + main(args : String[]) {static} - - useOfLoggedMute() {static} - - useOfMute() {static} - - utilizeResource(resource : Resource) {static} - } - interface CheckedRunnable { - + run() {abstract} - } - class Mute { - - Mute() - + loggedMute(runnable : CheckedRunnable) {static} - + mute(runnable : CheckedRunnable) {static} - } - interface Resource { - } -} -@enduml \ No newline at end of file diff --git a/mute-idiom/pom.xml b/mute-idiom/pom.xml index 92b36915d..41d660c73 100644 --- a/mute-idiom/pom.xml +++ b/mute-idiom/pom.xml @@ -21,7 +21,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT mute-idiom diff --git a/mutex/README.md b/mutex/README.md index 78cda9060..84755872f 100644 --- a/mutex/README.md +++ b/mutex/README.md @@ -3,7 +3,6 @@ layout: pattern title: Mutex folder: mutex permalink: /patterns/mutex/ -pumlid: 9SR13OCm30NGLSe0n7UsCS62LB69x6zWV2hrdTxKhFRS9Br_3c34GkHybxtXo3L3l9u6CPHwAhMUDuETldpnl4cqtUR1WBW5ASSlf0bvI53_A-bQHcf_0G00 categories: Concurrency tags: - Java diff --git a/mutex/etc/mutex.urm.puml b/mutex/etc/mutex.urm.puml deleted file mode 100644 index 08cf43b90..000000000 --- a/mutex/etc/mutex.urm.puml +++ /dev/null @@ -1,27 +0,0 @@ -@startuml -package com.iluwatar.mutex { - class App { - + App() - + main(args : String[]) {static} - } - class Jar { - - beans : int - - lock : Lock - + Jar(beans : int, lock : Lock) - + takeBean() : boolean - } - interface Lock { - + acquire() {abstract} - + release() {abstract} - } - class Mutex { - - owner : Object - + Mutex() - + acquire() - + getOwner() : Object - + release() - } -} -Jar --> "-lock" Lock -Mutex ..|> Lock -@enduml \ No newline at end of file diff --git a/mutex/pom.xml b/mutex/pom.xml index 6ba6c74a3..ff938604b 100644 --- a/mutex/pom.xml +++ b/mutex/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT mutex diff --git a/mutex/src/test/java/com/iluwatar/mutex/AppTest.java b/mutex/src/test/java/com/iluwatar/mutex/AppTest.java index f224a56f5..530db835d 100644 --- a/mutex/src/test/java/com/iluwatar/mutex/AppTest.java +++ b/mutex/src/test/java/com/iluwatar/mutex/AppTest.java @@ -28,7 +28,7 @@ import java.io.IOException; /** * Application Test Entrypoint */ -public class AppTest{ +public class AppTest { @Test public void test() throws IOException { String[] args = {}; diff --git a/naked-objects/README.md b/naked-objects/README.md index 66e6ac2b0..eb1c083b1 100644 --- a/naked-objects/README.md +++ b/naked-objects/README.md @@ -29,4 +29,4 @@ Use the Naked Objects pattern when ## Credits -* [Richard Pawson - Naked Objects](https://isis.apache.org/resources/thesis/Pawson-Naked-Objects-thesis.pdf) +* [Richard Pawson - Naked Objects](http://downloads.nakedobjects.net/resources/Pawson%20thesis.pdf) diff --git a/naked-objects/dom/pom.xml b/naked-objects/dom/pom.xml index f26060fbf..5a6f4e7ba 100644 --- a/naked-objects/dom/pom.xml +++ b/naked-objects/dom/pom.xml @@ -16,7 +16,7 @@ com.iluwatar naked-objects - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT naked-objects-dom diff --git a/naked-objects/etc/naked-objects-dom.urm.puml b/naked-objects/etc/naked-objects-dom.urm.puml deleted file mode 100644 index 462364099..000000000 --- a/naked-objects/etc/naked-objects-dom.urm.puml +++ /dev/null @@ -1,39 +0,0 @@ -@startuml -package domainapp.dom.app.homepage { - class HomePageService { - ~ container : DomainObjectContainer - + HomePageService() - + homePage() : HomePageViewModel - } - class HomePageViewModel { - ~ simpleObjects : SimpleObjects - + HomePageViewModel() - + getObjects() : List - + title() : String - } -} -package domainapp.dom.modules.simple { - class SimpleObject { - - container : DomainObjectContainer - - name : String - + SimpleObject() - + compareTo(other : SimpleObject) : int - + default0UpdateName() : String - + getName() : String - + getVersionSequence() : Long - + setName(name : String) - + title() : TranslatableString - + updateName(name : String) : SimpleObject - + validateUpdateName(name : String) : TranslatableString - } - class SimpleObjects { - ~ container : DomainObjectContainer - + SimpleObjects() - + create(name : String) : SimpleObject - + findByName(name : String) : List - + listAll() : List - + title() : TranslatableString - } -} -HomePageViewModel --> "-simpleObjects" SimpleObjects -@enduml \ No newline at end of file diff --git a/naked-objects/etc/naked-objects-fixture.urm.puml b/naked-objects/etc/naked-objects-fixture.urm.puml deleted file mode 100644 index 04b3b1350..000000000 --- a/naked-objects/etc/naked-objects-fixture.urm.puml +++ /dev/null @@ -1,93 +0,0 @@ -@startuml -package domainapp.dom.app.homepage { - class HomePageService { - ~ container : DomainObjectContainer - + HomePageService() - + homePage() : HomePageViewModel - } - class HomePageViewModel { - ~ simpleObjects : SimpleObjects - + HomePageViewModel() - + getObjects() : List - + title() : String - } -} -package domainapp.dom.modules.simple { - class SimpleObject { - - container : DomainObjectContainer - - dnFieldFlags : byte[] {static} - - dnFieldNames : String[] {static} - - dnFieldTypes : Class[] {static} - # dnFlags : byte - - dnInheritedFieldCount : int {static} - - dnPersistableSuperclass : Class {static} - # dnStateManager : StateManager - - name : String - + SimpleObject() - + ___dn$loadClass(className : String) : Class {static} - - __dnFieldFlagsInit() : byte[] {static} - - __dnFieldNamesInit() : String[] {static} - - __dnFieldTypesInit() : Class[] {static} - # __dnGetInheritedFieldCount() : int {static} - - __dnPersistableSuperclassInit() : Class {static} - + compareTo(other : SimpleObject) : int - + default0UpdateName() : String - # dnCopyField(obj : SimpleObject, index : int) - + dnCopyFields(obj : Object, indices : int[]) - + dnCopyKeyFieldsFromObjectId(fc : ObjectIdFieldConsumer, oid : Object) - # dnCopyKeyFieldsFromObjectId(oid : Object) - + dnCopyKeyFieldsToObjectId(fs : ObjectIdFieldSupplier, oid : Object) - + dnCopyKeyFieldsToObjectId(oid : Object) - + dnGetExecutionContext() : ExecutionContextReference - # dnGetManagedFieldCount() : int {static} - + dnGetObjectId() : Object - + dnGetTransactionalObjectId() : Object - + dnGetVersion() : Object - + dnGetname() : String - + dnIsDeleted() : boolean - + dnIsDetached() : boolean - + dnIsDirty() : boolean - + dnIsNew() : boolean - + dnIsPersistent() : boolean - + dnIsTransactional() : boolean - + dnMakeDirty(fieldName : String) - + dnNewInstance(sm : StateManager) : Persistable - + dnNewInstance(sm : StateManager, obj : Object) : Persistable - + dnNewObjectIdInstance() : Object - + dnNewObjectIdInstance(key : Object) : Object - # dnPreSerialize() - + dnProvideField(index : int) - + dnProvideFields(indices : int[]) - + dnReplaceField(index : int) - + dnReplaceFields(indices : int[]) - + dnReplaceFlags() - + dnReplaceStateManager(sm : StateManager) - + dnSetname(name : String) - - dnSuperClone() : Object - + getName() : String - + getVersionSequence() : Long - + setName(val : String) - + title() : TranslatableString - + updateName(name : String) : SimpleObject - + validateUpdateName(name : String) : TranslatableString - } - class SimpleObjects { - ~ container : DomainObjectContainer - + SimpleObjects() - + create(name : String) : SimpleObject - + findByName(name : String) : List - + listAll() : List - + title() : TranslatableString - } -} -package domainapp.fixture { - class DomainAppFixturesProvider { - + DomainAppFixturesProvider() - + getSpecification() : FixtureScriptsSpecification - } -} -Builder ..+ FixtureScriptsSpecification -DropDownPolicy ..+ FixtureScriptsSpecification -MultipleExecutionStrategy ..+ FixtureScripts -HomePageViewModel --> "-simpleObjects" SimpleObjects -@enduml \ No newline at end of file diff --git a/naked-objects/etc/naked-objects-integtests.urm.puml b/naked-objects/etc/naked-objects-integtests.urm.puml deleted file mode 100644 index 04b3b1350..000000000 --- a/naked-objects/etc/naked-objects-integtests.urm.puml +++ /dev/null @@ -1,93 +0,0 @@ -@startuml -package domainapp.dom.app.homepage { - class HomePageService { - ~ container : DomainObjectContainer - + HomePageService() - + homePage() : HomePageViewModel - } - class HomePageViewModel { - ~ simpleObjects : SimpleObjects - + HomePageViewModel() - + getObjects() : List - + title() : String - } -} -package domainapp.dom.modules.simple { - class SimpleObject { - - container : DomainObjectContainer - - dnFieldFlags : byte[] {static} - - dnFieldNames : String[] {static} - - dnFieldTypes : Class[] {static} - # dnFlags : byte - - dnInheritedFieldCount : int {static} - - dnPersistableSuperclass : Class {static} - # dnStateManager : StateManager - - name : String - + SimpleObject() - + ___dn$loadClass(className : String) : Class {static} - - __dnFieldFlagsInit() : byte[] {static} - - __dnFieldNamesInit() : String[] {static} - - __dnFieldTypesInit() : Class[] {static} - # __dnGetInheritedFieldCount() : int {static} - - __dnPersistableSuperclassInit() : Class {static} - + compareTo(other : SimpleObject) : int - + default0UpdateName() : String - # dnCopyField(obj : SimpleObject, index : int) - + dnCopyFields(obj : Object, indices : int[]) - + dnCopyKeyFieldsFromObjectId(fc : ObjectIdFieldConsumer, oid : Object) - # dnCopyKeyFieldsFromObjectId(oid : Object) - + dnCopyKeyFieldsToObjectId(fs : ObjectIdFieldSupplier, oid : Object) - + dnCopyKeyFieldsToObjectId(oid : Object) - + dnGetExecutionContext() : ExecutionContextReference - # dnGetManagedFieldCount() : int {static} - + dnGetObjectId() : Object - + dnGetTransactionalObjectId() : Object - + dnGetVersion() : Object - + dnGetname() : String - + dnIsDeleted() : boolean - + dnIsDetached() : boolean - + dnIsDirty() : boolean - + dnIsNew() : boolean - + dnIsPersistent() : boolean - + dnIsTransactional() : boolean - + dnMakeDirty(fieldName : String) - + dnNewInstance(sm : StateManager) : Persistable - + dnNewInstance(sm : StateManager, obj : Object) : Persistable - + dnNewObjectIdInstance() : Object - + dnNewObjectIdInstance(key : Object) : Object - # dnPreSerialize() - + dnProvideField(index : int) - + dnProvideFields(indices : int[]) - + dnReplaceField(index : int) - + dnReplaceFields(indices : int[]) - + dnReplaceFlags() - + dnReplaceStateManager(sm : StateManager) - + dnSetname(name : String) - - dnSuperClone() : Object - + getName() : String - + getVersionSequence() : Long - + setName(val : String) - + title() : TranslatableString - + updateName(name : String) : SimpleObject - + validateUpdateName(name : String) : TranslatableString - } - class SimpleObjects { - ~ container : DomainObjectContainer - + SimpleObjects() - + create(name : String) : SimpleObject - + findByName(name : String) : List - + listAll() : List - + title() : TranslatableString - } -} -package domainapp.fixture { - class DomainAppFixturesProvider { - + DomainAppFixturesProvider() - + getSpecification() : FixtureScriptsSpecification - } -} -Builder ..+ FixtureScriptsSpecification -DropDownPolicy ..+ FixtureScriptsSpecification -MultipleExecutionStrategy ..+ FixtureScripts -HomePageViewModel --> "-simpleObjects" SimpleObjects -@enduml \ No newline at end of file diff --git a/naked-objects/fixture/pom.xml b/naked-objects/fixture/pom.xml index 0fccbaf56..88c982dfd 100644 --- a/naked-objects/fixture/pom.xml +++ b/naked-objects/fixture/pom.xml @@ -16,7 +16,7 @@ com.iluwatar naked-objects - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT naked-objects-fixture diff --git a/naked-objects/integtests/pom.xml b/naked-objects/integtests/pom.xml index ba620c5be..e4006561a 100644 --- a/naked-objects/integtests/pom.xml +++ b/naked-objects/integtests/pom.xml @@ -16,7 +16,7 @@ com.iluwatar naked-objects - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT naked-objects-integtests diff --git a/naked-objects/pom.xml b/naked-objects/pom.xml index 4dee87660..3d89e5af1 100644 --- a/naked-objects/pom.xml +++ b/naked-objects/pom.xml @@ -15,7 +15,7 @@ java-design-patterns com.iluwatar - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT naked-objects @@ -317,23 +317,6 @@ org.apache.maven.plugins maven-surefire-report-plugin - - com.github.markusmo3.urm - urm-maven-plugin - ${urm.version} - - ${project.basedir}/../etc - - com.iluwatar - domainapp - - - - naked-objects - naked-objects-webapp - - - @@ -367,17 +350,17 @@ ${project.groupId} naked-objects-dom - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT ${project.groupId} naked-objects-fixture - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT ${project.groupId} naked-objects-webapp - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT diff --git a/naked-objects/webapp/pom.xml b/naked-objects/webapp/pom.xml index d318da81d..244d1737d 100644 --- a/naked-objects/webapp/pom.xml +++ b/naked-objects/webapp/pom.xml @@ -16,7 +16,7 @@ com.iluwatar naked-objects - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT naked-objects-webapp diff --git a/null-object/README.md b/null-object/README.md index bfaaeac66..0ed28a0af 100644 --- a/null-object/README.md +++ b/null-object/README.md @@ -3,7 +3,6 @@ layout: pattern title: Null Object folder: null-object permalink: /patterns/null-object/ -pumlid: JSV14SCm20J0Lk829Fxf1cF6bWSX3JhYzfDdVhjRSx4yDCDU5p3NcoZugMV3bNik3HaETLGPdPhbm-2WcpzS3btjz38PqF15dTSFv6bMndwhW1Jo_vhHwynkNm00 categories: Behavioral tags: - Java diff --git a/null-object/etc/null-object.urm.puml b/null-object/etc/null-object.urm.puml deleted file mode 100644 index a937a2b17..000000000 --- a/null-object/etc/null-object.urm.puml +++ /dev/null @@ -1,41 +0,0 @@ -@startuml -package com.iluwatar.nullobject { - class App { - + App() - + main(args : String[]) {static} - } - interface Node { - + getLeft() : Node {abstract} - + getName() : String {abstract} - + getRight() : Node {abstract} - + getTreeSize() : int {abstract} - + walk() {abstract} - } - class NodeImpl { - - LOGGER : Logger {static} - - left : Node - - name : String - - right : Node - + NodeImpl(name : String, left : Node, right : Node) - + getLeft() : Node - + getName() : String - + getRight() : Node - + getTreeSize() : int - + walk() - } - class NullNode { - - instance : NullNode {static} - - NullNode() - + getInstance() : NullNode {static} - + getLeft() : Node - + getName() : String - + getRight() : Node - + getTreeSize() : int - + walk() - } -} -NullNode --> "-instance" NullNode -NodeImpl --> "-left" Node -NodeImpl ..|> Node -NullNode ..|> Node -@enduml \ No newline at end of file diff --git a/null-object/pom.xml b/null-object/pom.xml index 0d4248dbc..755db259e 100644 --- a/null-object/pom.xml +++ b/null-object/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT null-object diff --git a/object-mother/README.md b/object-mother/README.md index cda3336cf..125ecdfe5 100644 --- a/object-mother/README.md +++ b/object-mother/README.md @@ -3,7 +3,6 @@ layout: pattern title: Object Mother folder: object-mother permalink: /patterns/object-mother/ -pumlid: LOr13iCW30JlVKNx0E3UKxxYW9KGWK7sklb-wR6dtLbfj9k15DxRurKbDo_isfudCEsTaj8TZuhJTpVMF0GiY7dqL9lVjDHqqOT2OQk7X4a0grZgPAkaiL-S4Vh0kOYH_vVeskFyVMyiPUKN categories: Creational tags: - Java diff --git a/object-mother/etc/object-mother.urm.puml b/object-mother/etc/object-mother.urm.puml deleted file mode 100644 index 1bb52f2ed..000000000 --- a/object-mother/etc/object-mother.urm.puml +++ /dev/null @@ -1,45 +0,0 @@ -@startuml -package com.iluwatar.objectmother { - class King { - ~ isDrunk : boolean - ~ isHappy : boolean - + King() - + flirt(queen : Queen) - + isHappy() : boolean - + makeDrunk() - + makeHappy() - + makeSober() - + makeUnhappy() - } - class Queen { - - isDrunk : boolean - - isFlirty : boolean - - isHappy : boolean - + Queen() - + getFlirted(king : King) : boolean - + isFlirty() : boolean - + makeDrunk() - + makeHappy() - + makeSober() - + makeUnhappy() - + setFlirtiness(flirtiness : boolean) - } - interface Royalty { - + makeDrunk() {abstract} - + makeHappy() {abstract} - + makeSober() {abstract} - + makeUnhappy() {abstract} - } - class RoyaltyObjectMother { - + RoyaltyObjectMother() - + createDrunkKing() : King {static} - + createFlirtyQueen() : Queen {static} - + createHappyDrunkKing() : King {static} - + createHappyKing() : King {static} - + createNotFlirtyQueen() : Queen {static} - + createSoberUnhappyKing() : King {static} - } -} -King ..|> Royalty -Queen ..|> Royalty -@enduml \ No newline at end of file diff --git a/object-mother/pom.xml b/object-mother/pom.xml index 7b598ed9a..9b9171888 100644 --- a/object-mother/pom.xml +++ b/object-mother/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT object-mother diff --git a/object-pool/README.md b/object-pool/README.md index 15fee51aa..cf36d9880 100644 --- a/object-pool/README.md +++ b/object-pool/README.md @@ -3,7 +3,6 @@ layout: pattern title: Object Pool folder: object-pool permalink: /patterns/object-pool/ -pumlid: JSV94SCm2030Lk829Fxf1cF6bWU1XYDkFtdcjxiD9Qc3o-LrPQvu0pW-_HnvrLx1JgR9cfrimf1wCD7XnW-sWsESsXPcicl0nFW1RB-PiYqp0KxwVo-VVTMKBm00 categories: Creational tags: - Java diff --git a/object-pool/etc/object-pool.urm.puml b/object-pool/etc/object-pool.urm.puml deleted file mode 100644 index ca74f8cec..000000000 --- a/object-pool/etc/object-pool.urm.puml +++ /dev/null @@ -1,30 +0,0 @@ -@startuml -package com.iluwatar.object.pool { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } - abstract class ObjectPool { - - available : Set - - inUse : Set - + ObjectPool() - + checkIn(instance : T) - + checkOut() : T - # create() : T {abstract} - + toString() : String - } - class Oliphaunt { - - counter : int {static} - - id : int - + Oliphaunt() - + getId() : int - + toString() : String - } - class OliphauntPool { - + OliphauntPool() - # create() : Oliphaunt - } -} -OliphauntPool --|> ObjectPool -@enduml \ No newline at end of file diff --git a/object-pool/pom.xml b/object-pool/pom.xml index 66d694169..4ebb40385 100644 --- a/object-pool/pom.xml +++ b/object-pool/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT object-pool diff --git a/observer/README.md b/observer/README.md index 3b3fcd2c5..38a28032f 100644 --- a/observer/README.md +++ b/observer/README.md @@ -3,7 +3,6 @@ layout: pattern title: Observer folder: observer permalink: /patterns/observer/ -pumlid: FSkn4OGm30NHLg00hFow4KO3PcpP8tr1-pYwx6smQz5Suv2mkbp0y1-HyPlEWYlsSB7S5Q98kJSgDLu66ztyy7Q8brEtmO2OEZNs2Uhxl9u9GVv72cjfHAiV categories: Behavioral tags: - Java diff --git a/observer/etc/observer.urm.puml b/observer/etc/observer.urm.puml deleted file mode 100644 index 5d046d880..000000000 --- a/observer/etc/observer.urm.puml +++ /dev/null @@ -1,81 +0,0 @@ -@startuml -left to right direction -package com.iluwatar.observer { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } - class Hobbits { - - LOGGER : Logger {static} - + Hobbits() - + update(currentWeather : WeatherType) - } - class Orcs { - - LOGGER : Logger {static} - + Orcs() - + update(currentWeather : WeatherType) - } - class Weather { - - LOGGER : Logger {static} - - currentWeather : WeatherType - - observers : List - + Weather() - + addObserver(obs : WeatherObserver) - - notifyObservers() - + removeObserver(obs : WeatherObserver) - + timePasses() - } - interface WeatherObserver { - + update(WeatherType) {abstract} - } - enum WeatherType { - + COLD {static} - + RAINY {static} - + SUNNY {static} - + WINDY {static} - + toString() : String - + valueOf(name : String) : WeatherType {static} - + values() : WeatherType[] {static} - } -} -package com.iluwatar.observer.generic { - class GHobbits { - - LOGGER : Logger {static} - + GHobbits() - + update(weather : GWeather, weatherType : WeatherType) - } - class GOrcs { - - LOGGER : Logger {static} - + GOrcs() - + update(weather : GWeather, weatherType : WeatherType) - } - class GWeather { - - LOGGER : Logger {static} - - currentWeather : WeatherType - + GWeather() - + timePasses() - } - abstract class Observable, A> { - # observers : List> - + Observable, A>() - + addObserver(observer : O extends Observer) - + notifyObservers(argument : A) - + removeObserver(observer : O extends Observer) - } - interface Observer, O extends Observer, A> { - + update(S extends Observable, A) {abstract} - } - interface Race { - } -} -Weather --> "-currentWeather" WeatherType -GWeather --> "-currentWeather" WeatherType -Weather --> "-observers" WeatherObserver -Hobbits ..|> WeatherObserver -Orcs ..|> WeatherObserver -GHobbits ..|> Race -GOrcs ..|> Race -GWeather --|> Observable -Race --|> Observer -@enduml diff --git a/observer/pom.xml b/observer/pom.xml index e1f2cf6bd..7113306f3 100644 --- a/observer/pom.xml +++ b/observer/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT observer diff --git a/page-object/etc/page-object.urm.puml b/page-object/etc/page-object.urm.puml deleted file mode 100644 index 735cf2889..000000000 --- a/page-object/etc/page-object.urm.puml +++ /dev/null @@ -1,8 +0,0 @@ -@startuml -package com.iluwatar.pageobject { - class App { - - App() - + main(args : String[]) {static} - } -} -@enduml \ No newline at end of file diff --git a/page-object/pom.xml b/page-object/pom.xml index ea17c372c..98842b387 100644 --- a/page-object/pom.xml +++ b/page-object/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT page-object diff --git a/partial-response/README.md b/partial-response/README.md new file mode 100644 index 000000000..5d03cb359 --- /dev/null +++ b/partial-response/README.md @@ -0,0 +1,29 @@ +--- +layout: pattern +title: Partial Response +folder: partial-response +permalink: /patterns/partial-response/ +categories: Architectural +tags: + - Java + - KISS + - YAGNI + - Difficulty-Beginner +--- + +## Intent +Send partial response from server to client on need basis. Client will specify the the fields +that it need to server, instead of serving all details for resource. + +![alt text](./etc/partial-response.urm.png "partial-response") + +## Applicability +Use the Partial Response pattern when + +* Client need only subset of data from resource. +* To avoid too much data transfer over wire + +## Credits + +* [Common Design Patterns](https://cloud.google.com/apis/design/design_patterns) +* [Partial Response in RESTful API Design](http://yaoganglian.com/2013/07/01/partial-response/) diff --git a/partial-response/etc/partial-response.ucls b/partial-response/etc/partial-response.ucls new file mode 100644 index 000000000..a0b029496 --- /dev/null +++ b/partial-response/etc/partial-response.ucls @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/partial-response/etc/partial-response.urm.png b/partial-response/etc/partial-response.urm.png new file mode 100644 index 000000000..17dbd5f1b Binary files /dev/null and b/partial-response/etc/partial-response.urm.png differ diff --git a/partial-response/pom.xml b/partial-response/pom.xml new file mode 100644 index 000000000..94c583a98 --- /dev/null +++ b/partial-response/pom.xml @@ -0,0 +1,49 @@ + + + + + java-design-patterns + com.iluwatar + 1.18.0-SNAPSHOT + + 4.0.0 + + partial-response + + + junit + junit + + + org.mockito + mockito-core + + + + + \ No newline at end of file diff --git a/partial-response/src/main/java/com/iluwatar/partialresponse/App.java b/partial-response/src/main/java/com/iluwatar/partialresponse/App.java new file mode 100644 index 000000000..2977b50a7 --- /dev/null +++ b/partial-response/src/main/java/com/iluwatar/partialresponse/App.java @@ -0,0 +1,74 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2014-2017 Gopinath Langote + * + * 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.partialresponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +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. + */ + +public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + + /** + * Method as act client and request to server for video details. + * + * @param args program argument. + */ + public static void main(String[] args) throws Exception { + Map videos = new HashMap<>(); + videos.put(1, new Video(1, "Avatar", 178, "epic science fiction film", "James Cameron", "English")); + videos.put(2, new Video(2, "Godzilla Resurgence", 120, "Action & drama movie|", "Hideaki Anno", "Japanese")); + videos.put(3, new Video(3, "Interstellar", 169, "Adventure & Sci-Fi", "Christopher Nolan", "English")); + VideoResource videoResource = new VideoResource(new FieldJsonMapper(), videos); + + + LOGGER.info("Retrieving full response from server:-"); + LOGGER.info("Get all video information:"); + String videoDetails = videoResource.getDetails(1); + LOGGER.info(videoDetails); + + LOGGER.info("----------------------------------------------------------"); + + LOGGER.info("Retrieving partial response from server:-"); + LOGGER.info("Get video @id, @title, @director:"); + String specificFieldsDetails = videoResource.getDetails(3, "id", "title", "director"); + LOGGER.info(specificFieldsDetails); + + LOGGER.info("Get video @id, @length:"); + String videoLength = videoResource.getDetails(3, "id", "length"); + LOGGER.info(videoLength); + } +} diff --git a/partial-response/src/main/java/com/iluwatar/partialresponse/FieldJsonMapper.java b/partial-response/src/main/java/com/iluwatar/partialresponse/FieldJsonMapper.java new file mode 100644 index 000000000..9283cfa69 --- /dev/null +++ b/partial-response/src/main/java/com/iluwatar/partialresponse/FieldJsonMapper.java @@ -0,0 +1,60 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2014-2017 Gopinath Langote + * + * 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.partialresponse; + +import java.lang.reflect.Field; + +/** + * Map a video to json + */ +public class FieldJsonMapper { + + /** + * @param video object containing video information + * @param fields fields information to get + * @return json of required fields from video + */ + public String toJson(Video video, String[] fields) throws Exception { + StringBuilder json = new StringBuilder().append("{"); + + for (int i = 0, fieldsLength = fields.length; i < fieldsLength; i++) { + json.append(getString(video, Video.class.getDeclaredField(fields[i]))); + if (i != fieldsLength - 1) { + json.append(","); + } + } + json.append("}"); + return json.toString(); + } + + private String getString(Video video, Field declaredField) throws IllegalAccessException { + declaredField.setAccessible(true); + Object value = declaredField.get(video); + if (declaredField.get(video) instanceof Integer) { + return "\"" + declaredField.getName() + "\"" + ": " + value; + } + return "\"" + declaredField.getName() + "\"" + ": " + "\"" + value.toString() + "\""; + } +} diff --git a/partial-response/src/main/java/com/iluwatar/partialresponse/Video.java b/partial-response/src/main/java/com/iluwatar/partialresponse/Video.java new file mode 100644 index 000000000..e242965e3 --- /dev/null +++ b/partial-response/src/main/java/com/iluwatar/partialresponse/Video.java @@ -0,0 +1,70 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2014-2017 Gopinath Langote + * + * 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.partialresponse; + +/** + * {@link Video} is a entity to serve from server.It contains all video related information.. + *

+ */ +public class Video { + private final Integer id; + private final String title; + private final Integer length; + private final String description; + private final String director; + 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} + */ + public Video(Integer id, String title, Integer length, String description, String director, String language) { + this.id = id; + this.title = title; + this.length = length; + this.description = description; + this.director = director; + this.language = language; + } + + /** + * @return json representaion of video + */ + @Override + public String toString() { + return "{" + + "\"id\": " + id + "," + + "\"title\": \"" + title + "\"," + + "\"length\": " + length + "," + + "\"description\": \"" + description + "\"," + + "\"director\": \"" + director + "\"," + + "\"language\": \"" + language + "\"," + + "}"; + } +} diff --git a/partial-response/src/main/java/com/iluwatar/partialresponse/VideoResource.java b/partial-response/src/main/java/com/iluwatar/partialresponse/VideoResource.java new file mode 100644 index 000000000..2bf7a73c1 --- /dev/null +++ b/partial-response/src/main/java/com/iluwatar/partialresponse/VideoResource.java @@ -0,0 +1,57 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2014-2017 Gopinath Langote + * + * 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.partialresponse; + +import java.util.Map; + +/** + * 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; + + /** + * @param fieldJsonMapper map object to json. + * @param videos initialize resource with existing videos. Act as database. + */ + public VideoResource(FieldJsonMapper fieldJsonMapper, Map videos) { + this.fieldJsonMapper = fieldJsonMapper; + this.videos = videos; + } + + /** + * @param id video id + * @param fields fields to get information about + * @return full response if no fields specified else partial response for given field. + */ + public String getDetails(Integer id, String... fields) throws Exception { + if (fields.length == 0) { + return videos.get(id).toString(); + } + return fieldJsonMapper.toJson(videos.get(id), fields); + } +} diff --git a/partial-response/src/test/java/com/iluwatar/partialresponse/AppTest.java b/partial-response/src/test/java/com/iluwatar/partialresponse/AppTest.java new file mode 100644 index 000000000..2ac34dd0d --- /dev/null +++ b/partial-response/src/test/java/com/iluwatar/partialresponse/AppTest.java @@ -0,0 +1,40 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2014-2017 Gopinath Langote + * + * 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.partialresponse; + +import org.junit.Test; + +/** + * Application test + */ +public class AppTest { + + @Test + public void main() throws Exception { + String[] args = {}; + App.main(args); + } + +} \ No newline at end of file diff --git a/partial-response/src/test/java/com/iluwatar/partialresponse/FieldJsonMapperTest.java b/partial-response/src/test/java/com/iluwatar/partialresponse/FieldJsonMapperTest.java new file mode 100644 index 000000000..9bc078b57 --- /dev/null +++ b/partial-response/src/test/java/com/iluwatar/partialresponse/FieldJsonMapperTest.java @@ -0,0 +1,53 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2014-2017 Gopinath Langote + * + * 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.partialresponse; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * tests {@link FieldJsonMapper}. + */ +public class FieldJsonMapperTest { + private FieldJsonMapper mapper; + + @Before + public void setUp() { + mapper = new FieldJsonMapper(); + } + + @Test + public void shouldReturnJsonForSpecifiedFieldsInVideo() throws Exception { + String[] fields = new String[]{"id", "title", "length"}; + Video video = new Video(2, "Godzilla Resurgence", 120, "Action & drama movie|", "Hideaki Anno", "Japanese"); + + String jsonFieldResponse = mapper.toJson(video, fields); + + String expectedDetails = "{\"id\": 2,\"title\": \"Godzilla Resurgence\",\"length\": 120}"; + assertEquals(expectedDetails, jsonFieldResponse); + } +} \ No newline at end of file diff --git a/partial-response/src/test/java/com/iluwatar/partialresponse/VideoResourceTest.java b/partial-response/src/test/java/com/iluwatar/partialresponse/VideoResourceTest.java new file mode 100644 index 000000000..0453e8ffd --- /dev/null +++ b/partial-response/src/test/java/com/iluwatar/partialresponse/VideoResourceTest.java @@ -0,0 +1,80 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2014-2017 Gopinath Langote + * + * 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.partialresponse; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.when; + +/** + * tests {@link VideoResource}. + */ +@RunWith(MockitoJUnitRunner.class) +public class VideoResourceTest { + @Mock + private FieldJsonMapper fieldJsonMapper; + + private VideoResource resource; + + @Before + public void setUp() { + Map videos = new HashMap<>(); + videos.put(1, new Video(1, "Avatar", 178, "epic science fiction film", "James Cameron", "English")); + videos.put(2, new Video(2, "Godzilla Resurgence", 120, "Action & drama movie|", "Hideaki Anno", "Japanese")); + videos.put(3, new Video(3, "Interstellar", 169, "Adventure & Sci-Fi", "Christopher Nolan", "English")); + resource = new VideoResource(fieldJsonMapper, videos); + } + + @Test + public void shouldGiveVideoDetailsById() throws Exception { + String actualDetails = resource.getDetails(1); + + String expectedDetails = "{\"id\": 1,\"title\": \"Avatar\",\"length\": 178,\"description\": " + + "\"epic science fiction film\",\"director\": \"James Cameron\",\"language\": \"English\",}"; + assertEquals(expectedDetails, actualDetails); + } + + @Test + public void shouldGiveSpecifiedFieldsInformationOfVideo() throws Exception { + String[] fields = new String[]{"id", "title", "length"}; + + String expectedDetails = "{\"id\": 1,\"title\": \"Avatar\",\"length\": 178}"; + when(fieldJsonMapper.toJson(any(Video.class), eq(fields))).thenReturn(expectedDetails); + + String actualFieldsDetails = resource.getDetails(2, fields); + + assertEquals(expectedDetails, actualFieldsDetails); + } +} \ No newline at end of file diff --git a/poison-pill/README.md b/poison-pill/README.md index 8f673ad49..0815b376e 100644 --- a/poison-pill/README.md +++ b/poison-pill/README.md @@ -3,7 +3,6 @@ layout: pattern title: Poison Pill folder: poison-pill permalink: /patterns/poison-pill/ -pumlid: JSZ14SCm20NHLf82BExfXiYCJGOX3NpYzkDZRllsgTwjTgcmnmciV145N-rGdFMkbEZJ8OxMvo2rkXWSzE4lRxka7huj1YGyQN3UGMjgpdkh6Gdwlrl5QAk6_G00 categories: Other tags: - Java diff --git a/poison-pill/etc/poison-pill.urm.puml b/poison-pill/etc/poison-pill.urm.puml deleted file mode 100644 index 5c2b9fa2b..000000000 --- a/poison-pill/etc/poison-pill.urm.puml +++ /dev/null @@ -1,71 +0,0 @@ -@startuml -package com.iluwatar.poison.pill { - class App { - + App() - + main(args : String[]) {static} - } - class Consumer { - - LOGGER : Logger {static} - - name : String - - queue : MqSubscribePoint - + Consumer(name : String, queue : MqSubscribePoint) - + consume() - } - interface Message { - + POISON_PILL : Message {static} - + addHeader(Headers, String) {abstract} - + getBody() : String {abstract} - + getHeader(Headers) : String {abstract} - + getHeaders() : Map {abstract} - + setBody(String) {abstract} - } - enum Headers { - + DATE {static} - + SENDER {static} - + valueOf(name : String) : Headers {static} - + values() : Headers[] {static} - } - interface MessageQueue { - } - interface MqPublishPoint { - + put(Message) {abstract} - } - interface MqSubscribePoint { - + take() : Message {abstract} - } - class Producer { - - LOGGER : Logger {static} - - isStopped : boolean - - name : String - - queue : MqPublishPoint - + Producer(name : String, queue : MqPublishPoint) - + send(body : String) - + stop() - } - class SimpleMessage { - - body : String - - headers : Map - + SimpleMessage() - + addHeader(header : Headers, value : String) - + getBody() : String - + getHeader(header : Headers) : String - + getHeaders() : Map - + setBody(body : String) - } - class SimpleMessageQueue { - - queue : BlockingQueue - + SimpleMessageQueue(bound : int) - + put(msg : Message) - + take() : Message - } -} -SimpleMessageQueue --> "-queue" Message -Consumer --> "-queue" MqSubscribePoint -Headers ..+ Message -Producer --> "-queue" MqPublishPoint -Message --> "-POISON_PILL" Message -MessageQueue --|> MqPublishPoint -MessageQueue --|> MqSubscribePoint -SimpleMessage ..|> Message -SimpleMessageQueue ..|> MessageQueue -@enduml \ No newline at end of file diff --git a/poison-pill/pom.xml b/poison-pill/pom.xml index 8c0935310..3bd0f0967 100644 --- a/poison-pill/pom.xml +++ b/poison-pill/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT poison-pill diff --git a/pom.xml b/pom.xml index f2b6b7ccb..a60c8e7f9 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ 4.0.0 com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT pom 2014 @@ -42,7 +42,6 @@ 4.12.1 4.5.2 2.22 - 1.4.4 4.0 3.3.0 1.7.21 @@ -145,8 +144,14 @@ cqrs event-sourcing data-transfer-object - throttling - + throttling + + unit-of-work + partial-response + eip-wire-tap + eip-splitter + eip-aggregator + @@ -308,25 +313,6 @@ - - - - com.github.markusmo3.urm - - - urm-maven-plugin - - - [1.4.1,) - - - map - - - - - - @@ -441,41 +427,6 @@ - - - com.github.markusmo3.urm - urm-maven-plugin - ${urm.version} - - - process-classes - - map - - - - - ${project.basedir}/etc - - com.iluwatar - - - - java-design-patterns - singleton - factory-method - abstract-factory - builder - prototype - adapter - bridge - composite - decorator - facade - flyweight - - - diff --git a/private-class-data/README.md b/private-class-data/README.md index 061cc9e77..981208fa3 100644 --- a/private-class-data/README.md +++ b/private-class-data/README.md @@ -3,7 +3,6 @@ layout: pattern title: Private Class Data folder: private-class-data permalink: /patterns/private-class-data/ -pumlid: RShR3SCm243HLTe1RFwx3S4eeSB4uf6itmpGlwkZ-nOZhS7b-ZeoLtm07E--InwrLR3JQScMdSu9edLZeiCNBso3GtPh2pFPBM1YF07BvSBaHeeHRJm_SD8VxkMphvhw0m00 categories: Other tags: - Java diff --git a/private-class-data/etc/private-class-data.urm.puml b/private-class-data/etc/private-class-data.urm.puml deleted file mode 100644 index 990b53342..000000000 --- a/private-class-data/etc/private-class-data.urm.puml +++ /dev/null @@ -1,36 +0,0 @@ -@startuml -package com.iluwatar.privateclassdata { - class App { - + App() - + main(args : String[]) {static} - } - class ImmutableStew { - - LOGGER : Logger {static} - - data : StewData - + ImmutableStew(numPotatoes : int, numCarrots : int, numMeat : int, numPeppers : int) - + mix() - } - class Stew { - - LOGGER : Logger {static} - - numCarrots : int - - numMeat : int - - numPeppers : int - - numPotatoes : int - + Stew(numPotatoes : int, numCarrots : int, numMeat : int, numPeppers : int) - + mix() - + taste() - } - class StewData { - - numCarrots : int - - numMeat : int - - numPeppers : int - - numPotatoes : int - + StewData(numPotatoes : int, numCarrots : int, numMeat : int, numPeppers : int) - + getNumCarrots() : int - + getNumMeat() : int - + getNumPeppers() : int - + getNumPotatoes() : int - } -} -ImmutableStew --> "-data" StewData -@enduml \ No newline at end of file diff --git a/private-class-data/pom.xml b/private-class-data/pom.xml index 98a60c3c7..3ac0cf532 100644 --- a/private-class-data/pom.xml +++ b/private-class-data/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT private-class-data diff --git a/producer-consumer/README.md b/producer-consumer/README.md index b3cb56af1..1bb84c35f 100644 --- a/producer-consumer/README.md +++ b/producer-consumer/README.md @@ -3,7 +3,6 @@ layout: pattern title: Producer Consumer folder: producer-consumer permalink: /patterns/producer-consumer/ -pumlid: PSjB3iCW303HgxG70Ezx6zTO2HKso9_a-c7VtUX9y-vA8nkdZTSPiVm3O7ZNeyUPttGscXgiKMaAz94t1XhyyCBIsFkXPM44cpe8-WvODbiIMzcdfspXe7-jQL9NodW0 categories: Concurrency tags: - Java diff --git a/producer-consumer/etc/producer-consumer.urm.puml b/producer-consumer/etc/producer-consumer.urm.puml deleted file mode 100644 index 05539a55e..000000000 --- a/producer-consumer/etc/producer-consumer.urm.puml +++ /dev/null @@ -1,39 +0,0 @@ -@startuml -package com.iluwatar.producer.consumer { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } - class Consumer { - - LOGGER : Logger {static} - - name : String - - queue : ItemQueue - + Consumer(name : String, queue : ItemQueue) - + consume() - } - class Item { - - id : int - - producer : String - + Item(producer : String, id : int) - + getId() : int - + getProducer() : String - } - class ItemQueue { - - queue : BlockingQueue - + ItemQueue() - + put(item : Item) - + take() : Item - } - class Producer { - - itemId : int - - name : String - - queue : ItemQueue - + Producer(name : String, queue : ItemQueue) - + produce() - } -} -Consumer --> "-queue" ItemQueue -Producer --> "-queue" ItemQueue -ItemQueue --> "-queue" Item -@enduml \ No newline at end of file diff --git a/producer-consumer/pom.xml b/producer-consumer/pom.xml index 2680a973e..893d7a4ff 100644 --- a/producer-consumer/pom.xml +++ b/producer-consumer/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT producer-consumer diff --git a/promise/README.md b/promise/README.md index 37fd214b7..fa9556547 100644 --- a/promise/README.md +++ b/promise/README.md @@ -3,7 +3,6 @@ layout: pattern title: Promise folder: promise permalink: /patterns/promise/ -pumlid: DOqv4i8m301xNW4FYDLJvIl2rYHYBDcZWtmVKr3jDZkxUw15IhyzM6lFHcdzVaPCVm8ONkNWEFELJbQ71ccKEWIuvuKhXJT-S6laVEWsCO9C7GHz2KmRmav0KVzUqgJCtsydROjV categories: Concurrency tags: - Java diff --git a/promise/etc/promise.urm.puml b/promise/etc/promise.urm.puml deleted file mode 100644 index 8aabc1d2a..000000000 --- a/promise/etc/promise.urm.puml +++ /dev/null @@ -1,79 +0,0 @@ -@startuml -left to right direction -package com.iluwatar.promise { - class App { - - DEFAULT_URL : String {static} - - LOGGER : Logger {static} - - executor : ExecutorService - - stopLatch : CountDownLatch - - App() - - calculateLineCount() - - calculateLowestFrequencyChar() - - characterFrequency() : Promise> - - countLines() : Promise - - download(urlString : String) : Promise - - lowestFrequencyChar() : Promise - + main(args : String[]) {static} - - promiseUsage() - - stop() - - taskCompleted() - } - class Promise { - - exceptionHandler : Consumer - - fulfillmentAction : Runnable - + Promise() - + fulfill(value : T) - + fulfillExceptionally(exception : Exception) - + fulfillInAsync(task : Callable, executor : Executor) : Promise - - handleException(exception : Exception) - + onError(exceptionHandler : Consumer) : Promise - - postFulfillment() - + thenAccept(action : Consumer) : Promise - + thenApply(func : Function) : Promise - } - -class ConsumeAction { - - action : Consumer - - dest : Promise - - src : Promise - - ConsumeAction(src : Promise, dest : Promise, action : Consumer) - + run() - } - -class TransformAction { - - dest : Promise - - func : Function - - src : Promise - - TransformAction(src : Promise, dest : Promise, func : Function) - + run() - } - ~class PromiseSupport { - - COMPLETED : int {static} - - FAILED : int {static} - - RUNNING : int {static} - - exception : Exception - - lock : Object - - state : int - - value : T - ~ PromiseSupport() - + cancel(mayInterruptIfRunning : boolean) : boolean - ~ fulfill(value : T) - ~ fulfillExceptionally(exception : Exception) - + get() : T - + get(timeout : long, unit : TimeUnit) : T - + isCancelled() : boolean - + isDone() : boolean - } - class Utility { - - LOGGER : Logger {static} - + Utility() - + characterFrequency(fileLocation : String) : Map {static} - + countLines(fileLocation : String) : Integer {static} - + downloadFile(urlString : String) : String {static} - + lowestFrequencyChar(charFrequency : Map) : Character {static} - } -} -TransformAction --+ Promise -TransformAction --> "-src" Promise -ConsumeAction --+ Promise -ConsumeAction --> "-src" Promise -Promise --|> PromiseSupport -@enduml diff --git a/promise/pom.xml b/promise/pom.xml index 3753e4c25..05fd4c3ee 100644 --- a/promise/pom.xml +++ b/promise/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT promise diff --git a/promise/src/main/java/com/iluwatar/promise/App.java b/promise/src/main/java/com/iluwatar/promise/App.java index df4d0cc79..dd40ec15b 100644 --- a/promise/src/main/java/com/iluwatar/promise/App.java +++ b/promise/src/main/java/com/iluwatar/promise/App.java @@ -65,7 +65,7 @@ public class App { private static final Logger LOGGER = LoggerFactory.getLogger(App.class); - private static final String DEFAULT_URL = "https://raw.githubusercontent.com/iluwatar/java-design-patterns/Promise/promise/README.md"; + private static final String DEFAULT_URL = "https://raw.githubusercontent.com/iluwatar/java-design-patterns/master/promise/README.md"; private final ExecutorService executor; private final CountDownLatch stopLatch; diff --git a/promise/src/main/java/com/iluwatar/promise/PromiseSupport.java b/promise/src/main/java/com/iluwatar/promise/PromiseSupport.java index 3629b4b5d..ae90a927e 100644 --- a/promise/src/main/java/com/iluwatar/promise/PromiseSupport.java +++ b/promise/src/main/java/com/iluwatar/promise/PromiseSupport.java @@ -27,11 +27,16 @@ import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * A really simplified implementation of future that allows completing it successfully with a value * or exceptionally with an exception. */ class PromiseSupport implements Future { + + private static final Logger LOGGER = LoggerFactory.getLogger(PromiseSupport.class); private static final int RUNNING = 1; private static final int FAILED = 2; @@ -80,40 +85,34 @@ class PromiseSupport implements Future { @Override public T get() throws InterruptedException, ExecutionException { - if (state == COMPLETED) { - return value; - } else if (state == FAILED) { - throw new ExecutionException(exception); - } else { - synchronized (lock) { + synchronized (lock) { + while (state == RUNNING) { lock.wait(); - if (state == COMPLETED) { - return value; - } else { - throw new ExecutionException(exception); - } } } + if (state == COMPLETED) { + return value; + } + throw new ExecutionException(exception); } @Override public T get(long timeout, TimeUnit unit) - throws InterruptedException, ExecutionException, TimeoutException { - if (state == COMPLETED) { - return value; - } else if (state == FAILED) { - throw new ExecutionException(exception); - } else { - synchronized (lock) { - lock.wait(unit.toMillis(timeout)); - if (state == COMPLETED) { - return value; - } else if (state == FAILED) { - throw new ExecutionException(exception); - } else { - throw new TimeoutException(); + throws ExecutionException, TimeoutException { + synchronized (lock) { + while (state == RUNNING) { + try { + lock.wait(unit.toMillis(timeout)); + } catch (InterruptedException e) { + LOGGER.warn("Interrupted!", e); + Thread.currentThread().interrupt(); } } } + + if (state == COMPLETED) { + return value; + } + throw new ExecutionException(exception); } } \ No newline at end of file diff --git a/property/README.md b/property/README.md index c1502f75c..0ac5c7a6c 100644 --- a/property/README.md +++ b/property/README.md @@ -3,7 +3,6 @@ layout: pattern title: Property folder: property permalink: /patterns/property/ -pumlid: FSV13OCm30NGLTe1YEziumOBKYMEPN-3s9wUUdlltRJst2Izlmx0OYLolihUSEGdGxnEXIXAdODQpul1Jby-UTaasgwBCI2kGOFZ1pAV9ewR1FMVaZwAvUWF categories: Creational tags: - Java diff --git a/property/etc/property.urm.puml b/property/etc/property.urm.puml deleted file mode 100644 index f281cd873..000000000 --- a/property/etc/property.urm.puml +++ /dev/null @@ -1,54 +0,0 @@ -@startuml -package com.iluwatar.property { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } - class Character { - - name : String - - properties : Map - - prototype : Prototype - - type : Type - + Character() - + Character(name : String, prototype : Character) - + Character(type : Type, prototype : Prototype) - + get(stat : Stats) : Integer - + has(stat : Stats) : boolean - + name() : String - + remove(stat : Stats) - + set(stat : Stats, val : Integer) - + toString() : String - + type() : Type - } - enum Type { - + MAGE {static} - + ROGUE {static} - + WARRIOR {static} - + valueOf(name : String) : Type {static} - + values() : Type[] {static} - } - interface Prototype { - + get(Stats) : Integer {abstract} - + has(Stats) : boolean {abstract} - + remove(Stats) {abstract} - + set(Stats, Integer) {abstract} - } - enum Stats { - + AGILITY {static} - + ARMOR {static} - + ATTACK_POWER {static} - + ENERGY {static} - + INTELLECT {static} - + RAGE {static} - + SPIRIT {static} - + STRENGTH {static} - + valueOf(name : String) : Stats {static} - + values() : Stats[] {static} - } -} -Character --> "-prototype" Prototype -Type ..+ Character -Character --> "-type" Type -Character ..|> Prototype -@enduml \ No newline at end of file diff --git a/property/pom.xml b/property/pom.xml index 8b5d25c87..db2ff8f60 100644 --- a/property/pom.xml +++ b/property/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT property diff --git a/prototype/README.md b/prototype/README.md index 477cd6e6f..4bfeebe19 100644 --- a/prototype/README.md +++ b/prototype/README.md @@ -3,7 +3,6 @@ layout: pattern title: Prototype folder: prototype permalink: /patterns/prototype/ -pumlid: HSV13OCm30NGLM00udktCS62eCInxE-YRj_UUdjlRLfx7fBUbmkmU14vF-Lik7BF4AzJ8OfIvw3Mys6mqyrltWw9Tkfc38XhqE3uWSmd9Zuc9AZ_bVHHB4V_0W00 categories: Creational tags: - Java diff --git a/prototype/pom.xml b/prototype/pom.xml index de3571a77..62d4f0eb1 100644 --- a/prototype/pom.xml +++ b/prototype/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT prototype diff --git a/prototype/src/test/java/com/iluwatar/prototype/PrototypeTest.java b/prototype/src/test/java/com/iluwatar/prototype/PrototypeTest.java index add5617b1..839f27bc7 100644 --- a/prototype/src/test/java/com/iluwatar/prototype/PrototypeTest.java +++ b/prototype/src/test/java/com/iluwatar/prototype/PrototypeTest.java @@ -56,7 +56,7 @@ public class PrototypeTest

{ /** * The tested prototype instance */ - private final Prototype testedPrototype; + private final P testedPrototype; /** * The expected {@link Prototype#toString()} value @@ -69,7 +69,7 @@ public class PrototypeTest

{ * @param testedPrototype The tested prototype instance * @param expectedToString The expected {@link Prototype#toString()} value */ - public PrototypeTest(final Prototype testedPrototype, final String expectedToString) { + public PrototypeTest(final P testedPrototype, final String expectedToString) { this.expectedToString = expectedToString; this.testedPrototype = testedPrototype; } diff --git a/proxy/README.md b/proxy/README.md index 17f23de50..80593c75e 100644 --- a/proxy/README.md +++ b/proxy/README.md @@ -3,7 +3,6 @@ layout: pattern title: Proxy folder: proxy permalink: /patterns/proxy/ -pumlid: 9SR13OCm30NGLM00udktCS62eCI9x6yesrEfx_Jcehd69c5rEe3X7oBZE-q5HwpXOhahH95oRrHgt0msEldYPHClkow30J5rQko_qB3-VKYG_qjXBOrezGK0 categories: Structural tags: - Java @@ -18,7 +17,97 @@ Surrogate Provide a surrogate or placeholder for another object to control access to it. -![alt text](./etc/proxy.png "Proxy") +## Explanation +Real world example + +> Imagine a tower where the local wizards go to study their spells. The ivory tower can only be accessed through a proxy which ensures that only the first three wizards can enter. Here the proxy represents the functionality of the tower and adds access control to it. + +In plain words + +> Using the proxy pattern, a class represents the functionality of another class. + +Wikipedia says + +> A proxy, in its most general form, is a class functioning as an interface to something else. A proxy is a wrapper or agent object that is being called by the client to access the real serving object behind the scenes. Use of the proxy can simply be forwarding to the real object, or can provide additional logic. In the proxy extra functionality can be provided, for example caching when operations on the real object are resource intensive, or checking preconditions before operations on the real object are invoked. + +**Programmatic Example** + +Taking our wizard tower example from above. Firstly we have the wizard tower interface and the ivory tower class + +``` +public interface WizardTower { + + void enter(Wizard wizard); +} + +public class IvoryTower implements WizardTower { + + private static final Logger LOGGER = LoggerFactory.getLogger(IvoryTower.class); + + public void enter(Wizard wizard) { + LOGGER.info("{} enters the tower.", wizard); + } + +} +``` + +Then a simple wizard class + +``` +public class Wizard { + + private final String name; + + public Wizard(String name) { + this.name = name; + } + + @Override + public String toString() { + return name; + } +} +``` + +Then we have the proxy to add access control to wizard tower + +``` +public class WizardTowerProxy implements WizardTower { + + private static final Logger LOGGER = LoggerFactory.getLogger(WizardTowerProxy.class); + + private static final int NUM_WIZARDS_ALLOWED = 3; + + private int numWizards; + + private final WizardTower tower; + + public WizardTowerProxy(WizardTower tower) { + this.tower = tower; + } + + @Override + public void enter(Wizard wizard) { + if (numWizards < NUM_WIZARDS_ALLOWED) { + tower.enter(wizard); + numWizards++; + } else { + LOGGER.info("{} is not allowed to enter!", wizard); + } + } +} +``` + +And here is tower entering scenario + +``` +WizardTowerProxy proxy = new WizardTowerProxy(new IvoryTower()); +proxy.enter(new Wizard("Red wizard")); // Red wizard enters the tower. +proxy.enter(new Wizard("White wizard")); // White wizard enters the tower. +proxy.enter(new Wizard("Black wizard")); // Black wizard enters the tower. +proxy.enter(new Wizard("Green wizard")); // Green wizard is not allowed to enter! +proxy.enter(new Wizard("Brown wizard")); // Brown wizard is not allowed to enter! +``` ## Applicability Proxy is applicable whenever there is a need for a more diff --git a/proxy/etc/proxy.png b/proxy/etc/proxy.png deleted file mode 100644 index 300e58dd3..000000000 Binary files a/proxy/etc/proxy.png and /dev/null differ diff --git a/proxy/etc/proxy.urm.puml b/proxy/etc/proxy.urm.puml deleted file mode 100644 index ffe0fa446..000000000 --- a/proxy/etc/proxy.urm.puml +++ /dev/null @@ -1,32 +0,0 @@ -@startuml -package com.iluwatar.proxy { - class App { - + App() - + main(args : String[]) {static} - } - class IvoryTower { - - LOGGER : Logger {static} - + IvoryTower() - + enter(wizard : Wizard) - } - class Wizard { - - name : String - + Wizard(name : String) - + toString() : String - } - interface WizardTower { - + enter(Wizard) {abstract} - } - class WizardTowerProxy { - - LOGGER : Logger {static} - - NUM_WIZARDS_ALLOWED : int {static} - - numWizards : int - - tower : WizardTower - + WizardTowerProxy(tower : WizardTower) - + enter(wizard : Wizard) - } -} -WizardTowerProxy --> "-tower" WizardTower -IvoryTower ..|> WizardTower -WizardTowerProxy ..|> WizardTower -@enduml \ No newline at end of file diff --git a/proxy/pom.xml b/proxy/pom.xml index b81611fa4..ea55330b7 100644 --- a/proxy/pom.xml +++ b/proxy/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT proxy diff --git a/publish-subscribe/etc/publish-subscribe.urm.puml b/publish-subscribe/etc/publish-subscribe.urm.puml deleted file mode 100644 index 2e511c92d..000000000 --- a/publish-subscribe/etc/publish-subscribe.urm.puml +++ /dev/null @@ -1,9 +0,0 @@ -@startuml -package com.iluwatar.publish.subscribe { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } -} -@enduml \ No newline at end of file diff --git a/publish-subscribe/pom.xml b/publish-subscribe/pom.xml index c9a55a3ff..ebd82f3a7 100644 --- a/publish-subscribe/pom.xml +++ b/publish-subscribe/pom.xml @@ -28,7 +28,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT publish-subscribe diff --git a/queue-load-leveling/README.md b/queue-load-leveling/README.md index ca73ac34a..13821a54e 100644 --- a/queue-load-leveling/README.md +++ b/queue-load-leveling/README.md @@ -3,7 +3,6 @@ layout: pattern title: Queue based load leveling folder: queue-load-leveling permalink: /patterns/queue-load-leveling/ -pumlid: ROux3W8n30LxJW47IDnJxLLCOcM376VnP_VwX9xgZKOQwMtcg1w3RuykXQDIADztzyEU08fNRjttU8MHbYbEuhdC0PtZmfN26qzCbQmtIGUwauh1G5i0dw2Wn1DhOZg9kpGWB_zy3Xtv-FtOIEhQBm00 categories: Other tags: - Java diff --git a/queue-load-leveling/etc/queue-load-leveling.urm.puml b/queue-load-leveling/etc/queue-load-leveling.urm.puml deleted file mode 100644 index ca90842d9..000000000 --- a/queue-load-leveling/etc/queue-load-leveling.urm.puml +++ /dev/null @@ -1,44 +0,0 @@ -@startuml -package com.iluwatar.queue.load.leveling { - class App { - - LOGGER : Logger {static} - - SHUTDOWN_TIME : int {static} - + App() - + main(args : String[]) {static} - } - class Message { - - msg : String - + Message(msg : String) - + getMsg() : String - + toString() : String - } - class MessageQueue { - - LOGGER : Logger {static} - - blkQueue : BlockingQueue - + MessageQueue() - + retrieveMsg() : Message - + submitMsg(msg : Message) - } - class ServiceExecutor { - - LOGGER : Logger {static} - - msgQueue : MessageQueue - + ServiceExecutor(msgQueue : MessageQueue) - + run() - } - interface Task { - + submit(Message) {abstract} - } - class TaskGenerator { - - LOGGER : Logger {static} - - msgCount : int - - msgQueue : MessageQueue - + TaskGenerator(msgQueue : MessageQueue, msgCount : int) - + run() - + submit(msg : Message) - } -} -MessageQueue --> "-blkQueue" Message -ServiceExecutor --> "-msgQueue" MessageQueue -TaskGenerator --> "-msgQueue" MessageQueue -TaskGenerator ..|> Task -@enduml \ No newline at end of file diff --git a/queue-load-leveling/pom.xml b/queue-load-leveling/pom.xml index 0841357b3..57741ed52 100644 --- a/queue-load-leveling/pom.xml +++ b/queue-load-leveling/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT queue-load-leveling diff --git a/reactor/README.md b/reactor/README.md index 68461cfdd..ba96f9c68 100644 --- a/reactor/README.md +++ b/reactor/README.md @@ -3,7 +3,6 @@ layout: pattern title: Reactor folder: reactor permalink: /patterns/reactor/ -pumlid: DSR14OGm20NGLjO23FVj1f7Hx2Ga0nzjVxtuJc-f9YrtJM-V4vZn9NA-or5nvfQXBiEWXYAZKsrvCzZfnnUlkqOzR9qCg5jGvtX2hYmOJWfvNz9xcTdR7m00 pumlformat: svg categories: Concurrency tags: diff --git a/reactor/etc/reactor.urm.puml b/reactor/etc/reactor.urm.puml deleted file mode 100644 index 1ce92cab2..000000000 --- a/reactor/etc/reactor.urm.puml +++ /dev/null @@ -1,156 +0,0 @@ -@startuml -left to right direction -package com.iluwatar.reactor.framework { - abstract class AbstractNioChannel { - - channel : SelectableChannel - - channelToPendingWrites : Map> - - handler : ChannelHandler - - reactor : NioReactor - + AbstractNioChannel(handler : ChannelHandler, channel : SelectableChannel) - + bind() {abstract} - # doWrite(Object, SelectionKey) {abstract} - ~ flush(key : SelectionKey) - + getHandler() : ChannelHandler - + getInterestedOps() : int {abstract} - + getJavaChannel() : SelectableChannel - + read(SelectionKey) : Object {abstract} - ~ setReactor(reactor : NioReactor) - + write(data : Object, key : SelectionKey) - } - interface ChannelHandler { - + handleChannelRead(AbstractNioChannel, Object, SelectionKey) {abstract} - } - interface Dispatcher { - + onChannelReadEvent(AbstractNioChannel, Object, SelectionKey) {abstract} - + stop() {abstract} - } - class NioDatagramChannel { - - LOGGER : Logger {static} - - port : int - + NioDatagramChannel(port : int, handler : ChannelHandler) - + bind() - # doWrite(pendingWrite : Object, key : SelectionKey) - + getInterestedOps() : int - + getJavaChannel() : DatagramChannel - + read(key : SelectionKey) : DatagramPacket - + write(data : Object, key : SelectionKey) - } - class DatagramPacket { - - data : ByteBuffer - - receiver : SocketAddress - - sender : SocketAddress - + DatagramPacket(data : ByteBuffer) - + getData() : ByteBuffer - + getReceiver() : SocketAddress - + getSender() : SocketAddress - + setReceiver(receiver : SocketAddress) - + setSender(sender : SocketAddress) - } - class NioReactor { - - LOGGER : Logger {static} - - dispatcher : Dispatcher - - pendingCommands : Queue - - reactorMain : ExecutorService - - selector : Selector - + NioReactor(dispatcher : Dispatcher) - + changeOps(key : SelectionKey, interestedOps : int) - - dispatchReadEvent(key : SelectionKey, readObject : Object) - - eventLoop() - - onChannelAcceptable(key : SelectionKey) - - onChannelReadable(key : SelectionKey) - - onChannelWritable(key : SelectionKey) {static} - - processKey(key : SelectionKey) - - processPendingCommands() - + registerChannel(channel : AbstractNioChannel) : NioReactor - + start() - + stop() - } - ~class ChangeKeyOpsCommand { - - interestedOps : int - - key : SelectionKey - + ChangeKeyOpsCommand(this$0 : SelectionKey, key : int) - + run() - + toString() : String - } - class NioServerSocketChannel { - - LOGGER : Logger {static} - - port : int - + NioServerSocketChannel(port : int, handler : ChannelHandler) - + bind() - # doWrite(pendingWrite : Object, key : SelectionKey) - + getInterestedOps() : int - + getJavaChannel() : ServerSocketChannel - + read(key : SelectionKey) : ByteBuffer - } - class SameThreadDispatcher { - + SameThreadDispatcher() - + onChannelReadEvent(channel : AbstractNioChannel, readObject : Object, key : SelectionKey) - + stop() - } - class ThreadPoolDispatcher { - - executorService : ExecutorService - + ThreadPoolDispatcher(poolSize : int) - + onChannelReadEvent(channel : AbstractNioChannel, readObject : Object, key : SelectionKey) - + stop() - } -} -package com.iluwatar.reactor.app { - class App { - - channels : List - - dispatcher : Dispatcher - - reactor : NioReactor - + App(dispatcher : Dispatcher) - + main(args : String[]) {static} - + start() - + stop() - - tcpChannel(port : int, handler : ChannelHandler) : AbstractNioChannel - - udpChannel(port : int, handler : ChannelHandler) : AbstractNioChannel - } - class AppClient { - - LOGGER : Logger {static} - - service : ExecutorService - + AppClient() - - artificialDelayOf(millis : long) {static} - + main(args : String[]) {static} - + start() - + stop() - } - ~class TcpLoggingClient { - - clientName : String - - serverPort : int - + TcpLoggingClient(clientName : String, serverPort : int) - + run() - - sendLogRequests(writer : PrintWriter, inputStream : InputStream) - } - ~class UdpLoggingClient { - - clientName : String - - remoteAddress : InetSocketAddress - + UdpLoggingClient(clientName : String, port : int) - + run() - } - class LoggingHandler { - - ACK : byte[] {static} - - LOGGER : Logger {static} - + LoggingHandler() - - doLogging(data : ByteBuffer) {static} - + handleChannelRead(channel : AbstractNioChannel, readObject : Object, key : SelectionKey) - - sendReply(channel : AbstractNioChannel, incomingPacket : DatagramPacket, key : SelectionKey) {static} - - sendReply(channel : AbstractNioChannel, key : SelectionKey) {static} - } -} -AbstractNioChannel --> "-handler" ChannelHandler -UdpLoggingClient ..+ AppClient -TcpLoggingClient ..+ AppClient -AbstractNioChannel --> "-reactor" NioReactor -NioReactor --> "-dispatcher" Dispatcher -App --> "-reactor" NioReactor -App --> "-channels" AbstractNioChannel -DatagramPacket ..+ NioDatagramChannel -App --> "-dispatcher" Dispatcher -ChangeKeyOpsCommand --+ NioReactor -LoggingHandler ..|> ChannelHandler -NioDatagramChannel --|> AbstractNioChannel -NioServerSocketChannel --|> AbstractNioChannel -SameThreadDispatcher ..|> Dispatcher -ThreadPoolDispatcher ..|> Dispatcher -@enduml diff --git a/reactor/pom.xml b/reactor/pom.xml index 2a50d5934..9ab44d2c0 100644 --- a/reactor/pom.xml +++ b/reactor/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT reactor diff --git a/reader-writer-lock/README.md b/reader-writer-lock/README.md index 556b9cd85..40b711361 100644 --- a/reader-writer-lock/README.md +++ b/reader-writer-lock/README.md @@ -3,7 +3,6 @@ layout: pattern title: Reader Writer Lock folder: reader-writer-lock permalink: /patterns/reader-writer-lock/ -pumlid: RSZB4S8m303HLg00MtUw4R8cCP5bZpwuVL80jttxx4gIZTFaSKOiVm4OxdhqEFETpaPJWpKgpG5TScEWmGU_M1fxFxGiZ61JXu5-1nXZOolR-gqYaoxWe3-xfeswSiWF categories: Concurrency tags: - Java diff --git a/reader-writer-lock/etc/reader-writer-lock.urm.puml b/reader-writer-lock/etc/reader-writer-lock.urm.puml deleted file mode 100644 index b71cf73f6..000000000 --- a/reader-writer-lock/etc/reader-writer-lock.urm.puml +++ /dev/null @@ -1,61 +0,0 @@ -@startuml -package com.iluwatar.reader.writer.lock { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } - class Reader { - - LOGGER : Logger {static} - - name : String - - readLock : Lock - + Reader(name : String, readLock : Lock) - + read() - + run() - } - class ReaderWriterLock { - - currentReaderCount : int - - globalMutex : Set - - readerLock : ReadLock - - readerMutex : Object - - writerLock : WriteLock - + ReaderWriterLock() - - doesReaderOwnThisLock() : boolean - - doesWriterOwnThisLock() : boolean - - isLockFree() : boolean - + readLock() : Lock - - waitUninterruptibly(o : Object) {static} - + writeLock() : Lock - } - -class ReadLock { - - ReadLock() - + lock() - + lockInterruptibly() - + newCondition() : Condition - + tryLock() : boolean - + tryLock(time : long, unit : TimeUnit) : boolean - + unlock() - } - -class WriteLock { - - WriteLock() - + lock() - + lockInterruptibly() - + newCondition() : Condition - + tryLock() : boolean - + tryLock(time : long, unit : TimeUnit) : boolean - + unlock() - } - class Writer { - - LOGGER : Logger {static} - - name : String - - writeLock : Lock - + Writer(name : String, writeLock : Lock) - + run() - + write() - } -} -ReaderWriterLock --> "-readerLock" ReadLock -ReadLock --+ ReaderWriterLock -WriteLock --+ ReaderWriterLock -ReaderWriterLock --> "-writerLock" WriteLock -@enduml \ No newline at end of file diff --git a/reader-writer-lock/pom.xml b/reader-writer-lock/pom.xml index 70ff7afc9..d5ea9114c 100644 --- a/reader-writer-lock/pom.xml +++ b/reader-writer-lock/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT reader-writer-lock diff --git a/repository/README.md b/repository/README.md index 501f39f9c..67b3ea44e 100644 --- a/repository/README.md +++ b/repository/README.md @@ -3,7 +3,6 @@ layout: pattern title: Repository folder: repository permalink: /patterns/repository/ -pumlid: JSV13OCm30NGLM00udktCS42eyI9xE-YRjyUUtjlLQij3qblomNCU14vF-LKNBbdYDTX44EfevEsV1ZiTFERjqD2Jzic0-8Mr3b-89SvGZ7yGuBwrvBUoypUlW00 categories: Persistence Tier tags: - Java diff --git a/repository/etc/repository.urm.puml b/repository/etc/repository.urm.puml deleted file mode 100644 index 10768260c..000000000 --- a/repository/etc/repository.urm.puml +++ /dev/null @@ -1,56 +0,0 @@ -@startuml -package com.iluwatar.repository { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } - class AppConfig { - - LOGGER : Logger {static} - + AppConfig() - + dataSource() : DataSource - + entityManagerFactory() : LocalContainerEntityManagerFactoryBean - - jpaProperties() : Properties {static} - + main(args : String[]) {static} - + transactionManager() : JpaTransactionManager - } - class Person { - - age : int - - id : Long - - name : String - - surname : String - + Person() - + Person(name : String, surname : String, age : int) - + equals(obj : Object) : boolean - + getAge() : int - + getId() : Long - + getName() : String - + getSurname() : String - + hashCode() : int - + setAge(age : int) - + setId(id : Long) - + setName(name : String) - + setSurname(surname : String) - + toString() : String - } - interface PersonRepository { - + findByName(String) : Person {abstract} - } - class PersonSpecifications { - + PersonSpecifications() - } - class AgeBetweenSpec { - - from : int - - to : int - + AgeBetweenSpec(from : int, to : int) - + toPredicate(root : Root, query : CriteriaQuery, cb : CriteriaBuilder) : Predicate - } - class NameEqualSpec { - + name : String - + NameEqualSpec(name : String) - + toPredicate(root : Root, query : CriteriaQuery, cb : CriteriaBuilder) : Predicate - } -} -NameEqualSpec ..+ PersonSpecifications -AgeBetweenSpec ..+ PersonSpecifications -@enduml \ No newline at end of file diff --git a/repository/pom.xml b/repository/pom.xml index a167dd58c..f12c40113 100644 --- a/repository/pom.xml +++ b/repository/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT repository diff --git a/resource-acquisition-is-initialization/README.md b/resource-acquisition-is-initialization/README.md index df7ee294b..821f220d7 100644 --- a/resource-acquisition-is-initialization/README.md +++ b/resource-acquisition-is-initialization/README.md @@ -3,7 +3,6 @@ layout: pattern title: Resource Acquisition Is Initialization folder: resource-acquisition-is-initialization permalink: /patterns/resource-acquisition-is-initialization/ -pumlid: ZShR3S8m343HLUW0YV_PnhXMQvGumOzMOdhA1lqxkhgBABLSEQqzzeZfJm33isuIUxxIsMXei4QbqK5QdXXeyCO3oyekcvQ94MpgqD4lWB6FDEA2z4bn2HbQn8leHMponNy13hgvrhHUP_Rs0m00 categories: Other tags: - Java diff --git a/resource-acquisition-is-initialization/etc/resource-acquisition-is-initialization.urm.puml b/resource-acquisition-is-initialization/etc/resource-acquisition-is-initialization.urm.puml deleted file mode 100644 index 11309f0a6..000000000 --- a/resource-acquisition-is-initialization/etc/resource-acquisition-is-initialization.urm.puml +++ /dev/null @@ -1,19 +0,0 @@ -@startuml -package com.iluwatar.resource.acquisition.is.initialization { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } - class SlidingDoor { - - LOGGER : Logger {static} - + SlidingDoor() - + close() - } - class TreasureChest { - - LOGGER : Logger {static} - + TreasureChest() - + close() - } -} -@enduml \ No newline at end of file diff --git a/resource-acquisition-is-initialization/pom.xml b/resource-acquisition-is-initialization/pom.xml index ae07196b7..7a6716d7b 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.17.0-SNAPSHOT + 1.18.0-SNAPSHOT resource-acquisition-is-initialization diff --git a/semaphore/README.md b/semaphore/README.md index 071e061a7..46ccd7b8e 100644 --- a/semaphore/README.md +++ b/semaphore/README.md @@ -3,7 +3,6 @@ layout: pattern title: Semaphore folder: semaphore permalink: /patterns/semaphore/ -pumlid: HSV14SCm20J0Lk82BFxf1ikCfOn06ZZizfDVVhjRjphobFJnQi2ADv7pKwwEbaU6U9q6CPGwbVh8Xy5E7xvvFoNwPVjYGDo2bEC72b5URRgGeFvNqhMirF45 categories: Concurrency tags: - Java diff --git a/semaphore/etc/semaphore.urm.puml b/semaphore/etc/semaphore.urm.puml deleted file mode 100644 index 168fd17e7..000000000 --- a/semaphore/etc/semaphore.urm.puml +++ /dev/null @@ -1,56 +0,0 @@ -@startuml -package com.iluwatar.semaphore { - class App { - + App() - + main(args : String[]) {static} - } - class Fruit { - - type : FruitType - + Fruit(type : FruitType) - + getType() : FruitType - + toString() : String - } - enum FruitType { - + APPLE {static} - + LEMON {static} - + ORANGE {static} - + valueOf(name : String) : FruitType {static} - + values() : FruitType[] {static} - } - class FruitBowl { - - fruit : List - + FruitBowl() - + countFruit() : int - + put(f : Fruit) - + take() : Fruit - + toString() : String - } - class FruitShop { - - available : boolean[] - - bowls : FruitBowl[] - - semaphore : Semaphore - + FruitShop() - + countFruit() : int - + returnBowl(bowl : FruitBowl) - + takeBowl() : FruitBowl - } - interface Lock { - + acquire() {abstract} - + release() {abstract} - } - class Semaphore { - - counter : int - - licenses : int - + Semaphore(licenses : int) - + acquire() - + getAvailableLicenses() : int - + getNumLicenses() : int - + release() - } -} -FruitType ..+ Fruit -Fruit --> "-type" FruitType -FruitShop --> "-semaphore" Semaphore -FruitBowl --> "-fruit" Fruit -Semaphore ..|> Lock -@enduml \ No newline at end of file diff --git a/semaphore/pom.xml b/semaphore/pom.xml index dbab5325e..4fa1733f4 100644 --- a/semaphore/pom.xml +++ b/semaphore/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT semaphore diff --git a/semaphore/src/test/java/com/iluwatar/semaphore/AppTest.java b/semaphore/src/test/java/com/iluwatar/semaphore/AppTest.java index 26d274262..5eaed3b2e 100644 --- a/semaphore/src/test/java/com/iluwatar/semaphore/AppTest.java +++ b/semaphore/src/test/java/com/iluwatar/semaphore/AppTest.java @@ -28,7 +28,7 @@ import java.io.IOException; /** * Application Test Entrypoint */ -public class AppTest{ +public class AppTest { @Test public void test() throws IOException { String[] args = {}; diff --git a/servant/README.md b/servant/README.md index d14d35edf..3e82ab2cf 100644 --- a/servant/README.md +++ b/servant/README.md @@ -3,7 +3,6 @@ layout: pattern title: Servant folder: servant permalink: /patterns/servant/ -pumlid: DSkn4O0m20NGLNG0G-ys63cDbv0SV7HzRUnUy-QYkSOkONKwWU4haV6JZe8pjd2nt1MYIBatAZKU1XjTVFEoYvT3by60c3erzW_qdPiL9CY_KrXB8rfz0G00 categories: Structural tags: - Java diff --git a/servant/etc/servant.urm.puml b/servant/etc/servant.urm.puml deleted file mode 100644 index 96dee04bc..000000000 --- a/servant/etc/servant.urm.puml +++ /dev/null @@ -1,56 +0,0 @@ -@startuml -package com.iluwatar.servant { - class App { - - LOGGER : Logger {static} - ~ jenkins : Servant {static} - ~ travis : Servant {static} - + App() - + main(args : String[]) {static} - + scenario(servant : Servant, compliment : int) {static} - } - class King { - - complimentReceived : boolean - - isDrunk : boolean - - isHappy : boolean - - isHungry : boolean - + King() - + changeMood() - + getDrink() - + getFed() - + getMood() : boolean - + receiveCompliments() - } - class Queen { - - complimentReceived : boolean - - isDrunk : boolean - - isFlirty : boolean - - isHappy : boolean - - isHungry : boolean - + Queen() - + changeMood() - + getDrink() - + getFed() - + getMood() : boolean - + receiveCompliments() - + setFlirtiness(f : boolean) - } - ~interface Royalty { - + changeMood() {abstract} - + getDrink() {abstract} - + getFed() {abstract} - + getMood() : boolean {abstract} - + receiveCompliments() {abstract} - } - class Servant { - + name : String - + Servant(name : String) - + checkIfYouWillBeHanged(tableGuests : List) : boolean - + feed(r : Royalty) - + giveCompliments(r : Royalty) - + giveWine(r : Royalty) - } -} -App --> "-jenkins" Servant -King ..|> Royalty -Queen ..|> Royalty -@enduml \ No newline at end of file diff --git a/servant/pom.xml b/servant/pom.xml index 4a0c753de..daa44d223 100644 --- a/servant/pom.xml +++ b/servant/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT servant diff --git a/service-layer/README.md b/service-layer/README.md index af393947f..9b685d4e3 100644 --- a/service-layer/README.md +++ b/service-layer/README.md @@ -3,7 +3,6 @@ layout: pattern title: Service Layer folder: service-layer permalink: /patterns/service-layer/ -pumlid: LOl93SCm3C1MQGUmzUysgY8aAcJ5q96WszVV_aW2V8gHriRb-ZWoPxm07E--Inxrhc2dqv8jEvq3HEl6H8SFNjWs3jcjJSnaju21iG3MSmbnK_mkuwJ_qij7dpNq1m00 categories: Architectural tags: - Java diff --git a/service-layer/etc/service-layer.urm.puml b/service-layer/etc/service-layer.urm.puml deleted file mode 100644 index 6cf9b938d..000000000 --- a/service-layer/etc/service-layer.urm.puml +++ /dev/null @@ -1,161 +0,0 @@ -@startuml -left to right direction -package com.iluwatar.servicelayer.hibernate { - class HibernateUtil { - - LOGGER : Logger {static} - - sessionFactory : SessionFactory {static} - - HibernateUtil() - + dropSession() {static} - + getSessionFactory() : SessionFactory {static} - } -} -package com.iluwatar.servicelayer.common { - abstract class BaseEntity { - - version : Long - + BaseEntity() - + getId() : Long {abstract} - + getName() : String {abstract} - + setId(Long) {abstract} - + setName(String) {abstract} - } - interface Dao { - + delete(E extends BaseEntity) {abstract} - + find(Long) : E extends BaseEntity {abstract} - + findAll() : List {abstract} - + merge(E extends BaseEntity) : E extends BaseEntity {abstract} - + persist(E extends BaseEntity) {abstract} - } - abstract class DaoBaseImpl { - # persistentClass : Class - + DaoBaseImpl() - + delete(entity : E extends BaseEntity) - + find(id : Long) : E extends BaseEntity - + findAll() : List - # getSession() : Session - + merge(entity : E extends BaseEntity) : E extends BaseEntity - + persist(entity : E extends BaseEntity) - } -} -package com.iluwatar.servicelayer.magic { - interface MagicService { - + findAllSpellbooks() : List {abstract} - + findAllSpells() : List {abstract} - + findAllWizards() : List {abstract} - + findWizardsWithSpell(String) : List {abstract} - + findWizardsWithSpellbook(String) : List {abstract} - } - class MagicServiceImpl { - - spellDao : SpellDao - - spellbookDao : SpellbookDao - - wizardDao : WizardDao - + MagicServiceImpl(wizardDao : WizardDao, spellbookDao : SpellbookDao, spellDao : SpellDao) - + findAllSpellbooks() : List - + findAllSpells() : List - + findAllWizards() : List - + findWizardsWithSpell(name : String) : List - + findWizardsWithSpellbook(name : String) : List - } -} -package com.iluwatar.servicelayer.wizard { - class Wizard { - - id : Long - - name : String - - spellbooks : Set - + Wizard() - + Wizard(name : String) - + addSpellbook(spellbook : Spellbook) - + getId() : Long - + getName() : String - + getSpellbooks() : Set - + setId(id : Long) - + setName(name : String) - + setSpellbooks(spellbooks : Set) - + toString() : String - } - interface WizardDao { - + findByName(String) : Wizard {abstract} - } - class WizardDaoImpl { - + WizardDaoImpl() - + findByName(name : String) : Wizard - } -} -package com.iluwatar.servicelayer.spellbook { - class Spellbook { - - id : Long - - name : String - - spells : Set - - wizards : Set - + Spellbook() - + Spellbook(name : String) - + addSpell(spell : Spell) - + getId() : Long - + getName() : String - + getSpells() : Set - + getWizards() : Set - + setId(id : Long) - + setName(name : String) - + setSpells(spells : Set) - + setWizards(wizards : Set) - + toString() : String - } - interface SpellbookDao { - + findByName(String) : Spellbook {abstract} - } - class SpellbookDaoImpl { - + SpellbookDaoImpl() - + findByName(name : String) : Spellbook - } -} -package com.iluwatar.servicelayer.spell { - class Spell { - - id : Long - - name : String - - spellbook : Spellbook - + Spell() - + Spell(name : String) - + getId() : Long - + getName() : String - + getSpellbook() : Spellbook - + setId(id : Long) - + setName(name : String) - + setSpellbook(spellbook : Spellbook) - + toString() : String - } - interface SpellDao { - + findByName(String) : Spell {abstract} - } - class SpellDaoImpl { - + SpellDaoImpl() - + findByName(name : String) : Spell - } -} -package com.iluwatar.servicelayer.app { - class App { - - LOGGER : Logger {static} - + App() - + initData() {static} - + main(args : String[]) {static} - + queryData() {static} - } -} -MagicServiceImpl --> "-wizardDao" WizardDao -MagicServiceImpl --> "-spellbookDao" SpellbookDao -MagicServiceImpl --> "-spellDao" SpellDao -Spellbook --> "-spells" Spell -Spellbook --> "-wizards" Wizard -DaoBaseImpl ..|> Dao -MagicServiceImpl ..|> MagicService -Spell --|> BaseEntity -SpellDao --|> Dao -SpellDaoImpl ..|> SpellDao -SpellDaoImpl --|> DaoBaseImpl -Spellbook --|> BaseEntity -SpellbookDao --|> Dao -SpellbookDaoImpl ..|> SpellbookDao -SpellbookDaoImpl --|> DaoBaseImpl -Wizard --|> BaseEntity -WizardDao --|> Dao -WizardDaoImpl ..|> WizardDao -WizardDaoImpl --|> DaoBaseImpl -@enduml diff --git a/service-layer/pom.xml b/service-layer/pom.xml index 3174e95ed..6edbeba44 100644 --- a/service-layer/pom.xml +++ b/service-layer/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT service-layer diff --git a/service-locator/README.md b/service-locator/README.md index 479c9ed0f..974a2a5fe 100644 --- a/service-locator/README.md +++ b/service-locator/README.md @@ -3,7 +3,6 @@ layout: pattern title: Service Locator folder: service-locator permalink: /patterns/service-locator/ -pumlid: NSjB3iCm203HgxG7iDdtDeIWX0fZYqzo_MRTtUX9ynOZhPtBzNLchlW0EDxza3nhgs2dQScMdUO0qRenqU6B5xQTGmvh2pFPBM1WF07FSmbnqqcOqu6J_gsNZxvgw0y0 categories: Structural tags: - Java diff --git a/service-locator/etc/service-locator.urm.puml b/service-locator/etc/service-locator.urm.puml deleted file mode 100644 index 38fe7ea1b..000000000 --- a/service-locator/etc/service-locator.urm.puml +++ /dev/null @@ -1,41 +0,0 @@ -@startuml -package com.iluwatar.servicelocator { - class App { - + App() - + main(args : String[]) {static} - } - class InitContext { - - LOGGER : Logger {static} - + InitContext() - + lookup(serviceName : String) : Object - } - interface Service { - + execute() {abstract} - + getId() : int {abstract} - + getName() : String {abstract} - } - class ServiceCache { - - LOGGER : Logger {static} - - serviceCache : Map - + ServiceCache() - + addService(newService : Service) - + getService(serviceName : String) : Service - } - class ServiceImpl { - - LOGGER : Logger {static} - - id : int - - serviceName : String - + ServiceImpl(serviceName : String) - + execute() - + getId() : int - + getName() : String - } - class ServiceLocator { - - serviceCache : ServiceCache {static} - - ServiceLocator() - + getService(serviceJndiName : String) : Service {static} - } -} -ServiceLocator --> "-serviceCache" ServiceCache -ServiceImpl ..|> Service -@enduml \ No newline at end of file diff --git a/service-locator/pom.xml b/service-locator/pom.xml index 23c54c08d..7cd4028ff 100644 --- a/service-locator/pom.xml +++ b/service-locator/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT service-locator diff --git a/singleton/README.md b/singleton/README.md index 1be304d8e..90a845846 100644 --- a/singleton/README.md +++ b/singleton/README.md @@ -3,7 +3,6 @@ layout: pattern title: Singleton folder: singleton permalink: /patterns/singleton/ -pumlid: HSV14SCm20J0Lk82BFxf1ikCh0n26ZZizfDVVhjRjwfvIhg-Bc35cyZvAQtZoYD3l4w364gTWxhcms2d3z-ydnAzsRuO4BUWmV43HRUcWcaagF-Lz55M3lq2 categories: Creational tags: - Java diff --git a/singleton/pom.xml b/singleton/pom.xml index 77226821d..00794e25a 100644 --- a/singleton/pom.xml +++ b/singleton/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT singleton diff --git a/specification/README.md b/specification/README.md index dc47f4970..564830653 100644 --- a/specification/README.md +++ b/specification/README.md @@ -3,7 +3,6 @@ layout: pattern title: Specification folder: specification permalink: /patterns/specification/ -pumlid: LSX14i8m20NGg-W16lRU1YcsE0d9mCTUNxVkthoxkVJQjQBVJc3bWoZuQeVXh6UbXao7EfhCGTRhOd3Gcp-yxPfs-BOOqF2amVa3vLAnbmd3ffD2_gTLZBPgz2y0 categories: Behavioral tags: - Java diff --git a/specification/etc/specification.urm.puml b/specification/etc/specification.urm.puml deleted file mode 100644 index fd3cbb20e..000000000 --- a/specification/etc/specification.urm.puml +++ /dev/null @@ -1,107 +0,0 @@ -@startuml -package com.iluwatar.specification.creature { - abstract class AbstractCreature { - - color : Color - - movement : Movement - - name : String - - size : Size - + AbstractCreature(name : String, size : Size, movement : Movement, color : Color) - + getColor() : Color - + getMovement() : Movement - + getName() : String - + getSize() : Size - + toString() : String - } - interface Creature { - + getColor() : Color {abstract} - + getMovement() : Movement {abstract} - + getName() : String {abstract} - + getSize() : Size {abstract} - } - class Dragon { - + Dragon() - } - class Goblin { - + Goblin() - } - class KillerBee { - + KillerBee() - } - class Octopus { - + Octopus() - } - class Shark { - + Shark() - } - class Troll { - + Troll() - } -} -package com.iluwatar.specification.property { - enum Color { - + DARK {static} - + GREEN {static} - + LIGHT {static} - + RED {static} - - title : String - + toString() : String - + valueOf(name : String) : Color {static} - + values() : Color[] {static} - } - enum Movement { - + FLYING {static} - + SWIMMING {static} - + WALKING {static} - - title : String - + toString() : String - + valueOf(name : String) : Movement {static} - + values() : Movement[] {static} - } - enum Size { - + LARGE {static} - + NORMAL {static} - + SMALL {static} - - title : String - + toString() : String - + valueOf(name : String) : Size {static} - + values() : Size[] {static} - } -} -package com.iluwatar.specification.selector { - class ColorSelector { - - c : Color - + ColorSelector(c : Color) - + test(t : Creature) : boolean - } - class MovementSelector { - - m : Movement - + MovementSelector(m : Movement) - + test(t : Creature) : boolean - } - class SizeSelector { - - s : Size - + SizeSelector(s : Size) - + test(t : Creature) : boolean - } -} -package com.iluwatar.specification.app { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } -} -SizeSelector --> "-s" Size -AbstractCreature --> "-color" Color -MovementSelector --> "-m" Movement -AbstractCreature --> "-movement" Movement -AbstractCreature --> "-size" Size -ColorSelector --> "-c" Color -AbstractCreature ..|> Creature -Dragon --|> AbstractCreature -Goblin --|> AbstractCreature -KillerBee --|> AbstractCreature -Octopus --|> AbstractCreature -Shark --|> AbstractCreature -Troll --|> AbstractCreature -@enduml \ No newline at end of file diff --git a/specification/pom.xml b/specification/pom.xml index 3a4fd371b..76732b964 100644 --- a/specification/pom.xml +++ b/specification/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT specification diff --git a/state/README.md b/state/README.md index 34ad8074c..549afa61f 100644 --- a/state/README.md +++ b/state/README.md @@ -3,7 +3,6 @@ layout: pattern title: State folder: state permalink: /patterns/state/ -pumlid: 9SRH3O0m20N0LNG0ox_RO2LQqz867hg-9jxNpKLpZLt2wdG2mrSYuoST1MTiuMAvAqIHSczKQZmCDhhuvcKNBuSkWm4nTMhiNyZ141BaVocifH6jlW00 categories: Behavioral tags: - Java diff --git a/state/etc/state.urm.puml b/state/etc/state.urm.puml deleted file mode 100644 index 207a227d8..000000000 --- a/state/etc/state.urm.puml +++ /dev/null @@ -1,39 +0,0 @@ -@startuml -package com.iluwatar.state { - class AngryState { - - LOGGER : Logger {static} - - mammoth : Mammoth - + AngryState(mammoth : Mammoth) - + observe() - + onEnterState() - } - class App { - + App() - + main(args : String[]) {static} - } - class Mammoth { - - state : State - + Mammoth() - - changeStateTo(newState : State) - + observe() - + timePasses() - + toString() : String - } - class PeacefulState { - - LOGGER : Logger {static} - - mammoth : Mammoth - + PeacefulState(mammoth : Mammoth) - + observe() - + onEnterState() - } - interface State { - + observe() {abstract} - + onEnterState() {abstract} - } -} -PeacefulState --> "-mammoth" Mammoth -AngryState --> "-mammoth" Mammoth -Mammoth --> "-state" State -AngryState ..|> State -PeacefulState ..|> State -@enduml \ No newline at end of file diff --git a/state/pom.xml b/state/pom.xml index 44404d5a9..256a5e9e2 100644 --- a/state/pom.xml +++ b/state/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT state diff --git a/step-builder/README.md b/step-builder/README.md index 65d356c2e..bc636e37a 100644 --- a/step-builder/README.md +++ b/step-builder/README.md @@ -3,7 +3,6 @@ layout: pattern title: Step Builder folder: step-builder permalink: /patterns/step-builder/ -pumlid: LOZ93SCm3C1MQGQmzUysYYqaAcJ5q96i7t_x8KXkh4soKvfypeZfNm33fnuSP-xfPEtI88tQhW4i-M2WmGzlB9sS3oqJ8yZKOQ0lWOLPzcJfAoZQtwXfeyuSyW80 categories: Creational tags: - Java diff --git a/step-builder/etc/step-builder.urm.puml b/step-builder/etc/step-builder.urm.puml deleted file mode 100644 index dc6087340..000000000 --- a/step-builder/etc/step-builder.urm.puml +++ /dev/null @@ -1,91 +0,0 @@ -@startuml -package com.iluwatar.stepbuilder { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } - class Character { - - abilities : List - - fighterClass : String - - name : String - - spell : String - - weapon : String - - wizardClass : String - + Character(name : String) - + getAbilities() : List - + getFighterClass() : String - + getName() : String - + getSpell() : String - + getWeapon() : String - + getWizardClass() : String - + setAbilities(abilities : List) - + setFighterClass(fighterClass : String) - + setName(name : String) - + setSpell(spell : String) - + setWeapon(weapon : String) - + setWizardClass(wizardClass : String) - + toString() : String - } - class CharacterStepBuilder { - - CharacterStepBuilder() - + newBuilder() : NameStep {static} - } - interface AbilityStep { - + noAbilities() : BuildStep {abstract} - + noMoreAbilities() : BuildStep {abstract} - + withAbility(String) : AbilityStep {abstract} - } - interface BuildStep { - + build() : Character {abstract} - } - -class CharacterSteps { - - abilities : List - - fighterClass : String - - name : String - - spell : String - - weapon : String - - wizardClass : String - - CharacterSteps() - + build() : Character - + fighterClass(fighterClass : String) : WeaponStep - + name(name : String) : ClassStep - + noAbilities() : BuildStep - + noMoreAbilities() : BuildStep - + noSpell() : BuildStep - + noWeapon() : BuildStep - + withAbility(ability : String) : AbilityStep - + withSpell(spell : String) : AbilityStep - + withWeapon(weapon : String) : AbilityStep - + wizardClass(wizardClass : String) : SpellStep - } - interface ClassStep { - + fighterClass(String) : WeaponStep {abstract} - + wizardClass(String) : SpellStep {abstract} - } - interface NameStep { - + name(String) : ClassStep {abstract} - } - interface SpellStep { - + noSpell() : BuildStep {abstract} - + withSpell(String) : AbilityStep {abstract} - } - interface WeaponStep { - + noWeapon() : BuildStep {abstract} - + withWeapon(String) : AbilityStep {abstract} - } -} -WeaponStep ..+ CharacterStepBuilder -CharacterSteps ..+ CharacterStepBuilder -AbilityStep ..+ CharacterStepBuilder -SpellStep ..+ CharacterStepBuilder -ClassStep ..+ CharacterStepBuilder -NameStep ..+ CharacterStepBuilder -BuildStep ..+ CharacterStepBuilder -CharacterSteps ..|> NameStep -CharacterSteps ..|> ClassStep -CharacterSteps ..|> WeaponStep -CharacterSteps ..|> SpellStep -CharacterSteps ..|> AbilityStep -CharacterSteps ..|> BuildStep -@enduml \ No newline at end of file diff --git a/step-builder/pom.xml b/step-builder/pom.xml index fc7c7232e..432d5477a 100644 --- a/step-builder/pom.xml +++ b/step-builder/pom.xml @@ -30,7 +30,7 @@ java-design-patterns com.iluwatar - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT step-builder diff --git a/strategy/README.md b/strategy/README.md index 697b6cc88..f07397f67 100644 --- a/strategy/README.md +++ b/strategy/README.md @@ -3,7 +3,6 @@ layout: pattern title: Strategy folder: strategy permalink: /patterns/strategy/ -pumlid: FSV13OCm30NGLM00udktCS4AGOaJsTz5tRwSkBstLiqj3WbhombC_n0PtwbKdB67Y-MX44NAerDjSJFOwE8lRuTuBRfD1iJKgRC_88SnfFn8aD-ai9vczFO7 categories: Behavioral tags: - Java diff --git a/strategy/etc/strategy.urm.puml b/strategy/etc/strategy.urm.puml deleted file mode 100644 index 8b9daabb9..000000000 --- a/strategy/etc/strategy.urm.puml +++ /dev/null @@ -1,37 +0,0 @@ -@startuml -package com.iluwatar.strategy { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } - class DragonSlayer { - - strategy : DragonSlayingStrategy - + DragonSlayer(strategy : DragonSlayingStrategy) - + changeStrategy(strategy : DragonSlayingStrategy) - + goToBattle() - } - interface DragonSlayingStrategy { - + execute() {abstract} - } - class MeleeStrategy { - - LOGGER : Logger {static} - + MeleeStrategy() - + execute() - } - class ProjectileStrategy { - - LOGGER : Logger {static} - + ProjectileStrategy() - + execute() - } - class SpellStrategy { - - LOGGER : Logger {static} - + SpellStrategy() - + execute() - } -} -DragonSlayer --> "-strategy" DragonSlayingStrategy -MeleeStrategy ..|> DragonSlayingStrategy -ProjectileStrategy ..|> DragonSlayingStrategy -SpellStrategy ..|> DragonSlayingStrategy -@enduml \ No newline at end of file diff --git a/strategy/pom.xml b/strategy/pom.xml index e6fc4cd53..cd2d7e9a0 100644 --- a/strategy/pom.xml +++ b/strategy/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT strategy diff --git a/template-method/README.md b/template-method/README.md index 65381d0ce..ad972f06b 100644 --- a/template-method/README.md +++ b/template-method/README.md @@ -3,7 +3,6 @@ layout: pattern title: Template method folder: template-method permalink: /patterns/template-method/ -pumlid: NSZ13SCW30NGLPe1mFTkuu0Lg6n0vZjPlpttzlIEFef6bN1zDM3jDv7paw-E5cTiyJ87P22NQTGr7WOxVVZcL6NtQwJ5WFZOPBn_88WjPKWoGPkL1EN_ShZb5QPV categories: Behavioral tags: - Java diff --git a/template-method/etc/template-method.urm.puml b/template-method/etc/template-method.urm.puml deleted file mode 100644 index a6e2dc3d2..000000000 --- a/template-method/etc/template-method.urm.puml +++ /dev/null @@ -1,39 +0,0 @@ -@startuml -package com.iluwatar.templatemethod { - class App { - + App() - + main(args : String[]) {static} - } - class HalflingThief { - - method : StealingMethod - + HalflingThief(method : StealingMethod) - + changeMethod(method : StealingMethod) - + steal() - } - class HitAndRunMethod { - - LOGGER : Logger {static} - + HitAndRunMethod() - # confuseTarget(target : String) - # pickTarget() : String - # stealTheItem(target : String) - } - abstract class StealingMethod { - - LOGGER : Logger {static} - + StealingMethod() - # confuseTarget(String) {abstract} - # pickTarget() : String {abstract} - + steal() - # stealTheItem(String) {abstract} - } - class SubtleMethod { - - LOGGER : Logger {static} - + SubtleMethod() - # confuseTarget(target : String) - # pickTarget() : String - # stealTheItem(target : String) - } -} -HalflingThief --> "-method" StealingMethod -HitAndRunMethod --|> StealingMethod -SubtleMethod --|> StealingMethod -@enduml \ No newline at end of file diff --git a/template-method/pom.xml b/template-method/pom.xml index 0bd5bdc43..916d61b0b 100644 --- a/template-method/pom.xml +++ b/template-method/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT template-method diff --git a/thread-pool/README.md b/thread-pool/README.md index 473494ef9..9806fa8e0 100644 --- a/thread-pool/README.md +++ b/thread-pool/README.md @@ -3,7 +3,6 @@ layout: pattern title: Thread Pool folder: thread-pool permalink: /patterns/thread-pool/ -pumlid: JSV14SCW30J0Lk82GFzq8uF6a1624IUx_UIPt-xHhMXK2TTN0zP-4pa_-UfeSSOMBzCWXbpceAxnCDZfmpUdAhjVbXO3uhPfyFw1q5oufZMdag3yFuUFl6Be5m00 categories: Concurrency tags: - Java diff --git a/thread-pool/etc/thread-pool.urm.puml b/thread-pool/etc/thread-pool.urm.puml deleted file mode 100644 index 251033c81..000000000 --- a/thread-pool/etc/thread-pool.urm.puml +++ /dev/null @@ -1,37 +0,0 @@ -@startuml -package com.iluwatar.threadpool { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } - class CoffeeMakingTask { - - TIME_PER_CUP : int {static} - + CoffeeMakingTask(numCups : int) - + toString() : String - } - class PotatoPeelingTask { - - TIME_PER_POTATO : int {static} - + PotatoPeelingTask(numPotatoes : int) - + toString() : String - } - abstract class Task { - - ID_GENERATOR : AtomicInteger {static} - - id : int - - timeMs : int - + Task(timeMs : int) - + getId() : int - + getTimeMs() : int - + toString() : String - } - class Worker { - - LOGGER : Logger {static} - - task : Task - + Worker(task : Task) - + run() - } -} -Worker --> "-task" Task -CoffeeMakingTask --|> Task -PotatoPeelingTask --|> Task -@enduml \ No newline at end of file diff --git a/thread-pool/pom.xml b/thread-pool/pom.xml index f34238176..94fce2b16 100644 --- a/thread-pool/pom.xml +++ b/thread-pool/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT thread-pool diff --git a/throttling/README.md b/throttling/README.md index efc966d04..73d982bff 100644 --- a/throttling/README.md +++ b/throttling/README.md @@ -1,17 +1,16 @@ --- layout: pattern -title: Throttling pattern +title: Throttling folder: throttling permalink: /patterns/throttling/ +categories: Behavioral tags: - Java - Difficulty-Beginner - - Throttling --- ## Intent Ensure that a given client is not able to access service resources more than the assigned limit. -![alt text](./etc/throttling-patern.png "Throttling pattern") ## Applicability The Throttling pattern should be used: diff --git a/throttling/etc/throttling.urm.puml b/throttling/etc/throttling.urm.puml deleted file mode 100644 index 8c97da50a..000000000 --- a/throttling/etc/throttling.urm.puml +++ /dev/null @@ -1,29 +0,0 @@ -@startuml -package com.iluwatar.tls { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - - makeServiceCalls(service : B2BService) {static} - } - ~class B2BService { - - LOGGER : Logger {static} - - callsCounter : int - - tenant : Tenant - + B2BService(tenant : Tenant) - + dummyCustomerApi() : int - + getCurrentCallsCount() : int - - getRandomCustomerId() : int - } - class Tenant { - - allowedCallsPerSecond : int - - name : String - + Tenant(name : String, allowedCallsPerSecond : int) - + getAllowedCallsPerSecond() : int - + getName() : String - + setAllowedCallsPerSecond(allowedCallsPerSecond : int) - + setName(name : String) - } -} -B2BService --> "-tenant" Tenant -@enduml \ No newline at end of file diff --git a/throttling/pom.xml b/throttling/pom.xml index 2cbd7bf9e..7c2ee8b9a 100644 --- a/throttling/pom.xml +++ b/throttling/pom.xml @@ -29,7 +29,7 @@ java-design-patterns com.iluwatar - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT 4.0.0 diff --git a/throttling/src/main/java/com/iluwatar/throttling/B2BService.java b/throttling/src/main/java/com/iluwatar/throttling/B2BService.java index c9acd4b73..51ed492eb 100644 --- a/throttling/src/main/java/com/iluwatar/throttling/B2BService.java +++ b/throttling/src/main/java/com/iluwatar/throttling/B2BService.java @@ -46,7 +46,7 @@ class B2BService { */ public int dummyCustomerApi(Tenant tenant) { String tenantName = tenant.getName(); - int count = CallsCount.getCount(tenantName); + long count = CallsCount.getCount(tenantName); LOGGER.debug("Counter for {} : {} ", tenant.getName(), count); if (count >= tenant.getAllowedCallsPerSecond()) { LOGGER.error("API access per second limit reached for: {}", tenantName); diff --git a/throttling/src/main/java/com/iluwatar/throttling/CallsCount.java b/throttling/src/main/java/com/iluwatar/throttling/CallsCount.java index 81195b074..9b274849a 100644 --- a/throttling/src/main/java/com/iluwatar/throttling/CallsCount.java +++ b/throttling/src/main/java/com/iluwatar/throttling/CallsCount.java @@ -22,9 +22,13 @@ */ package com.iluwatar.throttling; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicLong; /** * A class to keep track of the counter of different Tenants @@ -32,16 +36,16 @@ import java.util.concurrent.ConcurrentHashMap; * */ public final class CallsCount { - private static Map tenantCallsCount = new ConcurrentHashMap<>(); + + private static final Logger LOGGER = LoggerFactory.getLogger(CallsCount.class); + private static Map tenantCallsCount = new ConcurrentHashMap<>(); /** * Add a new tenant to the map. * @param tenantName name of the tenant. */ public static void addTenant(String tenantName) { - if (!tenantCallsCount.containsKey(tenantName)) { - tenantCallsCount.put(tenantName, 0); - } + tenantCallsCount.putIfAbsent(tenantName, new AtomicLong(0)); } /** @@ -49,7 +53,7 @@ public final class CallsCount { * @param tenantName name of the tenant. */ public static void incrementCount(String tenantName) { - tenantCallsCount.put(tenantName, tenantCallsCount.get(tenantName) + 1); + tenantCallsCount.get(tenantName).incrementAndGet(); } /** @@ -57,16 +61,17 @@ public final class CallsCount { * @param tenantName name of the tenant. * @return the count of the tenant. */ - public static int getCount(String tenantName) { - return tenantCallsCount.get(tenantName); + public static long getCount(String tenantName) { + return tenantCallsCount.get(tenantName).get(); } /** * Resets the count of all the tenants in the map. */ public static void reset() { - for (Entry e : tenantCallsCount.entrySet()) { - tenantCallsCount.put(e.getKey(), 0); + LOGGER.debug("Resetting the map."); + for (Entry e : tenantCallsCount.entrySet()) { + tenantCallsCount.put(e.getKey(), new AtomicLong(0)); } } } diff --git a/throttling/src/main/java/com/iluwatar/throttling/timer/ThrottleTimerImpl.java b/throttling/src/main/java/com/iluwatar/throttling/timer/ThrottleTimerImpl.java index 51c5e3c28..4ff4ce246 100644 --- a/throttling/src/main/java/com/iluwatar/throttling/timer/ThrottleTimerImpl.java +++ b/throttling/src/main/java/com/iluwatar/throttling/timer/ThrottleTimerImpl.java @@ -35,7 +35,7 @@ import com.iluwatar.throttling.CallsCount; * @author drastogi * */ -public class ThrottleTimerImpl implements Throttler{ +public class ThrottleTimerImpl implements Throttler { private int throttlePeriod; diff --git a/throttling/src/test/java/com/iluwatar/throttling/B2BServiceTest.java b/throttling/src/test/java/com/iluwatar/throttling/B2BServiceTest.java index b9ca1a1d8..aaab62b3a 100644 --- a/throttling/src/test/java/com/iluwatar/throttling/B2BServiceTest.java +++ b/throttling/src/test/java/com/iluwatar/throttling/B2BServiceTest.java @@ -36,14 +36,13 @@ public class B2BServiceTest { @Test public void dummyCustomerApiTest() { Tenant tenant = new Tenant("testTenant", 2); - Throttler timer = new ThrottleTimerImpl(10); + Throttler timer = new ThrottleTimerImpl(100); B2BService service = new B2BService(timer); - + for (int i = 0; i < 5; i++) { service.dummyCustomerApi(tenant); } - - int counter = CallsCount.getCount(tenant.getName()); + long counter = CallsCount.getCount(tenant.getName()); Assert.assertTrue("Counter limit must be reached", counter == 2); } } diff --git a/tls/etc/tls.urm.puml b/tls/etc/tls.urm.puml deleted file mode 100644 index d2eedb371..000000000 --- a/tls/etc/tls.urm.puml +++ /dev/null @@ -1,23 +0,0 @@ -@startuml -package com.iluwatar.tls { - class App { - + App() - + main(args : String[]) {static} - - printAndCountDates(res : Result) : int {static} - - printAndCountExceptions(res : Result) : int {static} - } - class DateFormatCallable { - - dateValue : String - - df : ThreadLocal - + DateFormatCallable(inDateFormat : String, inDateValue : String) - + call() : Result - } - class Result { - - dateList : List - - exceptionList : List - + Result() - + getDateList() : List - + getExceptionList() : List - } -} -@enduml \ No newline at end of file diff --git a/tls/pom.xml b/tls/pom.xml index 460c5e7ea..40d6b2b21 100644 --- a/tls/pom.xml +++ b/tls/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT tls diff --git a/tolerant-reader/README.md b/tolerant-reader/README.md index 5d1cf80fd..be0085f2c 100644 --- a/tolerant-reader/README.md +++ b/tolerant-reader/README.md @@ -3,7 +3,6 @@ layout: pattern title: Tolerant Reader folder: tolerant-reader permalink: /patterns/tolerant-reader/ -pumlid: NSZ14SCm20NHLf829ExfXaYChGn26lZ4xSVdtFRjSrZJx9AkZnFOyI9olkenSEOxGxmjWnXgMvE6viLWfmz_kNI9SLZP38XRqEIuWx1Kd0t5XVjjGVj_DNtMdLD_ categories: Integration tags: - Java diff --git a/tolerant-reader/etc/tolerant-reader.urm.puml b/tolerant-reader/etc/tolerant-reader.urm.puml deleted file mode 100644 index a73394a4e..000000000 --- a/tolerant-reader/etc/tolerant-reader.urm.puml +++ /dev/null @@ -1,39 +0,0 @@ -@startuml -package com.iluwatar.tolerantreader { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } - class RainbowFish { - - age : int - - lengthMeters : int - - name : String - - serialVersionUID : long {static} - - weightTons : int - + RainbowFish(name : String, age : int, lengthMeters : int, weightTons : int) - + getAge() : int - + getLengthMeters() : int - + getName() : String - + getWeightTons() : int - } - class RainbowFishSerializer { - - RainbowFishSerializer() - + readV1(filename : String) : RainbowFish {static} - + writeV1(rainbowFish : RainbowFish, filename : String) {static} - + writeV2(rainbowFish : RainbowFishV2, filename : String) {static} - } - class RainbowFishV2 { - - angry : boolean - - hungry : boolean - - serialVersionUID : long {static} - - sleeping : boolean - + RainbowFishV2(name : String, age : int, lengthMeters : int, weightTons : int) - + RainbowFishV2(name : String, age : int, lengthMeters : int, weightTons : int, sleeping : boolean, hungry : boolean, angry : boolean) - + getAngry() : boolean - + getHungry() : boolean - + getSleeping() : boolean - } -} -RainbowFishV2 --|> RainbowFish -@enduml \ No newline at end of file diff --git a/tolerant-reader/pom.xml b/tolerant-reader/pom.xml index 99a2cf880..7e3561f80 100644 --- a/tolerant-reader/pom.xml +++ b/tolerant-reader/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT tolerant-reader diff --git a/twin/README.md b/twin/README.md index 092032a55..3795236bb 100644 --- a/twin/README.md +++ b/twin/README.md @@ -3,7 +3,6 @@ layout: pattern title: Twin folder: twin permalink: /patterns/twin/ -pumlid: 7SR13OCm30NGLUW0n7UsCS42eyH4zdUpFbNVwNtKQij3qjjo0ICs8kTPJiMLUuPuVGnYAFNff2qdWvrk_l9wIEXfws10t88wno-4gKQ2-az9xsLaRoy0 categories: Creational tags: - Java diff --git a/twin/etc/twin.urm.puml b/twin/etc/twin.urm.puml deleted file mode 100644 index e48298f18..000000000 --- a/twin/etc/twin.urm.puml +++ /dev/null @@ -1,27 +0,0 @@ -@startuml -package com.iluwatar.twin { - class App { - + App() - + main(args : String[]) {static} - - waiting() {static} - } - class BallItem { - - LOGGER : Logger {static} - - isSuspended : boolean - - twin : BallThread - + BallItem() - + click() - + doDraw() - + move() - + setTwin(twin : BallThread) - } - abstract class GameItem { - - LOGGER : Logger {static} - + GameItem() - + click() {abstract} - + doDraw() {abstract} - + draw() - } -} -BallItem --|> GameItem -@enduml \ No newline at end of file diff --git a/twin/pom.xml b/twin/pom.xml index 013406215..62d138fd9 100644 --- a/twin/pom.xml +++ b/twin/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT twin diff --git a/unit-of-work/README.md b/unit-of-work/README.md new file mode 100644 index 000000000..b2fbde8ff --- /dev/null +++ b/unit-of-work/README.md @@ -0,0 +1,31 @@ +--- +layout: pattern +title: Unit Of Work +folder: unit-of-work +permalink: /patterns/unit-of-work/ + +categories: Architectural +tags: + - Java + - KISS + - YAGNI + - Difficulty-Beginner +--- + +## Intent +When a business transaction is completed, all the these updates are sent as one + big unit of work to be persisted in a database in one go so as to minimize database trips. + +![alt text](etc/unit-of-work.urm.png "unit-of-work") + +## Applicability +Use the Unit Of Work pattern when + +* To optimize the time taken for database transactions. +* To send changes to database as a unit of work which ensures atomicity of the transaction. +* To reduce number of database calls. + +## Credits + +* [Design Pattern - Unit Of Work Pattern](https://www.codeproject.com/Articles/581487/Unit-of-Work-Design-Pattern) +* [Unit Of Work](https://martinfowler.com/eaaCatalog/unitOfWork.html) diff --git a/proxy/etc/proxy.ucls b/unit-of-work/etc/unit-of-work.ucls similarity index 57% rename from proxy/etc/proxy.ucls rename to unit-of-work/etc/unit-of-work.ucls index 76b5f0160..98181f805 100644 --- a/proxy/etc/proxy.ucls +++ b/unit-of-work/etc/unit-of-work.ucls @@ -1,68 +1,64 @@ - - - + + + - - - - - - - - - + + - - + + - - + + - - - - + + + + + + + + + + + + + + + - + - - - - - - - - diff --git a/unit-of-work/etc/unit-of-work.urm.png b/unit-of-work/etc/unit-of-work.urm.png new file mode 100644 index 000000000..bb192af54 Binary files /dev/null and b/unit-of-work/etc/unit-of-work.urm.png differ diff --git a/unit-of-work/etc/unit-of-work.urm.puml b/unit-of-work/etc/unit-of-work.urm.puml new file mode 100644 index 000000000..7767a2e32 --- /dev/null +++ b/unit-of-work/etc/unit-of-work.urm.puml @@ -0,0 +1,48 @@ +@startuml +package com.iluwatar.unitofwork { + class App { + + App() + + main(args : String[]) {static} + } + interface IUnitOfWork { + + DELETE : String {static} + + INSERT : String {static} + + MODIFY : String {static} + + commit() {abstract} + + registerDeleted(T) {abstract} + + registerModified(T) {abstract} + + registerNew(T) {abstract} + } + class Student { + - address : String + - id : Integer + - name : String + + Student(id : Integer, name : String, address : String) + + getAddress() : String + + getId() : Integer + + getName() : String + } + class StudentDatabase { + + StudentDatabase() + + delete(student : Student) + + insert(student : Student) + + modify(student : Student) + } + class StudentRepository { + - LOGGER : Logger {static} + - context : Map> + - studentDatabase : StudentDatabase + + StudentRepository(context : Map>, studentDatabase : StudentDatabase) + + commit() + - commitDelete() + - commitInsert() + - commitModify() + - register(student : Student, operation : String) + + registerDeleted(student : Student) + + registerModified(student : Student) + + registerNew(student : Student) + } +} +StudentRepository --> "-studentDatabase" StudentDatabase +StudentRepository ..|> IUnitOfWork +@enduml \ No newline at end of file diff --git a/unit-of-work/pom.xml b/unit-of-work/pom.xml new file mode 100644 index 000000000..0d7fbf5a2 --- /dev/null +++ b/unit-of-work/pom.xml @@ -0,0 +1,25 @@ + + + + java-design-patterns + com.iluwatar + 1.18.0-SNAPSHOT + + 4.0.0 + + unit-of-work + + + junit + junit + + + org.mockito + mockito-core + + + + + \ No newline at end of file diff --git a/unit-of-work/src/main/java/com/iluwatar/unitofwork/App.java b/unit-of-work/src/main/java/com/iluwatar/unitofwork/App.java new file mode 100644 index 000000000..9b4b2f15c --- /dev/null +++ b/unit-of-work/src/main/java/com/iluwatar/unitofwork/App.java @@ -0,0 +1,52 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2014-2017 Piyush Chaudhari + * + * 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.unitofwork; + +import java.util.HashMap; +import java.util.List; + +/** + * {@link App} Application for managing student data. + */ +public class App { + /** + * + * @param args no argument sent + */ + public static void main(String[] args) { + Student ram = new Student(1, "Ram", "Street 9, Cupertino"); + Student shyam = new Student(2, "Shyam", "Z bridge, Pune"); + Student gopi = new Student(3, "Gopi", "Street 10, Mumbai"); + + HashMap> context = new HashMap<>(); + StudentDatabase studentDatabase = new StudentDatabase(); + StudentRepository studentRepository = new StudentRepository(context, studentDatabase); + + studentRepository.registerNew(ram); + studentRepository.registerModified(shyam); + studentRepository.registerDeleted(gopi); + studentRepository.commit(); + } +} diff --git a/unit-of-work/src/main/java/com/iluwatar/unitofwork/IUnitOfWork.java b/unit-of-work/src/main/java/com/iluwatar/unitofwork/IUnitOfWork.java new file mode 100644 index 000000000..e0b453498 --- /dev/null +++ b/unit-of-work/src/main/java/com/iluwatar/unitofwork/IUnitOfWork.java @@ -0,0 +1,55 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2014-2017 Piyush Chaudhari + * + * 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.unitofwork; + +/** + * @param Any generic entity + */ +public interface IUnitOfWork { + String INSERT = "INSERT"; + String DELETE = "DELETE"; + String MODIFY = "MODIFY"; + + /** + * Any register new operation occurring on UnitOfWork is only going to be performed on commit. + */ + void registerNew(T entity); + + /** + * Any register modify operation occurring on UnitOfWork is only going to be performed on commit. + */ + void registerModified(T entity); + + /** + * Any register delete operation occurring on UnitOfWork is only going to be performed on commit. + */ + void registerDeleted(T entity); + + /*** + * All UnitOfWork operations batched together executed in commit only. + */ + void commit(); + +} \ No newline at end of file diff --git a/unit-of-work/src/main/java/com/iluwatar/unitofwork/Student.java b/unit-of-work/src/main/java/com/iluwatar/unitofwork/Student.java new file mode 100644 index 000000000..5a57ccdde --- /dev/null +++ b/unit-of-work/src/main/java/com/iluwatar/unitofwork/Student.java @@ -0,0 +1,57 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2014-2017 Piyush Chaudhari + * + * 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.unitofwork; + +/** + * {@link Student} is an entity. + */ +public class Student { + private final Integer id; + private final String name; + private final String address; + + /** + * @param id student unique id + * @param name name of student + * @param address address of student + */ + public Student(Integer id, String name, String address) { + this.id = id; + this.name = name; + this.address = address; + } + + public String getName() { + return name; + } + + public Integer getId() { + return id; + } + + public String getAddress() { + return address; + } +} diff --git a/unit-of-work/src/main/java/com/iluwatar/unitofwork/StudentDatabase.java b/unit-of-work/src/main/java/com/iluwatar/unitofwork/StudentDatabase.java new file mode 100644 index 000000000..6b0e85517 --- /dev/null +++ b/unit-of-work/src/main/java/com/iluwatar/unitofwork/StudentDatabase.java @@ -0,0 +1,43 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2014-2017 Piyush Chaudhari + * + * 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.unitofwork; + +/** + * Act as Database for student records. + */ +public class StudentDatabase { + + public void insert(Student student) { + //Some insert logic to DB + } + + public void modify(Student student) { + //Some modify logic to DB + } + + public void delete(Student student) { + //Some delete logic to DB + } +} diff --git a/unit-of-work/src/main/java/com/iluwatar/unitofwork/StudentRepository.java b/unit-of-work/src/main/java/com/iluwatar/unitofwork/StudentRepository.java new file mode 100644 index 000000000..ff1136620 --- /dev/null +++ b/unit-of-work/src/main/java/com/iluwatar/unitofwork/StudentRepository.java @@ -0,0 +1,126 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2014-2017 Piyush Chaudhari + * + * 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.unitofwork; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * {@link StudentRepository} Student database repository. + * supports unit of work for student data. + */ +public class StudentRepository implements IUnitOfWork { + private static final Logger LOGGER = LoggerFactory.getLogger(StudentRepository.class); + + private Map> context; + private StudentDatabase studentDatabase; + + /** + * @param context set of operations to be perform during commit. + * @param studentDatabase Database for student records. + */ + public StudentRepository(Map> context, StudentDatabase studentDatabase) { + this.context = context; + this.studentDatabase = studentDatabase; + } + + @Override + public void registerNew(Student student) { + LOGGER.info("Registering {} for insert in context.", student.getName()); + register(student, IUnitOfWork.INSERT); + } + + @Override + public void registerModified(Student student) { + LOGGER.info("Registering {} for modify in context.", student.getName()); + register(student, IUnitOfWork.MODIFY); + + } + + @Override + public void registerDeleted(Student student) { + LOGGER.info("Registering {} for delete in context.", student.getName()); + register(student, IUnitOfWork.DELETE); + } + + private void register(Student student, String operation) { + List studentsToOperate = context.get(operation); + if (studentsToOperate == null) { + studentsToOperate = new ArrayList<>(); + } + studentsToOperate.add(student); + context.put(operation, studentsToOperate); + } + + /** + * All UnitOfWork operations are batched and executed together on commit only. + */ + @Override + public void commit() { + if (context == null || context.size() == 0) { + return; + } + LOGGER.info("Commit started"); + if (context.containsKey(IUnitOfWork.INSERT)) { + commitInsert(); + } + + if (context.containsKey(IUnitOfWork.MODIFY)) { + commitModify(); + } + if (context.containsKey(IUnitOfWork.DELETE)) { + commitDelete(); + } + LOGGER.info("Commit finished."); + } + + private void commitInsert() { + List studentsToBeInserted = context.get(IUnitOfWork.INSERT); + for (Student student : studentsToBeInserted) { + LOGGER.info("Saving {} to database.", student.getName()); + studentDatabase.insert(student); + } + } + + private void commitModify() { + List modifiedStudents = context.get(IUnitOfWork.MODIFY); + for (Student student : modifiedStudents) { + LOGGER.info("Modifying {} to database.", student.getName()); + studentDatabase.modify(student); + } + } + + private void commitDelete() { + List deletedStudents = context.get(IUnitOfWork.DELETE); + for (Student student : deletedStudents) { + LOGGER.info("Deleting {} to database.", student.getName()); + studentDatabase.delete(student); + } + } +} diff --git a/unit-of-work/src/test/java/com/iluwatar/unitofwork/AppTest.java b/unit-of-work/src/test/java/com/iluwatar/unitofwork/AppTest.java new file mode 100644 index 000000000..942db781f --- /dev/null +++ b/unit-of-work/src/test/java/com/iluwatar/unitofwork/AppTest.java @@ -0,0 +1,40 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2014-2017 Piyush Chaudhari + * + * 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.unitofwork; + +import org.junit.Test; + +import java.io.IOException; + +/** + * AppTest + */ +public class AppTest { + @Test + public void test() throws IOException { + String[] args = {}; + App.main(args); + } +} diff --git a/unit-of-work/src/test/java/com/iluwatar/unitofwork/StudentRepositoryTest.java b/unit-of-work/src/test/java/com/iluwatar/unitofwork/StudentRepositoryTest.java new file mode 100644 index 000000000..ee63442a5 --- /dev/null +++ b/unit-of-work/src/test/java/com/iluwatar/unitofwork/StudentRepositoryTest.java @@ -0,0 +1,147 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2014-2017 Piyush Chaudhari + * + * 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.unitofwork; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.*; + +/** + * tests {@link StudentRepository} + */ +@RunWith(MockitoJUnitRunner.class) +public class StudentRepositoryTest { + private final Student student1 = new Student(1, "Ram", "street 9, cupertino"); + private final Student student2 = new Student(1, "Sham", "Z bridge, pune"); + + private Map> context; + @Mock + private StudentDatabase studentDatabase; + private StudentRepository studentRepository; + + @Before + public void setUp() throws Exception { + context = new HashMap<>(); + studentRepository = new StudentRepository(context, studentDatabase); + } + + @Test + public void shouldSaveNewStudentWithoutWritingToDb() throws Exception { + studentRepository.registerNew(student1); + studentRepository.registerNew(student2); + + assertEquals(2, context.get(IUnitOfWork.INSERT).size()); + verifyNoMoreInteractions(studentDatabase); + } + + @Test + public void shouldSaveDeletedStudentWithoutWritingToDb() throws Exception { + studentRepository.registerDeleted(student1); + studentRepository.registerDeleted(student2); + + assertEquals(2, context.get(IUnitOfWork.DELETE).size()); + verifyNoMoreInteractions(studentDatabase); + } + + @Test + public void shouldSaveModifiedStudentWithoutWritingToDb() throws Exception { + studentRepository.registerModified(student1); + studentRepository.registerModified(student2); + + assertEquals(2, context.get(IUnitOfWork.MODIFY).size()); + verifyNoMoreInteractions(studentDatabase); + } + + @Test + public void shouldSaveAllLocalChangesToDb() throws Exception { + context.put(IUnitOfWork.INSERT, Collections.singletonList(student1)); + context.put(IUnitOfWork.MODIFY, Collections.singletonList(student1)); + context.put(IUnitOfWork.DELETE, Collections.singletonList(student1)); + + studentRepository.commit(); + + verify(studentDatabase, times(1)).insert(student1); + verify(studentDatabase, times(1)).modify(student1); + verify(studentDatabase, times(1)).delete(student1); + } + + @Test + public void shouldNotWriteToDbIfContextIsNull() throws Exception { + StudentRepository studentRepository = new StudentRepository(null, studentDatabase); + + studentRepository.commit(); + + verifyNoMoreInteractions(studentDatabase); + } + + @Test + public void shouldNotWriteToDbIfNothingToCommit() throws Exception { + StudentRepository studentRepository = new StudentRepository(new HashMap<>(), studentDatabase); + + studentRepository.commit(); + + verifyZeroInteractions(studentDatabase); + } + + @Test + public void shouldNotInsertToDbIfNoRegisteredStudentsToBeCommitted() throws Exception { + context.put(IUnitOfWork.MODIFY, Collections.singletonList(student1)); + context.put(IUnitOfWork.DELETE, Collections.singletonList(student1)); + + studentRepository.commit(); + + verify(studentDatabase, never()).insert(student1); + } + + @Test + public void shouldNotModifyToDbIfNotRegisteredStudentsToBeCommitted() throws Exception { + context.put(IUnitOfWork.INSERT, Collections.singletonList(student1)); + context.put(IUnitOfWork.DELETE, Collections.singletonList(student1)); + + studentRepository.commit(); + + verify(studentDatabase, never()).modify(student1); + } + + @Test + public void shouldNotDeleteFromDbIfNotRegisteredStudentsToBeCommitted() throws Exception { + context.put(IUnitOfWork.INSERT, Collections.singletonList(student1)); + context.put(IUnitOfWork.MODIFY, Collections.singletonList(student1)); + + studentRepository.commit(); + + verify(studentDatabase, never()).delete(student1); + } +} \ No newline at end of file diff --git a/value-object/README.md b/value-object/README.md index a8e707b05..83223d8a2 100644 --- a/value-object/README.md +++ b/value-object/README.md @@ -3,7 +3,6 @@ layout: pattern title: Value Object folder: value-object permalink: /patterns/value-object/ -pumlid: LSZ13SCm20NGLTe1RExTXX2KECBOmfza_VRQszDxDnVBNJFiTG9pVOY2dteqdBdbqf3XK4ULqQbPFWmEklZcikjgXvV9W8Olwhn-e9ijjOpjKW4fv2zgHgypktq1 categories: Creational tags: - Java diff --git a/value-object/etc/value-object.urm.puml b/value-object/etc/value-object.urm.puml deleted file mode 100644 index 6149ead9b..000000000 --- a/value-object/etc/value-object.urm.puml +++ /dev/null @@ -1,22 +0,0 @@ -@startuml -package com.iluwatar.value.object { - class App { - - LOGGER : Logger {static} - + App() - + main(args : String[]) {static} - } - class HeroStat { - - intelligence : int - - luck : int - - strength : int - - HeroStat(strength : int, intelligence : int, luck : int) - + equals(obj : Object) : boolean - + getIntelligence() : int - + getLuck() : int - + getStrength() : int - + hashCode() : int - + toString() : String - + valueOf(strength : int, intelligence : int, luck : int) : HeroStat {static} - } -} -@enduml \ No newline at end of file diff --git a/value-object/pom.xml b/value-object/pom.xml index 2db53f244..fa4c06697 100644 --- a/value-object/pom.xml +++ b/value-object/pom.xml @@ -30,7 +30,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT value-object diff --git a/visitor/README.md b/visitor/README.md index 23ffc3af7..bda789a18 100644 --- a/visitor/README.md +++ b/visitor/README.md @@ -3,7 +3,6 @@ layout: pattern title: Visitor folder: visitor permalink: /patterns/visitor/ -pumlid: DSR14OGm20NGLhG0mtsxmSWeJa8oyD7sTo_xJczLgoqFIM_B1Spu43c_vLHSkMU8rs4GGwcZaxPy6UnqyyFR8Q6dRPC1SGlg7B_Gew4OJeBwVqdlPMPlNm00 categories: Behavioral tags: - Java diff --git a/visitor/etc/visitor.urm.puml b/visitor/etc/visitor.urm.puml deleted file mode 100644 index 36a67b415..000000000 --- a/visitor/etc/visitor.urm.puml +++ /dev/null @@ -1,60 +0,0 @@ -@startuml -package com.iluwatar.visitor { - class App { - + App() - + main(args : String[]) {static} - } - class Commander { - + Commander(children : Unit[]) - + accept(visitor : UnitVisitor) - + toString() : String - } - class CommanderVisitor { - - LOGGER : Logger {static} - + CommanderVisitor() - + visitCommander(commander : Commander) - + visitSergeant(sergeant : Sergeant) - + visitSoldier(soldier : Soldier) - } - class Sergeant { - + Sergeant(children : Unit[]) - + accept(visitor : UnitVisitor) - + toString() : String - } - class SergeantVisitor { - - LOGGER : Logger {static} - + SergeantVisitor() - + visitCommander(commander : Commander) - + visitSergeant(sergeant : Sergeant) - + visitSoldier(soldier : Soldier) - } - class Soldier { - + Soldier(children : Unit[]) - + accept(visitor : UnitVisitor) - + toString() : String - } - class SoldierVisitor { - - LOGGER : Logger {static} - + SoldierVisitor() - + visitCommander(commander : Commander) - + visitSergeant(sergeant : Sergeant) - + visitSoldier(soldier : Soldier) - } - abstract class Unit { - - children : Unit[] - + Unit(children : Unit[]) - + accept(visitor : UnitVisitor) - } - interface UnitVisitor { - + visitCommander(Commander) {abstract} - + visitSergeant(Sergeant) {abstract} - + visitSoldier(Soldier) {abstract} - } -} -Commander --|> Unit -CommanderVisitor ..|> UnitVisitor -Sergeant --|> Unit -SergeantVisitor ..|> UnitVisitor -Soldier --|> Unit -SoldierVisitor ..|> UnitVisitor -@enduml \ No newline at end of file diff --git a/visitor/pom.xml b/visitor/pom.xml index 7105f6ba7..5445a94cc 100644 --- a/visitor/pom.xml +++ b/visitor/pom.xml @@ -29,7 +29,7 @@ com.iluwatar java-design-patterns - 1.17.0-SNAPSHOT + 1.18.0-SNAPSHOT visitor