From 3a9d1684fd19b0987d8230031a6b05efd6abb0cc Mon Sep 17 00:00:00 2001 From: igeligel Date: Tue, 4 Oct 2016 22:33:06 +0200 Subject: [PATCH 01/37] Initial commit of the object mother #498 Add a simple king and queen classes which implement the behaviour of the royalty interface. Also wrote the object mother of royalty objects which is final so you can just call the static methods in it to create objects with a specific state to use them fast in tests. The tests are already created for testing the behaviour and the type of the objects which are created by the object mother. I also created the UML diagrams via object aid and updated the readme. --- object-mother/README.md | 31 ++++++ object-mother/etc/object-mother.png | Bin 0 -> 19705 bytes object-mother/etc/object-mother.ucls | 56 +++++++++++ object-mother/pom.xml | 48 ++++++++++ .../java/com/iluwatar/objectmother/King.java | 66 +++++++++++++ .../java/com/iluwatar/objectmother/Queen.java | 69 ++++++++++++++ .../com/iluwatar/objectmother/Royalty.java | 33 +++++++ .../objectmother/RoyaltyObjectMother.java | 83 ++++++++++++++++ .../test/RoyaltyObjectMotherTest.java | 89 ++++++++++++++++++ 9 files changed, 475 insertions(+) create mode 100644 object-mother/README.md create mode 100644 object-mother/etc/object-mother.png create mode 100644 object-mother/etc/object-mother.ucls create mode 100644 object-mother/pom.xml create mode 100644 object-mother/src/main/java/com/iluwatar/objectmother/King.java create mode 100644 object-mother/src/main/java/com/iluwatar/objectmother/Queen.java create mode 100644 object-mother/src/main/java/com/iluwatar/objectmother/Royalty.java create mode 100644 object-mother/src/main/java/com/iluwatar/objectmother/RoyaltyObjectMother.java create mode 100644 object-mother/src/test/java/com/iluwatar/objectmother/test/RoyaltyObjectMotherTest.java diff --git a/object-mother/README.md b/object-mother/README.md new file mode 100644 index 000000000..9188c8b41 --- /dev/null +++ b/object-mother/README.md @@ -0,0 +1,31 @@ +--- +layout: pattern +title: Object Mother +folder: object-mother +permalink: /patterns/object-mother/ +pumlid: +categories: Creational +tags: + - Java + - Difficulty-Beginner +--- + +## Object Mother +Define a factory of immutable content with separated builder and factory interfaces. + +![alt text](./etc/object-mother.png "Object Mother") + +## Applicability +Use the Object Mother pattern when + +* You want consistent objects over several tests +* you want to reduce code for creation of objects in tests +* every test should run with fresh data + +## Credits + +* [Answer by David Brown](http://stackoverflow.com/questions/923319/what-is-an-objectmother) to the stackoverflow question: [What is an ObjectMother?](http://stackoverflow.com/questions/923319/what-is-an-objectmother) + +* [c2wiki - Object Mother](http://c2.com/cgi/wiki?ObjectMother) + +* [Nat Pryce - Test Data Builders: an alternative to the Object Mother pattern](http://www.natpryce.com/articles/000714.html) \ No newline at end of file diff --git a/object-mother/etc/object-mother.png b/object-mother/etc/object-mother.png new file mode 100644 index 0000000000000000000000000000000000000000..807343d9f9e42c2b3f306beb5c8e2199bbedafb1 GIT binary patch literal 19705 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 literal 0 HcmV?d00001 diff --git a/object-mother/etc/object-mother.ucls b/object-mother/etc/object-mother.ucls new file mode 100644 index 000000000..ef6cee5ef --- /dev/null +++ b/object-mother/etc/object-mother.ucls @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/object-mother/pom.xml b/object-mother/pom.xml new file mode 100644 index 000000000..91bdff8e2 --- /dev/null +++ b/object-mother/pom.xml @@ -0,0 +1,48 @@ + + + + 4.0.0 + + com.iluwatar + java-design-patterns + 1.14.0-SNAPSHOT + + object-mother + + + junit + junit + test + + + org.mockito + mockito-core + test + + + \ No newline at end of file diff --git a/object-mother/src/main/java/com/iluwatar/objectmother/King.java b/object-mother/src/main/java/com/iluwatar/objectmother/King.java new file mode 100644 index 000000000..544b0bacb --- /dev/null +++ b/object-mother/src/main/java/com/iluwatar/objectmother/King.java @@ -0,0 +1,66 @@ +/** + * The MIT License + * Copyright (c) 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. + */ +package com.iluwatar.objectmother; + +public class King implements Royalty { + boolean isDrunk = false; + boolean isHappy = false; + + @Override + public void makeDrunk() { + isDrunk = true; + } + + @Override + public void makeSober() { + isDrunk = false; + } + + @Override + public void makeHappy() { + isHappy = true; + } + + @Override + public void makeUnhappy() { + isHappy = false; + } + + public boolean isHappy() { + return isHappy; + } + + /** + * Method to flirt to a queen. + * @param queen Queen which should be flirted. + */ + public void flirt(Queen queen) { + boolean flirtStatus = queen.getFlirted(this); + if (flirtStatus == false) { + this.makeUnhappy(); + } else { + this.makeHappy(); + } + + } +} diff --git a/object-mother/src/main/java/com/iluwatar/objectmother/Queen.java b/object-mother/src/main/java/com/iluwatar/objectmother/Queen.java new file mode 100644 index 000000000..3e18fbf3a --- /dev/null +++ b/object-mother/src/main/java/com/iluwatar/objectmother/Queen.java @@ -0,0 +1,69 @@ +/** + * The MIT License + * Copyright (c) 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. + */ +package com.iluwatar.objectmother; + +public class Queen implements Royalty { + private boolean isDrunk = false; + private boolean isHappy = false; + private boolean isFlirty = false; + + @Override + public void makeDrunk() { + isDrunk = true; + } + + @Override + public void makeSober() { + isDrunk = false; + } + + @Override + public void makeHappy() { + isHappy = true; + } + + @Override + public void makeUnhappy() { + isHappy = false; + } + + public boolean isFlirty() { + return isFlirty; + } + + public void setFlirtiness(boolean flirtiness) { + this.isFlirty = flirtiness; + } + + /** + * Method which is called when the king is flirting to a queen. + * @param king King who initialized the flirt. + * @return A value which describes if the flirt was successful or not. + */ + public boolean getFlirted(King king) { + if (this.isFlirty && king.isHappy && !king.isDrunk) { + return true; + } + return false; + } +} diff --git a/object-mother/src/main/java/com/iluwatar/objectmother/Royalty.java b/object-mother/src/main/java/com/iluwatar/objectmother/Royalty.java new file mode 100644 index 000000000..2bebc0939 --- /dev/null +++ b/object-mother/src/main/java/com/iluwatar/objectmother/Royalty.java @@ -0,0 +1,33 @@ +/** + * The MIT License + * Copyright (c) 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. + */ +package com.iluwatar.objectmother; + +public interface Royalty { + void makeDrunk(); + + void makeSober(); + + void makeHappy(); + + void makeUnhappy(); +} diff --git a/object-mother/src/main/java/com/iluwatar/objectmother/RoyaltyObjectMother.java b/object-mother/src/main/java/com/iluwatar/objectmother/RoyaltyObjectMother.java new file mode 100644 index 000000000..624a29132 --- /dev/null +++ b/object-mother/src/main/java/com/iluwatar/objectmother/RoyaltyObjectMother.java @@ -0,0 +1,83 @@ +/** + * The MIT License + * Copyright (c) 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. + */ +package com.iluwatar.objectmother; + +public final class RoyaltyObjectMother { + + /** + * Method to create a sober and unhappy king. The standard paramters are set. + * @return An instance of {@link com.iluwatar.objectmother.King} with the standard properties. + */ + public static King createSoberUnhappyKing() { + return new King(); + } + + /** + * Method of the object mother to create a drunk king. + * @return A drunk {@link com.iluwatar.objectmother.King}. + */ + public static King createDrunkKing() { + King king = new King(); + king.makeDrunk(); + return king; + } + + /** + * Method to create a happy king. + * @return A happy {@link com.iluwatar.objectmother.King}. + */ + public static King createHappyKing() { + King king = new King(); + king.makeHappy(); + return king; + } + + /** + * Method to create a happy and drunk king. + * @return A drunk and happy {@link com.iluwatar.objectmother.King}. + */ + public static King createHappyDrunkKing() { + King king = new King(); + king.makeHappy(); + king.makeDrunk(); + return king; + } + + /** + * Method to create a flirty queen. + * @return A flirty {@link com.iluwatar.objectmother.Queen}. + */ + public static Queen createFlirtyQueen() { + Queen queen = new Queen(); + queen.setFlirtiness(true); + return queen; + } + + /** + * Method to create a not flirty queen. + * @return A not flirty {@link com.iluwatar.objectmother.Queen}. + */ + public static Queen createNotFlirtyQueen() { + return new Queen(); + } +} diff --git a/object-mother/src/test/java/com/iluwatar/objectmother/test/RoyaltyObjectMotherTest.java b/object-mother/src/test/java/com/iluwatar/objectmother/test/RoyaltyObjectMotherTest.java new file mode 100644 index 000000000..feba71a1b --- /dev/null +++ b/object-mother/src/test/java/com/iluwatar/objectmother/test/RoyaltyObjectMotherTest.java @@ -0,0 +1,89 @@ +/** + * The MIT License + * Copyright (c) 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. + */ +package com.iluwatar.objectmother.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import com.iluwatar.objectmother.King; +import com.iluwatar.objectmother.Queen; +import com.iluwatar.objectmother.Royalty; +import com.iluwatar.objectmother.RoyaltyObjectMother; + +public class RoyaltyObjectMotherTest { + + @Test + public void unsuccessfulKingFlirt() { + King soberUnhappyKing = RoyaltyObjectMother.createSoberUnhappyKing(); + Queen flirtyQueen = RoyaltyObjectMother.createFlirtyQueen(); + soberUnhappyKing.flirt(flirtyQueen); + assertFalse(soberUnhappyKing.isHappy()); + } + + @Test + public void queenIsBlockingFlirtCauseDrunkKing() { + King soberUnhappyKing = RoyaltyObjectMother.createDrunkKing(); + Queen notFlirtyQueen = RoyaltyObjectMother.createNotFlirtyQueen(); + soberUnhappyKing.flirt(notFlirtyQueen); + assertFalse(soberUnhappyKing.isHappy()); + } + + @Test + public void queenIsBlockingFlirt() { + King soberUnhappyKing = RoyaltyObjectMother.createHappyKing(); + Queen notFlirtyQueen = RoyaltyObjectMother.createNotFlirtyQueen(); + soberUnhappyKing.flirt(notFlirtyQueen); + assertFalse(soberUnhappyKing.isHappy()); + } + + @Test + public void successfullKingFlirt() { + King soberUnhappyKing = RoyaltyObjectMother.createHappyKing(); + Queen flirtyQueen = RoyaltyObjectMother.createFlirtyQueen(); + soberUnhappyKing.flirt(flirtyQueen); + assertTrue(soberUnhappyKing.isHappy()); + } + + @Test + public void testQueenType() { + Royalty flirtyQueen = RoyaltyObjectMother.createFlirtyQueen(); + Royalty notFlirtyQueen = RoyaltyObjectMother.createNotFlirtyQueen(); + assertEquals(flirtyQueen.getClass(), Queen.class); + assertEquals(notFlirtyQueen.getClass(), Queen.class); + } + + @Test + public void testKingType() { + Royalty drunkKing = RoyaltyObjectMother.createDrunkKing(); + Royalty happyDrunkKing = RoyaltyObjectMother.createHappyDrunkKing(); + Royalty happyKing = RoyaltyObjectMother.createHappyKing(); + Royalty soberUnhappyKing = RoyaltyObjectMother.createSoberUnhappyKing(); + assertEquals(drunkKing.getClass(), King.class); + assertEquals(happyDrunkKing.getClass(), King.class); + assertEquals(happyKing.getClass(), King.class); + assertEquals(soberUnhappyKing.getClass(), King.class); + } +} From 863ea7538156398eba1d179e36e9379e5eeef968 Mon Sep 17 00:00:00 2001 From: igeligel Date: Thu, 6 Oct 2016 20:12:43 +0200 Subject: [PATCH 02/37] Add PlantUML file for the UML diagram #498 --- object-mother/etc/object-mother.urm.puml | 45 ++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 object-mother/etc/object-mother.urm.puml diff --git a/object-mother/etc/object-mother.urm.puml b/object-mother/etc/object-mother.urm.puml new file mode 100644 index 000000000..9b26450f0 --- /dev/null +++ b/object-mother/etc/object-mother.urm.puml @@ -0,0 +1,45 @@ +@startuml +package com.iluwatar.objectmother { + class RoyaltyObjectMother { + + RoyaltyObjectMother() + + createDrunkKing() : King {static} + + createFlirtyQueen() : Queen {static} + + createHappyDrunkKing() : King {static} + + createHappyKing() : King {static} + + createNotFlirtyQueen() : Queen {static} + + createSoberUnhappyKing() : King {static} + } + 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 King { + ~ isDrunk : boolean + ~ isHappy : boolean + + King() + + flirt(queen : Queen) + + isHappy() : boolean + + makeDrunk() + + makeHappy() + + makeSober() + + makeUnhappy() + } +} +Queen ..|> Royalty +King ..|> Royalty +@enduml \ No newline at end of file From 0438811489c16948ad8418e9a3ce59bc10bd92c6 Mon Sep 17 00:00:00 2001 From: daniel-bryla Date: Sun, 23 Oct 2016 19:59:03 +0200 Subject: [PATCH 03/37] #502 Replaced usages of System.out with logger. --- .../com/iluwatar/abstractdocument/App.java | 17 +- .../com/iluwatar/abstractfactory/App.java | 21 +- .../iluwatar/adapter/BattleFishingBoat.java | 7 +- .../com/iluwatar/adapter/FishingBoat.java | 9 +- .../ProductInformationClientImpl.java | 6 +- .../ProductInventoryClientImpl.java | 6 +- .../iluwatar/async/method/invocation/App.java | 7 +- .../java/com/iluwatar/bridge/Excalibur.java | 13 +- .../java/com/iluwatar/bridge/Mjollnir.java | 13 +- .../com/iluwatar/bridge/Stormbringer.java | 13 +- .../main/java/com/iluwatar/builder/App.java | 10 +- .../business/delegate/EjbService.java | 7 +- .../business/delegate/JmsService.java | 7 +- .../main/java/com/iluwatar/caching/App.java | 30 +-- .../java/com/iluwatar/caching/CacheStore.java | 19 +- .../java/com/iluwatar/caching/LruCache.java | 9 +- .../main/java/com/iluwatar/callback/App.java | 7 +- .../com/iluwatar/callback/LambdasApp.java | 7 +- .../com/iluwatar/callback/SimpleTask.java | 7 +- .../com/iluwatar/chain/RequestHandler.java | 7 +- .../java/com/iluwatar/command/Target.java | 9 +- .../java/com/iluwatar/command/Wizard.java | 11 +- .../main/java/com/iluwatar/composite/App.java | 11 +- .../java/com/iluwatar/composite/Letter.java | 7 +- .../java/com/iluwatar/composite/Sentence.java | 7 +- .../java/com/iluwatar/composite/Word.java | 7 +- .../main/java/com/iluwatar/decorator/App.java | 13 +- .../com/iluwatar/decorator/SmartHostile.java | 9 +- .../java/com/iluwatar/decorator/Troll.java | 9 +- .../simple/printers/CanonPrinter.java | 6 +- .../simple/printers/EpsonPrinter.java | 6 +- .../delegation/simple/printers/HpPrinter.java | 6 +- .../dependency/injection/Tobacco.java | 9 +- .../iluwatar/doublechecked/locking/App.java | 7 +- .../doublechecked/locking/Inventory.java | 8 +- .../java/com/iluwatar/doubledispatch/App.java | 15 +- .../iluwatar/doubledispatch/Meteoroid.java | 17 +- .../doubledispatch/SpaceStationMir.java | 22 ++- .../event/aggregator/KingJoffrey.java | 7 +- .../eda/handler/UserCreatedEventHandler.java | 8 +- .../eda/handler/UserUpdatedEventHandler.java | 8 +- .../iluwatar/facade/DwarvenCartOperator.java | 7 +- .../iluwatar/facade/DwarvenGoldDigger.java | 7 +- .../iluwatar/facade/DwarvenMineWorker.java | 15 +- .../iluwatar/facade/DwarvenTunnelDigger.java | 7 +- .../java/com/iluwatar/factorykit/App.java | 8 +- .../java/com/iluwatar/factory/method/App.java | 9 +- .../java/com/iluwatar/featuretoggle/App.java | 12 +- .../com/iluwatar/fluentinterface/app/App.java | 14 +- .../com/iluwatar/flux/view/ContentView.java | 6 +- .../java/com/iluwatar/flux/view/MenuView.java | 8 +- .../com/iluwatar/flyweight/AlchemistShop.java | 9 +- .../com/iluwatar/flyweight/HealingPotion.java | 7 +- .../iluwatar/flyweight/HolyWaterPotion.java | 7 +- .../flyweight/InvisibilityPotion.java | 7 +- .../com/iluwatar/flyweight/PoisonPotion.java | 7 +- .../iluwatar/flyweight/StrengthPotion.java | 7 +- .../iluwatar/front/controller/ArcherView.java | 7 +- .../front/controller/CatapultView.java | 7 +- .../iluwatar/front/controller/ErrorView.java | 7 +- .../com/iluwatar/halfsynchalfasync/App.java | 9 +- .../administration/ConsoleAdministration.java | 26 +-- .../hexagonal/eventlog/StdOutEventLog.java | 26 +-- .../hexagonal/service/ConsoleLottery.java | 56 +++--- .../java/com/iluwatar/interpreter/App.java | 17 +- .../main/java/com/iluwatar/iterator/App.java | 19 +- .../com/iluwatar/layers/CakeViewImpl.java | 7 +- .../java/com/iluwatar/layers/StdOutTest.java | 2 + .../java/com/iluwatar/lazy/loading/App.java | 12 +- .../java/com/iluwatar/lazy/loading/Heavy.java | 11 +- .../iluwatar/lazy/loading/HolderNaive.java | 7 +- .../lazy/loading/HolderThreadSafe.java | 7 +- .../iluwatar/lazy/loading/Java8Holder.java | 7 +- .../iluwatar/mediator/PartyMemberBase.java | 11 +- .../main/java/com/iluwatar/memento/App.java | 17 +- .../com/iluwatar/message/channel/App.java | 6 +- .../model/view/controller/GiantView.java | 7 +- .../src/main/java/com/iluwatar/monad/App.java | 7 +- .../java/com/iluwatar/monostate/Server.java | 10 +- .../main/java/com/iluwatar/multiton/App.java | 23 ++- .../src/main/java/com/iluwatar/mute/App.java | 7 +- .../test/java/com/iluwatar/mute/MuteTest.java | 6 +- .../main/java/com/iluwatar/mutex/Thief.java | 9 +- naked-objects/dom/log4j.properties | 41 ---- naked-objects/integtests/logging.properties | 111 ----------- .../main/webapp/WEB-INF/logging.properties | 187 ------------------ .../com/iluwatar/nullobject/NodeImpl.java | 7 +- .../java/com/iluwatar/object/pool/App.java | 29 +-- .../main/java/com/iluwatar/observer/App.java | 6 +- .../java/com/iluwatar/observer/Hobbits.java | 13 +- .../main/java/com/iluwatar/observer/Orcs.java | 13 +- .../java/com/iluwatar/observer/Weather.java | 7 +- .../iluwatar/observer/generic/GHobbits.java | 13 +- .../com/iluwatar/observer/generic/GOrcs.java | 12 +- .../iluwatar/observer/generic/GWeather.java | 6 +- .../com/iluwatar/poison/pill/Consumer.java | 11 +- .../com/iluwatar/poison/pill/Producer.java | 8 +- pom.xml | 25 ++- .../privateclassdata/ImmutableStew.java | 10 +- .../com/iluwatar/privateclassdata/Stew.java | 12 +- .../com/iluwatar/producer/consumer/App.java | 7 +- .../iluwatar/producer/consumer/Consumer.java | 8 +- .../main/java/com/iluwatar/promise/App.java | 9 +- .../java/com/iluwatar/promise/Utility.java | 9 +- .../main/java/com/iluwatar/property/App.java | 12 +- .../main/java/com/iluwatar/prototype/App.java | 17 +- .../java/com/iluwatar/proxy/WizardTower.java | 7 +- .../com/iluwatar/proxy/WizardTowerProxy.java | 7 +- .../com/iluwatar/publish/subscribe/App.java | 6 +- .../com/iluwatar/reactor/app/AppClient.java | 14 +- .../iluwatar/reactor/app/LoggingHandler.java | 6 +- .../reactor/framework/NioDatagramChannel.java | 7 +- .../reactor/framework/NioReactor.java | 7 +- .../framework/NioServerSocketChannel.java | 7 +- .../com/iluwatar/reader/writer/lock/App.java | 7 +- .../iluwatar/reader/writer/lock/Reader.java | 9 +- .../iluwatar/reader/writer/lock/Writer.java | 9 +- .../writer/lock/ReaderAndWriterTest.java | 8 +- .../reader/writer/lock/ReaderTest.java | 6 +- .../reader/writer/lock/WriterTest.java | 6 +- .../java/com/iluwatar/repository/App.java | 18 +- .../com/iluwatar/repository/AppConfig.java | 18 +- .../acquisition/is/initialization/App.java | 9 +- .../is/initialization/SlidingDoor.java | 9 +- .../is/initialization/TreasureChest.java | 9 +- .../java/com/iluwatar/semaphore/Customer.java | 11 +- .../main/java/com/iluwatar/servant/App.java | 9 +- .../com/iluwatar/servicelayer/app/App.java | 24 ++- .../servicelayer/hibernate/HibernateUtil.java | 6 +- .../iluwatar/servicelocator/InitContext.java | 9 +- .../iluwatar/servicelocator/ServiceCache.java | 9 +- .../iluwatar/servicelocator/ServiceImpl.java | 7 +- .../main/java/com/iluwatar/singleton/App.java | 25 ++- .../com/iluwatar/specification/app/App.java | 16 +- .../java/com/iluwatar/state/AngryState.java | 9 +- .../com/iluwatar/state/PeacefulState.java | 9 +- .../java/com/iluwatar/stepbuilder/App.java | 11 +- .../main/java/com/iluwatar/strategy/App.java | 23 ++- .../com/iluwatar/strategy/MeleeStrategy.java | 7 +- .../iluwatar/strategy/ProjectileStrategy.java | 8 +- .../com/iluwatar/strategy/SpellStrategy.java | 8 +- .../templatemethod/HitAndRunMethod.java | 9 +- .../templatemethod/StealingMethod.java | 7 +- .../iluwatar/templatemethod/SubtleMethod.java | 9 +- .../java/com/iluwatar/threadpool/App.java | 9 +- .../java/com/iluwatar/threadpool/Worker.java | 8 +- .../java/com/iluwatar/tolerantreader/App.java | 23 ++- .../main/java/com/iluwatar/twin/BallItem.java | 9 +- .../java/com/iluwatar/twin/BallThread.java | 9 +- .../main/java/com/iluwatar/twin/GameItem.java | 7 +- .../java/com/iluwatar/value/object/App.java | 12 +- .../iluwatar/visitor/CommanderVisitor.java | 7 +- .../com/iluwatar/visitor/SergeantVisitor.java | 7 +- .../com/iluwatar/visitor/SoldierVisitor.java | 7 +- 154 files changed, 1155 insertions(+), 792 deletions(-) delete mode 100644 naked-objects/dom/log4j.properties delete mode 100644 naked-objects/integtests/logging.properties delete mode 100644 naked-objects/webapp/src/main/webapp/WEB-INF/logging.properties diff --git a/abstract-document/src/main/java/com/iluwatar/abstractdocument/App.java b/abstract-document/src/main/java/com/iluwatar/abstractdocument/App.java index d7758b6f7..35cdf7625 100644 --- a/abstract-document/src/main/java/com/iluwatar/abstractdocument/App.java +++ b/abstract-document/src/main/java/com/iluwatar/abstractdocument/App.java @@ -27,6 +27,8 @@ import com.iluwatar.abstractdocument.domain.HasModel; import com.iluwatar.abstractdocument.domain.HasParts; import com.iluwatar.abstractdocument.domain.HasPrice; import com.iluwatar.abstractdocument.domain.HasType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.Arrays; import java.util.HashMap; @@ -44,11 +46,13 @@ import java.util.Map; */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Executes the App */ public App() { - System.out.println("Constructing parts and car"); + LOGGER.info("Constructing parts and car"); Map carProperties = new HashMap<>(); carProperties.put(HasModel.PROPERTY, "300SL"); @@ -68,12 +72,11 @@ public class App { Car car = new Car(carProperties); - System.out.println("Here is our car:"); - System.out.println("-> model: " + car.getModel().get()); - System.out.println("-> price: " + car.getPrice().get()); - System.out.println("-> parts: "); - car.getParts().forEach(p -> System.out - .println("\t" + p.getType().get() + "/" + p.getModel().get() + "/" + p.getPrice().get())); + LOGGER.info("Here is our car:"); + LOGGER.info("-> model: {}", car.getModel().get()); + LOGGER.info("-> price: {}", car.getPrice().get()); + LOGGER.info("-> parts: "); + car.getParts().forEach(p -> LOGGER.info("\t{}/{}/{}", p.getType().get(), p.getModel().get(), p.getPrice().get())); } /** 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 aae396f1d..abc75a951 100644 --- a/abstract-factory/src/main/java/com/iluwatar/abstractfactory/App.java +++ b/abstract-factory/src/main/java/com/iluwatar/abstractfactory/App.java @@ -22,6 +22,9 @@ */ package com.iluwatar.abstractfactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * The Abstract Factory pattern provides a way to encapsulate a group of individual factories that have a common theme @@ -39,6 +42,8 @@ package com.iluwatar.abstractfactory; */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + private King king; private Castle castle; private Army army; @@ -98,17 +103,17 @@ public class App { App app = new App(); - System.out.println("Elf Kingdom"); + LOGGER.info("Elf Kingdom"); app.createKingdom(new ElfKingdomFactory()); - System.out.println(app.getArmy().getDescription()); - System.out.println(app.getCastle().getDescription()); - System.out.println(app.getKing().getDescription()); + LOGGER.info(app.getArmy().getDescription()); + LOGGER.info(app.getCastle().getDescription()); + LOGGER.info(app.getKing().getDescription()); - System.out.println("\nOrc Kingdom"); + LOGGER.info("Orc Kingdom"); app.createKingdom(new OrcKingdomFactory()); - System.out.println(app.getArmy().getDescription()); - System.out.println(app.getCastle().getDescription()); - System.out.println(app.getKing().getDescription()); + LOGGER.info(app.getArmy().getDescription()); + LOGGER.info(app.getCastle().getDescription()); + LOGGER.info(app.getKing().getDescription()); } diff --git a/adapter/src/main/java/com/iluwatar/adapter/BattleFishingBoat.java b/adapter/src/main/java/com/iluwatar/adapter/BattleFishingBoat.java index a591818fe..265f127c4 100644 --- a/adapter/src/main/java/com/iluwatar/adapter/BattleFishingBoat.java +++ b/adapter/src/main/java/com/iluwatar/adapter/BattleFishingBoat.java @@ -22,6 +22,9 @@ */ package com.iluwatar.adapter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * Adapter class. Adapts the interface of the device ({@link FishingBoat}) into {@link BattleShip} @@ -33,6 +36,8 @@ package com.iluwatar.adapter; */ public class BattleFishingBoat implements BattleShip { + private static final Logger LOGGER = LoggerFactory.getLogger(BattleFishingBoat.class); + private FishingBoat boat; public BattleFishingBoat() { @@ -41,7 +46,7 @@ public class BattleFishingBoat implements BattleShip { @Override public void fire() { - System.out.println("fire!"); + LOGGER.info("fire!"); } @Override diff --git a/adapter/src/main/java/com/iluwatar/adapter/FishingBoat.java b/adapter/src/main/java/com/iluwatar/adapter/FishingBoat.java index 307437038..a10e90967 100644 --- a/adapter/src/main/java/com/iluwatar/adapter/FishingBoat.java +++ b/adapter/src/main/java/com/iluwatar/adapter/FishingBoat.java @@ -22,6 +22,9 @@ */ package com.iluwatar.adapter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * Device class (adaptee in the pattern). We want to reuse this class @@ -29,12 +32,14 @@ package com.iluwatar.adapter; */ public class FishingBoat { + private static final Logger LOGGER = LoggerFactory.getLogger(FishingBoat.class); + public void sail() { - System.out.println("The Boat is moving to that place"); + LOGGER.info("The Boat is moving to that place"); } public void fish() { - System.out.println("fishing ..."); + LOGGER.info("fishing ..."); } } diff --git a/aggregator-microservices/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/ProductInformationClientImpl.java b/aggregator-microservices/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/ProductInformationClientImpl.java index 1c5c1527c..e86a84563 100644 --- a/aggregator-microservices/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/ProductInformationClientImpl.java +++ b/aggregator-microservices/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/ProductInformationClientImpl.java @@ -27,6 +27,8 @@ import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import java.io.IOException; @@ -37,6 +39,8 @@ import java.io.IOException; @Component public class ProductInformationClientImpl implements ProductInformationClient { + private static final Logger LOGGER = LoggerFactory.getLogger(ProductInformationClientImpl.class); + @Override public String getProductTitle() { String response = null; @@ -46,7 +50,7 @@ public class ProductInformationClientImpl implements ProductInformationClient { response = EntityUtils.toString(httpResponse.getEntity()); } } catch (IOException e) { - e.printStackTrace(); + LOGGER.error("Exception caught.", e); } return response; } diff --git a/aggregator-microservices/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/ProductInventoryClientImpl.java b/aggregator-microservices/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/ProductInventoryClientImpl.java index 14d0a32c4..c736462e6 100644 --- a/aggregator-microservices/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/ProductInventoryClientImpl.java +++ b/aggregator-microservices/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/ProductInventoryClientImpl.java @@ -27,6 +27,8 @@ import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import java.io.IOException; @@ -37,6 +39,8 @@ import java.io.IOException; @Component public class ProductInventoryClientImpl implements ProductInventoryClient { + private static final Logger LOGGER = LoggerFactory.getLogger(ProductInventoryClientImpl.class); + @Override public int getProductInventories() { String response = "0"; @@ -46,7 +50,7 @@ public class ProductInventoryClientImpl implements ProductInventoryClient { response = EntityUtils.toString(httpResponse.getEntity()); } } catch (IOException e) { - e.printStackTrace(); + LOGGER.error("Exception caught.", e); } return Integer.parseInt(response); } diff --git a/async-method-invocation/src/main/java/com/iluwatar/async/method/invocation/App.java b/async-method-invocation/src/main/java/com/iluwatar/async/method/invocation/App.java index 0a56dc166..ee33ea1db 100644 --- a/async-method-invocation/src/main/java/com/iluwatar/async/method/invocation/App.java +++ b/async-method-invocation/src/main/java/com/iluwatar/async/method/invocation/App.java @@ -22,6 +22,9 @@ */ package com.iluwatar.async.method.invocation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.util.concurrent.Callable; /** @@ -54,6 +57,8 @@ import java.util.concurrent.Callable; */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point */ @@ -120,6 +125,6 @@ public class App { } private static void log(String msg) { - System.out.println(String.format("[%1$-10s] - %2$s", Thread.currentThread().getName(), msg)); + LOGGER.info(msg); } } diff --git a/bridge/src/main/java/com/iluwatar/bridge/Excalibur.java b/bridge/src/main/java/com/iluwatar/bridge/Excalibur.java index 2523b3557..28bcf13fa 100644 --- a/bridge/src/main/java/com/iluwatar/bridge/Excalibur.java +++ b/bridge/src/main/java/com/iluwatar/bridge/Excalibur.java @@ -22,6 +22,9 @@ */ package com.iluwatar.bridge; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * Excalibur @@ -29,23 +32,25 @@ package com.iluwatar.bridge; */ public class Excalibur extends BlindingMagicWeaponImpl { + private static final Logger LOGGER = LoggerFactory.getLogger(Excalibur.class); + @Override public void wieldImp() { - System.out.println("wielding Excalibur"); + LOGGER.info("wielding Excalibur"); } @Override public void swingImp() { - System.out.println("swinging Excalibur"); + LOGGER.info("swinging Excalibur"); } @Override public void unwieldImp() { - System.out.println("unwielding Excalibur"); + LOGGER.info("unwielding Excalibur"); } @Override public void blindImp() { - System.out.println("bright light streams from Excalibur blinding the enemy"); + LOGGER.info("bright light streams from Excalibur blinding the enemy"); } } diff --git a/bridge/src/main/java/com/iluwatar/bridge/Mjollnir.java b/bridge/src/main/java/com/iluwatar/bridge/Mjollnir.java index 0cc31b471..a57d75abc 100644 --- a/bridge/src/main/java/com/iluwatar/bridge/Mjollnir.java +++ b/bridge/src/main/java/com/iluwatar/bridge/Mjollnir.java @@ -22,6 +22,9 @@ */ package com.iluwatar.bridge; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * Mjollnir @@ -29,23 +32,25 @@ package com.iluwatar.bridge; */ public class Mjollnir extends FlyingMagicWeaponImpl { + private static final Logger LOGGER = LoggerFactory.getLogger(Mjollnir.class); + @Override public void wieldImp() { - System.out.println("wielding Mjollnir"); + LOGGER.info("wielding Mjollnir"); } @Override public void swingImp() { - System.out.println("swinging Mjollnir"); + LOGGER.info("swinging Mjollnir"); } @Override public void unwieldImp() { - System.out.println("unwielding Mjollnir"); + LOGGER.info("unwielding Mjollnir"); } @Override public void flyImp() { - System.out.println("Mjollnir hits the enemy in the air and returns back to the owner's hand"); + LOGGER.info("Mjollnir hits the enemy in the air and returns back to the owner's hand"); } } diff --git a/bridge/src/main/java/com/iluwatar/bridge/Stormbringer.java b/bridge/src/main/java/com/iluwatar/bridge/Stormbringer.java index 91cad9cc2..e9d65bc8c 100644 --- a/bridge/src/main/java/com/iluwatar/bridge/Stormbringer.java +++ b/bridge/src/main/java/com/iluwatar/bridge/Stormbringer.java @@ -22,6 +22,9 @@ */ package com.iluwatar.bridge; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * Stormbringer @@ -29,23 +32,25 @@ package com.iluwatar.bridge; */ public class Stormbringer extends SoulEatingMagicWeaponImpl { + private static final Logger LOGGER = LoggerFactory.getLogger(Stormbringer.class); + @Override public void wieldImp() { - System.out.println("wielding Stormbringer"); + LOGGER.info("wielding Stormbringer"); } @Override public void swingImp() { - System.out.println("swinging Stormbringer"); + LOGGER.info("swinging Stormbringer"); } @Override public void unwieldImp() { - System.out.println("unwielding Stormbringer"); + LOGGER.info("unwielding Stormbringer"); } @Override public void eatSoulImp() { - System.out.println("Stormbringer devours the enemy's soul"); + LOGGER.info("Stormbringer devours the enemy's soul"); } } diff --git a/builder/src/main/java/com/iluwatar/builder/App.java b/builder/src/main/java/com/iluwatar/builder/App.java index d421de7b6..0790e3058 100644 --- a/builder/src/main/java/com/iluwatar/builder/App.java +++ b/builder/src/main/java/com/iluwatar/builder/App.java @@ -23,6 +23,8 @@ package com.iluwatar.builder; import com.iluwatar.builder.Hero.Builder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * @@ -50,6 +52,8 @@ import com.iluwatar.builder.Hero.Builder; */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point * @@ -60,18 +64,18 @@ public class App { Hero mage = new Hero.Builder(Profession.MAGE, "Riobard").withHairColor(HairColor.BLACK) .withWeapon(Weapon.DAGGER).build(); - System.out.println(mage); + LOGGER.info(mage.toString()); Hero warrior = new Hero.Builder(Profession.WARRIOR, "Amberjill").withHairColor(HairColor.BLOND) .withHairType(HairType.LONG_CURLY).withArmor(Armor.CHAIN_MAIL).withWeapon(Weapon.SWORD) .build(); - System.out.println(warrior); + LOGGER.info(warrior.toString()); Hero thief = new Hero.Builder(Profession.THIEF, "Desmond").withHairType(HairType.BALD) .withWeapon(Weapon.BOW).build(); - System.out.println(thief); + LOGGER.info(thief.toString()); } } diff --git a/business-delegate/src/main/java/com/iluwatar/business/delegate/EjbService.java b/business-delegate/src/main/java/com/iluwatar/business/delegate/EjbService.java index 7296f63b4..9c890b108 100644 --- a/business-delegate/src/main/java/com/iluwatar/business/delegate/EjbService.java +++ b/business-delegate/src/main/java/com/iluwatar/business/delegate/EjbService.java @@ -22,6 +22,9 @@ */ package com.iluwatar.business.delegate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * Service EJB implementation @@ -29,8 +32,10 @@ package com.iluwatar.business.delegate; */ public class EjbService implements BusinessService { + private static final Logger LOGGER = LoggerFactory.getLogger(EjbService.class); + @Override public void doProcessing() { - System.out.println("EjbService is now processing"); + LOGGER.info("EjbService is now processing"); } } diff --git a/business-delegate/src/main/java/com/iluwatar/business/delegate/JmsService.java b/business-delegate/src/main/java/com/iluwatar/business/delegate/JmsService.java index 5b71ce57d..5b5fa6247 100644 --- a/business-delegate/src/main/java/com/iluwatar/business/delegate/JmsService.java +++ b/business-delegate/src/main/java/com/iluwatar/business/delegate/JmsService.java @@ -22,6 +22,9 @@ */ package com.iluwatar.business.delegate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * Service JMS implementation @@ -29,8 +32,10 @@ package com.iluwatar.business.delegate; */ public class JmsService implements BusinessService { + private static final Logger LOGGER = LoggerFactory.getLogger(JmsService.class); + @Override public void doProcessing() { - System.out.println("JmsService is now processing"); + LOGGER.info("JmsService is now processing"); } } diff --git a/caching/src/main/java/com/iluwatar/caching/App.java b/caching/src/main/java/com/iluwatar/caching/App.java index 8e5a84085..377a4bfa6 100644 --- a/caching/src/main/java/com/iluwatar/caching/App.java +++ b/caching/src/main/java/com/iluwatar/caching/App.java @@ -22,6 +22,9 @@ */ package com.iluwatar.caching; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * The Caching pattern describes how to avoid expensive re-acquisition of resources by not releasing @@ -59,6 +62,9 @@ package com.iluwatar.caching; */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + + /** * Program entry point * @@ -80,13 +86,13 @@ public class App { * Read-through and write-through */ public void useReadAndWriteThroughStrategy() { - System.out.println("# CachingPolicy.THROUGH"); + LOGGER.info("# CachingPolicy.THROUGH"); AppManager.initCachingPolicy(CachingPolicy.THROUGH); UserAccount userAccount1 = new UserAccount("001", "John", "He is a boy."); AppManager.save(userAccount1); - System.out.println(AppManager.printCacheContent()); + LOGGER.info(AppManager.printCacheContent()); AppManager.find("001"); AppManager.find("001"); } @@ -95,21 +101,21 @@ public class App { * Read-through and write-around */ public void useReadThroughAndWriteAroundStrategy() { - System.out.println("# CachingPolicy.AROUND"); + LOGGER.info("# CachingPolicy.AROUND"); AppManager.initCachingPolicy(CachingPolicy.AROUND); UserAccount userAccount2 = new UserAccount("002", "Jane", "She is a girl."); AppManager.save(userAccount2); - System.out.println(AppManager.printCacheContent()); + LOGGER.info(AppManager.printCacheContent()); AppManager.find("002"); - System.out.println(AppManager.printCacheContent()); + LOGGER.info(AppManager.printCacheContent()); userAccount2 = AppManager.find("002"); userAccount2.setUserName("Jane G."); AppManager.save(userAccount2); - System.out.println(AppManager.printCacheContent()); + LOGGER.info(AppManager.printCacheContent()); AppManager.find("002"); - System.out.println(AppManager.printCacheContent()); + LOGGER.info(AppManager.printCacheContent()); AppManager.find("002"); } @@ -117,7 +123,7 @@ public class App { * Read-through and write-behind */ public void useReadThroughAndWriteBehindStrategy() { - System.out.println("# CachingPolicy.BEHIND"); + LOGGER.info("# CachingPolicy.BEHIND"); AppManager.initCachingPolicy(CachingPolicy.BEHIND); UserAccount userAccount3 = new UserAccount("003", "Adam", "He likes food."); @@ -127,13 +133,13 @@ public class App { AppManager.save(userAccount3); AppManager.save(userAccount4); AppManager.save(userAccount5); - System.out.println(AppManager.printCacheContent()); + LOGGER.info(AppManager.printCacheContent()); AppManager.find("003"); - System.out.println(AppManager.printCacheContent()); + LOGGER.info(AppManager.printCacheContent()); UserAccount userAccount6 = new UserAccount("006", "Yasha", "She is an only child."); AppManager.save(userAccount6); - System.out.println(AppManager.printCacheContent()); + LOGGER.info(AppManager.printCacheContent()); AppManager.find("004"); - System.out.println(AppManager.printCacheContent()); + LOGGER.info(AppManager.printCacheContent()); } } diff --git a/caching/src/main/java/com/iluwatar/caching/CacheStore.java b/caching/src/main/java/com/iluwatar/caching/CacheStore.java index 5903f8219..3b3226553 100644 --- a/caching/src/main/java/com/iluwatar/caching/CacheStore.java +++ b/caching/src/main/java/com/iluwatar/caching/CacheStore.java @@ -22,6 +22,9 @@ */ package com.iluwatar.caching; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.util.List; /** @@ -31,6 +34,8 @@ import java.util.List; */ public class CacheStore { + private static final Logger LOGGER = LoggerFactory.getLogger(CacheStore.class); + static LruCache cache; private CacheStore() { @@ -52,10 +57,10 @@ public class CacheStore { */ public static UserAccount readThrough(String userId) { if (cache.contains(userId)) { - System.out.println("# Cache Hit!"); + LOGGER.info("# Cache Hit!"); return cache.get(userId); } - System.out.println("# Cache Miss!"); + LOGGER.info("# Cache Miss!"); UserAccount userAccount = DbManager.readFromDb(userId); cache.set(userId, userAccount); return userAccount; @@ -91,13 +96,13 @@ public class CacheStore { */ public static UserAccount readThroughWithWriteBackPolicy(String userId) { if (cache.contains(userId)) { - System.out.println("# Cache Hit!"); + LOGGER.info("# Cache Hit!"); return cache.get(userId); } - System.out.println("# Cache Miss!"); + LOGGER.info("# Cache Miss!"); UserAccount userAccount = DbManager.readFromDb(userId); if (cache.isFull()) { - System.out.println("# Cache is FULL! Writing LRU data to DB..."); + LOGGER.info("# Cache is FULL! Writing LRU data to DB..."); UserAccount toBeWrittenToDb = cache.getLruData(); DbManager.upsertDb(toBeWrittenToDb); } @@ -110,7 +115,7 @@ public class CacheStore { */ public static void writeBehind(UserAccount userAccount) { if (cache.isFull() && !cache.contains(userAccount.getUserId())) { - System.out.println("# Cache is FULL! Writing LRU data to DB..."); + LOGGER.info("# Cache is FULL! Writing LRU data to DB..."); UserAccount toBeWrittenToDb = cache.getLruData(); DbManager.upsertDb(toBeWrittenToDb); } @@ -130,7 +135,7 @@ public class CacheStore { * Writes remaining content in the cache into the DB. */ public static void flushCache() { - System.out.println("# flushCache..."); + LOGGER.info("# flushCache..."); if (null == cache) { return; } diff --git a/caching/src/main/java/com/iluwatar/caching/LruCache.java b/caching/src/main/java/com/iluwatar/caching/LruCache.java index 5c5549afd..614b42ac4 100644 --- a/caching/src/main/java/com/iluwatar/caching/LruCache.java +++ b/caching/src/main/java/com/iluwatar/caching/LruCache.java @@ -22,6 +22,9 @@ */ package com.iluwatar.caching; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -38,6 +41,8 @@ import java.util.Map; */ public class LruCache { + private static final Logger LOGGER = LoggerFactory.getLogger(LruCache.class); + class Node { String userId; UserAccount userAccount; @@ -117,7 +122,7 @@ public class LruCache { } else { Node newNode = new Node(userId, userAccount); if (cache.size() >= capacity) { - System.out.println("# Cache is FULL! Removing " + end.userId + " from cache..."); + LOGGER.info("# Cache is FULL! Removing {} from cache...", end.userId); cache.remove(end.userId); // remove LRU data from cache. remove(end); setHead(newNode); @@ -136,7 +141,7 @@ public class LruCache { * Invalidate cache for user */ public void invalidate(String userId) { - System.out.println("# " + userId + " has been updated! Removing older version from cache..."); + LOGGER.info("# {} has been updated! Removing older version from cache...", userId); Node toBeRemoved = cache.get(userId); remove(toBeRemoved); cache.remove(userId); diff --git a/callback/src/main/java/com/iluwatar/callback/App.java b/callback/src/main/java/com/iluwatar/callback/App.java index bc1b2890e..ece6f8cce 100644 --- a/callback/src/main/java/com/iluwatar/callback/App.java +++ b/callback/src/main/java/com/iluwatar/callback/App.java @@ -22,6 +22,9 @@ */ package com.iluwatar.callback; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * Callback pattern is more native for functional languages where functions are treated as @@ -31,6 +34,8 @@ package com.iluwatar.callback; */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point */ @@ -39,7 +44,7 @@ public class App { Callback callback = new Callback() { @Override public void call() { - System.out.println("I'm done now."); + LOGGER.info("I'm done now."); } }; task.executeWith(callback); diff --git a/callback/src/main/java/com/iluwatar/callback/LambdasApp.java b/callback/src/main/java/com/iluwatar/callback/LambdasApp.java index 78ca63e0b..33a49a461 100644 --- a/callback/src/main/java/com/iluwatar/callback/LambdasApp.java +++ b/callback/src/main/java/com/iluwatar/callback/LambdasApp.java @@ -22,6 +22,9 @@ */ package com.iluwatar.callback; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * This example generates the exact same output as {@link App} however the callback has been @@ -30,12 +33,14 @@ package com.iluwatar.callback; */ public class LambdasApp { + private static final Logger LOGGER = LoggerFactory.getLogger(LambdasApp.class); + /** * Program entry point */ public static void main(String[] args) { Task task = new SimpleTask(); - Callback c = () -> System.out.println("I'm done now."); + Callback c = () -> LOGGER.info("I'm done now."); task.executeWith(c); } } diff --git a/callback/src/main/java/com/iluwatar/callback/SimpleTask.java b/callback/src/main/java/com/iluwatar/callback/SimpleTask.java index 2a7385607..2c56bea07 100644 --- a/callback/src/main/java/com/iluwatar/callback/SimpleTask.java +++ b/callback/src/main/java/com/iluwatar/callback/SimpleTask.java @@ -22,6 +22,9 @@ */ package com.iluwatar.callback; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * Implementation of task that need to be executed @@ -29,8 +32,10 @@ package com.iluwatar.callback; */ public class SimpleTask extends Task { + private static final Logger LOGGER = LoggerFactory.getLogger(SimpleTask.class); + @Override public void execute() { - System.out.println("Perform some important activity and after call the callback method."); + LOGGER.info("Perform some important activity and after call the callback method."); } } diff --git a/chain/src/main/java/com/iluwatar/chain/RequestHandler.java b/chain/src/main/java/com/iluwatar/chain/RequestHandler.java index 78d68e5dc..2fd774f99 100644 --- a/chain/src/main/java/com/iluwatar/chain/RequestHandler.java +++ b/chain/src/main/java/com/iluwatar/chain/RequestHandler.java @@ -22,6 +22,9 @@ */ package com.iluwatar.chain; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * RequestHandler @@ -29,6 +32,8 @@ package com.iluwatar.chain; */ public abstract class RequestHandler { + private static final Logger LOGGER = LoggerFactory.getLogger(RequestHandler.class); + private RequestHandler next; public RequestHandler(RequestHandler next) { @@ -45,7 +50,7 @@ public abstract class RequestHandler { } protected void printHandling(Request req) { - System.out.println(this + " handling request \"" + req + "\""); + LOGGER.info("{} handling request \"{}\"", this, req); } @Override diff --git a/command/src/main/java/com/iluwatar/command/Target.java b/command/src/main/java/com/iluwatar/command/Target.java index 2e49ab663..3bfbde926 100644 --- a/command/src/main/java/com/iluwatar/command/Target.java +++ b/command/src/main/java/com/iluwatar/command/Target.java @@ -22,6 +22,9 @@ */ package com.iluwatar.command; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * Base class for spell targets. @@ -29,6 +32,8 @@ package com.iluwatar.command; */ public abstract class Target { + private static final Logger LOGGER = LoggerFactory.getLogger(Target.class); + private Size size; private Visibility visibility; @@ -56,8 +61,6 @@ public abstract class Target { * Print status */ public void printStatus() { - System.out.println(String.format("%s, [size=%s] [visibility=%s]", this, getSize(), - getVisibility())); - System.out.println(); + LOGGER.info("{}, [size={}] [visibility={}]", this, getSize(), getVisibility()); } } diff --git a/command/src/main/java/com/iluwatar/command/Wizard.java b/command/src/main/java/com/iluwatar/command/Wizard.java index bd0ef85d4..abfc49967 100644 --- a/command/src/main/java/com/iluwatar/command/Wizard.java +++ b/command/src/main/java/com/iluwatar/command/Wizard.java @@ -22,6 +22,9 @@ */ package com.iluwatar.command; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.util.Deque; import java.util.LinkedList; @@ -32,6 +35,8 @@ import java.util.LinkedList; */ public class Wizard { + private static final Logger LOGGER = LoggerFactory.getLogger(Wizard.class); + private Deque undoStack = new LinkedList<>(); private Deque redoStack = new LinkedList<>(); @@ -41,7 +46,7 @@ public class Wizard { * Cast spell */ public void castSpell(Command command, Target target) { - System.out.println(this + " casts " + command + " at " + target); + LOGGER.info("{} casts {} at {}", this, command, target); command.execute(target); undoStack.offerLast(command); } @@ -53,7 +58,7 @@ public class Wizard { if (!undoStack.isEmpty()) { Command previousSpell = undoStack.pollLast(); redoStack.offerLast(previousSpell); - System.out.println(this + " undoes " + previousSpell); + LOGGER.info("{} undoes {}", this, previousSpell); previousSpell.undo(); } } @@ -65,7 +70,7 @@ public class Wizard { if (!redoStack.isEmpty()) { Command previousSpell = redoStack.pollLast(); undoStack.offerLast(previousSpell); - System.out.println(this + " redoes " + previousSpell); + LOGGER.info("{} redoes {}", this, previousSpell); previousSpell.redo(); } } diff --git a/composite/src/main/java/com/iluwatar/composite/App.java b/composite/src/main/java/com/iluwatar/composite/App.java index cfe37876f..07d4f0b68 100644 --- a/composite/src/main/java/com/iluwatar/composite/App.java +++ b/composite/src/main/java/com/iluwatar/composite/App.java @@ -22,6 +22,9 @@ */ package com.iluwatar.composite; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * The Composite pattern is a partitioning design pattern. The Composite pattern describes that a * group of objects is to be treated in the same way as a single instance of an object. The intent @@ -35,20 +38,22 @@ package com.iluwatar.composite; */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point * * @param args command line args */ public static void main(String[] args) { - System.out.println("Message from the orcs: "); + LOGGER.info("Message from the orcs: "); LetterComposite orcMessage = new Messenger().messageFromOrcs(); orcMessage.print(); - System.out.println("\n"); + LOGGER.info("\n"); - System.out.println("Message from the elves: "); + LOGGER.info("Message from the elves: "); LetterComposite elfMessage = new Messenger().messageFromElves(); elfMessage.print(); diff --git a/composite/src/main/java/com/iluwatar/composite/Letter.java b/composite/src/main/java/com/iluwatar/composite/Letter.java index d6a4005d2..c8a6ccfce 100644 --- a/composite/src/main/java/com/iluwatar/composite/Letter.java +++ b/composite/src/main/java/com/iluwatar/composite/Letter.java @@ -22,6 +22,9 @@ */ package com.iluwatar.composite; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * Letter @@ -29,6 +32,8 @@ package com.iluwatar.composite; */ public class Letter extends LetterComposite { + private static final Logger LOGGER = LoggerFactory.getLogger(Letter.class); + private char c; public Letter(char c) { @@ -37,7 +42,7 @@ public class Letter extends LetterComposite { @Override protected void printThisBefore() { - System.out.print(c); + LOGGER.info(String.valueOf(c)); } @Override diff --git a/composite/src/main/java/com/iluwatar/composite/Sentence.java b/composite/src/main/java/com/iluwatar/composite/Sentence.java index eea1d4b1d..ca8698f4f 100644 --- a/composite/src/main/java/com/iluwatar/composite/Sentence.java +++ b/composite/src/main/java/com/iluwatar/composite/Sentence.java @@ -22,6 +22,9 @@ */ package com.iluwatar.composite; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.util.List; /** @@ -31,6 +34,8 @@ import java.util.List; */ public class Sentence extends LetterComposite { + private static final Logger LOGGER = LoggerFactory.getLogger(Sentence.class); + /** * Constructor */ @@ -47,6 +52,6 @@ public class Sentence extends LetterComposite { @Override protected void printThisAfter() { - System.out.print("."); + LOGGER.info("."); } } diff --git a/composite/src/main/java/com/iluwatar/composite/Word.java b/composite/src/main/java/com/iluwatar/composite/Word.java index 819f166dc..4e5cfb31d 100644 --- a/composite/src/main/java/com/iluwatar/composite/Word.java +++ b/composite/src/main/java/com/iluwatar/composite/Word.java @@ -22,6 +22,9 @@ */ package com.iluwatar.composite; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.util.List; /** @@ -31,6 +34,8 @@ import java.util.List; */ public class Word extends LetterComposite { + private static final Logger LOGGER = LoggerFactory.getLogger(Word.class); + /** * Constructor */ @@ -42,7 +47,7 @@ public class Word extends LetterComposite { @Override protected void printThisBefore() { - System.out.print(" "); + LOGGER.info(" "); } @Override diff --git a/decorator/src/main/java/com/iluwatar/decorator/App.java b/decorator/src/main/java/com/iluwatar/decorator/App.java index bdc574fbc..2f0b1aa4e 100644 --- a/decorator/src/main/java/com/iluwatar/decorator/App.java +++ b/decorator/src/main/java/com/iluwatar/decorator/App.java @@ -22,6 +22,9 @@ */ package com.iluwatar.decorator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * The Decorator pattern is a more flexible alternative to subclassing. The Decorator class @@ -36,6 +39,8 @@ package com.iluwatar.decorator; */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point * @@ -44,17 +49,17 @@ public class App { public static void main(String[] args) { // simple troll - System.out.println("A simple looking troll approaches."); + LOGGER.info("A simple looking troll approaches."); Hostile troll = new Troll(); troll.attack(); troll.fleeBattle(); - System.out.printf("Simple troll power %d.\n", troll.getAttackPower()); + LOGGER.info("Simple troll power {}.\n", troll.getAttackPower()); // change the behavior of the simple troll by adding a decorator - System.out.println("\nA smart looking troll surprises you."); + LOGGER.info("A smart looking troll surprises you."); Hostile smart = new SmartHostile(troll); smart.attack(); smart.fleeBattle(); - System.out.printf("Smart troll power %d.\n", smart.getAttackPower()); + LOGGER.info("Smart troll power {}.\n", smart.getAttackPower()); } } diff --git a/decorator/src/main/java/com/iluwatar/decorator/SmartHostile.java b/decorator/src/main/java/com/iluwatar/decorator/SmartHostile.java index 3b4b86276..9a4a136ad 100644 --- a/decorator/src/main/java/com/iluwatar/decorator/SmartHostile.java +++ b/decorator/src/main/java/com/iluwatar/decorator/SmartHostile.java @@ -22,6 +22,9 @@ */ package com.iluwatar.decorator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * SmartHostile is a decorator for {@link Hostile} objects. The calls to the {@link Hostile} interface * are intercepted and decorated. Finally the calls are delegated to the decorated {@link Hostile} @@ -30,6 +33,8 @@ package com.iluwatar.decorator; */ public class SmartHostile implements Hostile { + private static final Logger LOGGER = LoggerFactory.getLogger(SmartHostile.class); + private Hostile decorated; public SmartHostile(Hostile decorated) { @@ -38,7 +43,7 @@ public class SmartHostile implements Hostile { @Override public void attack() { - System.out.println("It throws a rock at you!"); + LOGGER.info("It throws a rock at you!"); decorated.attack(); } @@ -50,7 +55,7 @@ public class SmartHostile implements Hostile { @Override public void fleeBattle() { - System.out.println("It calls for help!"); + LOGGER.info("It calls for help!"); decorated.fleeBattle(); } } diff --git a/decorator/src/main/java/com/iluwatar/decorator/Troll.java b/decorator/src/main/java/com/iluwatar/decorator/Troll.java index 628adda4b..0fff3b812 100644 --- a/decorator/src/main/java/com/iluwatar/decorator/Troll.java +++ b/decorator/src/main/java/com/iluwatar/decorator/Troll.java @@ -22,6 +22,9 @@ */ package com.iluwatar.decorator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * Troll implements {@link Hostile} interface directly. @@ -29,9 +32,11 @@ package com.iluwatar.decorator; */ public class Troll implements Hostile { + private static final Logger LOGGER = LoggerFactory.getLogger(Troll.class); + @Override public void attack() { - System.out.println("The troll swings at you with a club!"); + LOGGER.info("The troll swings at you with a club!"); } @Override @@ -41,6 +46,6 @@ public class Troll implements Hostile { @Override public void fleeBattle() { - System.out.println("The troll shrieks in horror and runs away!"); + LOGGER.info("The troll shrieks in horror and runs away!"); } } diff --git a/delegation/src/main/java/com/iluwatar/delegation/simple/printers/CanonPrinter.java b/delegation/src/main/java/com/iluwatar/delegation/simple/printers/CanonPrinter.java index 5e3966d85..1664e86e4 100644 --- a/delegation/src/main/java/com/iluwatar/delegation/simple/printers/CanonPrinter.java +++ b/delegation/src/main/java/com/iluwatar/delegation/simple/printers/CanonPrinter.java @@ -23,6 +23,8 @@ package com.iluwatar.delegation.simple.printers; import com.iluwatar.delegation.simple.Printer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Specialised Implementation of {@link Printer} for a Canon Printer, in @@ -32,12 +34,14 @@ import com.iluwatar.delegation.simple.Printer; */ public class CanonPrinter implements Printer { + private static final Logger LOGGER = LoggerFactory.getLogger(CanonPrinter.class); + /** * {@inheritDoc} */ @Override public void print(String message) { - System.out.print("Canon Printer : " + message); + LOGGER.info("Canon Printer : {}", message); } } diff --git a/delegation/src/main/java/com/iluwatar/delegation/simple/printers/EpsonPrinter.java b/delegation/src/main/java/com/iluwatar/delegation/simple/printers/EpsonPrinter.java index d37fbf613..f67f9defa 100644 --- a/delegation/src/main/java/com/iluwatar/delegation/simple/printers/EpsonPrinter.java +++ b/delegation/src/main/java/com/iluwatar/delegation/simple/printers/EpsonPrinter.java @@ -23,6 +23,8 @@ package com.iluwatar.delegation.simple.printers; import com.iluwatar.delegation.simple.Printer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Specialised Implementation of {@link Printer} for a Epson Printer, in @@ -32,12 +34,14 @@ import com.iluwatar.delegation.simple.Printer; */ public class EpsonPrinter implements Printer { + private static final Logger LOGGER = LoggerFactory.getLogger(EpsonPrinter.class); + /** * {@inheritDoc} */ @Override public void print(String message) { - System.out.print("Epson Printer : " + message); + LOGGER.info("Epson Printer : {}", message); } } diff --git a/delegation/src/main/java/com/iluwatar/delegation/simple/printers/HpPrinter.java b/delegation/src/main/java/com/iluwatar/delegation/simple/printers/HpPrinter.java index f81debf62..fdd89081b 100644 --- a/delegation/src/main/java/com/iluwatar/delegation/simple/printers/HpPrinter.java +++ b/delegation/src/main/java/com/iluwatar/delegation/simple/printers/HpPrinter.java @@ -23,6 +23,8 @@ package com.iluwatar.delegation.simple.printers; import com.iluwatar.delegation.simple.Printer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Specialised Implementation of {@link Printer} for a HP Printer, in @@ -32,12 +34,14 @@ import com.iluwatar.delegation.simple.Printer; */ public class HpPrinter implements Printer { + private static final Logger LOGGER = LoggerFactory.getLogger(HpPrinter.class); + /** * {@inheritDoc} */ @Override public void print(String message) { - System.out.print("HP Printer : " + message); + LOGGER.info("HP Printer : {}", message); } } diff --git a/dependency-injection/src/main/java/com/iluwatar/dependency/injection/Tobacco.java b/dependency-injection/src/main/java/com/iluwatar/dependency/injection/Tobacco.java index 74a564ab5..c003007e0 100644 --- a/dependency-injection/src/main/java/com/iluwatar/dependency/injection/Tobacco.java +++ b/dependency-injection/src/main/java/com/iluwatar/dependency/injection/Tobacco.java @@ -22,6 +22,9 @@ */ package com.iluwatar.dependency.injection; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * Tobacco abstraction @@ -29,8 +32,10 @@ package com.iluwatar.dependency.injection; */ public abstract class Tobacco { + private static final Logger LOGGER = LoggerFactory.getLogger(Tobacco.class); + public void smoke(Wizard wizard) { - System.out.println(String.format("%s smoking %s", wizard.getClass().getSimpleName(), this - .getClass().getSimpleName())); + LOGGER.info("{} smoking {}", wizard.getClass().getSimpleName(), + this.getClass().getSimpleName()); } } diff --git a/double-checked-locking/src/main/java/com/iluwatar/doublechecked/locking/App.java b/double-checked-locking/src/main/java/com/iluwatar/doublechecked/locking/App.java index 98309e181..9ce969037 100644 --- a/double-checked-locking/src/main/java/com/iluwatar/doublechecked/locking/App.java +++ b/double-checked-locking/src/main/java/com/iluwatar/doublechecked/locking/App.java @@ -22,6 +22,9 @@ */ package com.iluwatar.doublechecked.locking; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; @@ -40,6 +43,8 @@ import java.util.concurrent.TimeUnit; */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point * @@ -58,7 +63,7 @@ public class App { try { executorService.awaitTermination(5, TimeUnit.SECONDS); } catch (InterruptedException e) { - System.out.println("Error waiting for ExecutorService shutdown"); + LOGGER.error("Error waiting for ExecutorService shutdown"); } } } diff --git a/double-checked-locking/src/main/java/com/iluwatar/doublechecked/locking/Inventory.java b/double-checked-locking/src/main/java/com/iluwatar/doublechecked/locking/Inventory.java index 176203a44..09a14d320 100644 --- a/double-checked-locking/src/main/java/com/iluwatar/doublechecked/locking/Inventory.java +++ b/double-checked-locking/src/main/java/com/iluwatar/doublechecked/locking/Inventory.java @@ -22,6 +22,9 @@ */ package com.iluwatar.doublechecked.locking; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -35,6 +38,8 @@ import java.util.concurrent.locks.ReentrantLock; */ public class Inventory { + private static final Logger LOGGER = LoggerFactory.getLogger(Inventory.class); + private final int inventorySize; private final List items; private final Lock lock; @@ -57,8 +62,7 @@ public class Inventory { try { if (items.size() < inventorySize) { items.add(item); - System.out.println(Thread.currentThread() + ": items.size()=" + items.size() - + ", inventorySize=" + inventorySize); + LOGGER.info("{}: items.size()={}, inventorySize={}", Thread.currentThread(), items.size(), inventorySize); return true; } } finally { diff --git a/double-dispatch/src/main/java/com/iluwatar/doubledispatch/App.java b/double-dispatch/src/main/java/com/iluwatar/doubledispatch/App.java index 40a0485a5..601b0fcc0 100644 --- a/double-dispatch/src/main/java/com/iluwatar/doubledispatch/App.java +++ b/double-dispatch/src/main/java/com/iluwatar/doubledispatch/App.java @@ -22,6 +22,9 @@ */ package com.iluwatar.doubledispatch; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.util.ArrayList; import java.util.List; @@ -45,6 +48,8 @@ import java.util.List; */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point * @@ -58,8 +63,8 @@ public class App { objects.add(new SpaceStationMir(1, 1, 2, 2)); objects.add(new Meteoroid(10, 10, 15, 15)); objects.add(new SpaceStationIss(12, 12, 14, 14)); - objects.stream().forEach(o -> System.out.println(o)); - System.out.println(""); + objects.stream().forEach(o -> LOGGER.info(o.toString())); + LOGGER.info(""); // collision check objects.stream().forEach(o1 -> objects.stream().forEach(o2 -> { @@ -67,10 +72,10 @@ public class App { o1.collision(o2); } })); - System.out.println(""); + LOGGER.info(""); // output eventual object statuses - objects.stream().forEach(o -> System.out.println(o)); - System.out.println(""); + objects.stream().forEach(o -> LOGGER.info(o.toString())); + LOGGER.info(""); } } diff --git a/double-dispatch/src/main/java/com/iluwatar/doubledispatch/Meteoroid.java b/double-dispatch/src/main/java/com/iluwatar/doubledispatch/Meteoroid.java index cc68a85ec..fcda7f312 100644 --- a/double-dispatch/src/main/java/com/iluwatar/doubledispatch/Meteoroid.java +++ b/double-dispatch/src/main/java/com/iluwatar/doubledispatch/Meteoroid.java @@ -22,6 +22,9 @@ */ package com.iluwatar.doubledispatch; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * Meteoroid game object @@ -29,6 +32,8 @@ package com.iluwatar.doubledispatch; */ public class Meteoroid extends GameObject { + private static final Logger LOGGER = LoggerFactory.getLogger(Meteoroid.class); + public Meteoroid(int left, int top, int right, int bottom) { super(left, top, right, bottom); } @@ -40,25 +45,21 @@ public class Meteoroid extends GameObject { @Override public void collisionResolve(FlamingAsteroid asteroid) { - System.out.println(String.format("%s hits %s.", asteroid.getClass().getSimpleName(), this - .getClass().getSimpleName())); + LOGGER.info("{} hits {}.", asteroid.getClass().getSimpleName(), this.getClass().getSimpleName()); } @Override public void collisionResolve(Meteoroid meteoroid) { - System.out.println(String.format("%s hits %s.", meteoroid.getClass().getSimpleName(), this - .getClass().getSimpleName())); + LOGGER.info("{} hits {}.", meteoroid.getClass().getSimpleName(), this.getClass().getSimpleName()); } @Override public void collisionResolve(SpaceStationMir mir) { - System.out.println(String.format("%s hits %s.", mir.getClass().getSimpleName(), this.getClass() - .getSimpleName())); + LOGGER.info("{} hits {}.", mir.getClass().getSimpleName(), this.getClass().getSimpleName()); } @Override public void collisionResolve(SpaceStationIss iss) { - System.out.println(String.format("%s hits %s.", iss.getClass().getSimpleName(), this.getClass() - .getSimpleName())); + LOGGER.info("{} hits {}.", iss.getClass().getSimpleName(), this.getClass().getSimpleName()); } } diff --git a/double-dispatch/src/main/java/com/iluwatar/doubledispatch/SpaceStationMir.java b/double-dispatch/src/main/java/com/iluwatar/doubledispatch/SpaceStationMir.java index e7a55d0ee..c1f750059 100644 --- a/double-dispatch/src/main/java/com/iluwatar/doubledispatch/SpaceStationMir.java +++ b/double-dispatch/src/main/java/com/iluwatar/doubledispatch/SpaceStationMir.java @@ -22,6 +22,9 @@ */ package com.iluwatar.doubledispatch; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * Space station Mir game object @@ -29,6 +32,8 @@ package com.iluwatar.doubledispatch; */ public class SpaceStationMir extends GameObject { + private static final Logger LOGGER = LoggerFactory.getLogger(SpaceStationMir.class); + public SpaceStationMir(int left, int top, int right, int bottom) { super(left, top, right, bottom); } @@ -40,31 +45,30 @@ public class SpaceStationMir extends GameObject { @Override public void collisionResolve(FlamingAsteroid asteroid) { - System.out.println(String.format("%s hits %s. %s is damaged! %s is set on fire!", asteroid - .getClass().getSimpleName(), this.getClass().getSimpleName(), this.getClass() - .getSimpleName(), this.getClass().getSimpleName())); + LOGGER.info("{} hits {}. {} is damaged! {} is set on fire!", asteroid.getClass().getSimpleName(), + this.getClass().getSimpleName(), this.getClass().getSimpleName(), this.getClass().getSimpleName()); setDamaged(true); setOnFire(true); } @Override public void collisionResolve(Meteoroid meteoroid) { - System.out.println(String.format("%s hits %s. %s is damaged!", meteoroid.getClass() - .getSimpleName(), this.getClass().getSimpleName(), this.getClass().getSimpleName())); + LOGGER.info("{} hits {}. {} is damaged!", meteoroid.getClass().getSimpleName(), + this.getClass().getSimpleName(), this.getClass().getSimpleName()); setDamaged(true); } @Override public void collisionResolve(SpaceStationMir mir) { - System.out.println(String.format("%s hits %s. %s is damaged!", mir.getClass().getSimpleName(), - this.getClass().getSimpleName(), this.getClass().getSimpleName())); + LOGGER.info("{} hits {}. {} is damaged!", mir.getClass().getSimpleName(), + this.getClass().getSimpleName(), this.getClass().getSimpleName()); setDamaged(true); } @Override public void collisionResolve(SpaceStationIss iss) { - System.out.println(String.format("%s hits %s. %s is damaged!", iss.getClass().getSimpleName(), - this.getClass().getSimpleName(), this.getClass().getSimpleName())); + LOGGER.info("{} hits {}. {} is damaged!", iss.getClass().getSimpleName(), + this.getClass().getSimpleName(), this.getClass().getSimpleName()); setDamaged(true); } } diff --git a/event-aggregator/src/main/java/com/iluwatar/event/aggregator/KingJoffrey.java b/event-aggregator/src/main/java/com/iluwatar/event/aggregator/KingJoffrey.java index fdda59693..1a0ad3345 100644 --- a/event-aggregator/src/main/java/com/iluwatar/event/aggregator/KingJoffrey.java +++ b/event-aggregator/src/main/java/com/iluwatar/event/aggregator/KingJoffrey.java @@ -22,6 +22,9 @@ */ package com.iluwatar.event.aggregator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * KingJoffrey observes events from {@link KingsHand}. @@ -29,8 +32,10 @@ package com.iluwatar.event.aggregator; */ public class KingJoffrey implements EventObserver { + private static final Logger LOGGER = LoggerFactory.getLogger(KingJoffrey.class); + @Override public void onEvent(Event e) { - System.out.println("Received event from the King's Hand: " + e.toString()); + LOGGER.info("Received event from the King's Hand: {}", e.toString()); } } diff --git a/event-driven-architecture/src/main/java/com/iluwatar/eda/handler/UserCreatedEventHandler.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/handler/UserCreatedEventHandler.java index 3ef4e8255..ded6b76ce 100644 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/handler/UserCreatedEventHandler.java +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/handler/UserCreatedEventHandler.java @@ -24,17 +24,19 @@ package com.iluwatar.eda.handler; import com.iluwatar.eda.event.UserCreatedEvent; import com.iluwatar.eda.framework.Handler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Handles the {@link UserCreatedEvent} message. */ public class UserCreatedEventHandler implements Handler { + private static final Logger LOGGER = LoggerFactory.getLogger(UserCreatedEventHandler.class); + @Override public void onEvent(UserCreatedEvent event) { - - System.out.println(String.format( - "User '%s' has been Created!", event.getUser().getUsername())); + LOGGER.info("User '{}' has been Created!", event.getUser().getUsername()); } } diff --git a/event-driven-architecture/src/main/java/com/iluwatar/eda/handler/UserUpdatedEventHandler.java b/event-driven-architecture/src/main/java/com/iluwatar/eda/handler/UserUpdatedEventHandler.java index 0311d5781..a0bf28c57 100644 --- a/event-driven-architecture/src/main/java/com/iluwatar/eda/handler/UserUpdatedEventHandler.java +++ b/event-driven-architecture/src/main/java/com/iluwatar/eda/handler/UserUpdatedEventHandler.java @@ -24,16 +24,18 @@ package com.iluwatar.eda.handler; import com.iluwatar.eda.event.UserUpdatedEvent; import com.iluwatar.eda.framework.Handler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Handles the {@link UserUpdatedEvent} message. */ public class UserUpdatedEventHandler implements Handler { + private static final Logger LOGGER = LoggerFactory.getLogger(UserUpdatedEventHandler.class); + @Override public void onEvent(UserUpdatedEvent event) { - - System.out.println(String.format( - "User '%s' has been Updated!", event.getUser().getUsername())); + LOGGER.info("User '{}' has been Updated!", event.getUser().getUsername()); } } diff --git a/facade/src/main/java/com/iluwatar/facade/DwarvenCartOperator.java b/facade/src/main/java/com/iluwatar/facade/DwarvenCartOperator.java index bdc839f57..61e64a153 100644 --- a/facade/src/main/java/com/iluwatar/facade/DwarvenCartOperator.java +++ b/facade/src/main/java/com/iluwatar/facade/DwarvenCartOperator.java @@ -22,6 +22,9 @@ */ package com.iluwatar.facade; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * DwarvenCartOperator is one of the goldmine subsystems. @@ -29,9 +32,11 @@ package com.iluwatar.facade; */ public class DwarvenCartOperator extends DwarvenMineWorker { + private static final Logger LOGGER = LoggerFactory.getLogger(DwarvenCartOperator.class); + @Override public void work() { - System.out.println(name() + " moves gold chunks out of the mine."); + LOGGER.info("{} moves gold chunks out of the mine.", name()); } @Override diff --git a/facade/src/main/java/com/iluwatar/facade/DwarvenGoldDigger.java b/facade/src/main/java/com/iluwatar/facade/DwarvenGoldDigger.java index 54fa821f4..2eb464edf 100644 --- a/facade/src/main/java/com/iluwatar/facade/DwarvenGoldDigger.java +++ b/facade/src/main/java/com/iluwatar/facade/DwarvenGoldDigger.java @@ -22,6 +22,9 @@ */ package com.iluwatar.facade; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * DwarvenGoldDigger is one of the goldmine subsystems. @@ -29,9 +32,11 @@ package com.iluwatar.facade; */ public class DwarvenGoldDigger extends DwarvenMineWorker { + private static final Logger LOGGER = LoggerFactory.getLogger(DwarvenGoldDigger.class); + @Override public void work() { - System.out.println(name() + " digs for gold."); + LOGGER.info("{} digs for gold.", name()); } @Override diff --git a/facade/src/main/java/com/iluwatar/facade/DwarvenMineWorker.java b/facade/src/main/java/com/iluwatar/facade/DwarvenMineWorker.java index f27054c53..48ec1db48 100644 --- a/facade/src/main/java/com/iluwatar/facade/DwarvenMineWorker.java +++ b/facade/src/main/java/com/iluwatar/facade/DwarvenMineWorker.java @@ -22,6 +22,9 @@ */ package com.iluwatar.facade; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * DwarvenMineWorker is one of the goldmine subsystems. @@ -29,20 +32,22 @@ package com.iluwatar.facade; */ public abstract class DwarvenMineWorker { + private static final Logger LOGGER = LoggerFactory.getLogger(DwarvenMineWorker.class); + public void goToSleep() { - System.out.println(name() + " goes to sleep."); + LOGGER.info("{} goes to sleep.", name()); } public void wakeUp() { - System.out.println(name() + " wakes up."); + LOGGER.info("{} wakes up.", name()); } public void goHome() { - System.out.println(name() + " goes home."); + LOGGER.info("{} goes home.", name()); } public void goToMine() { - System.out.println(name() + " goes to the mine."); + LOGGER.info("{} goes to the mine.", name()); } private void action(Action action) { @@ -63,7 +68,7 @@ public abstract class DwarvenMineWorker { work(); break; default: - System.out.println("Undefined action"); + LOGGER.info("Undefined action"); break; } } diff --git a/facade/src/main/java/com/iluwatar/facade/DwarvenTunnelDigger.java b/facade/src/main/java/com/iluwatar/facade/DwarvenTunnelDigger.java index 74d8b89cc..54fcca73a 100644 --- a/facade/src/main/java/com/iluwatar/facade/DwarvenTunnelDigger.java +++ b/facade/src/main/java/com/iluwatar/facade/DwarvenTunnelDigger.java @@ -22,6 +22,9 @@ */ package com.iluwatar.facade; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * DwarvenTunnelDigger is one of the goldmine subsystems. @@ -29,9 +32,11 @@ package com.iluwatar.facade; */ public class DwarvenTunnelDigger extends DwarvenMineWorker { + private static final Logger LOGGER = LoggerFactory.getLogger(DwarvenTunnelDigger.class); + @Override public void work() { - System.out.println(name() + " creates another promising tunnel."); + LOGGER.info("{} creates another promising tunnel.", name()); } @Override diff --git a/factory-kit/src/main/java/com/iluwatar/factorykit/App.java b/factory-kit/src/main/java/com/iluwatar/factorykit/App.java index f27bee170..c091cb1eb 100644 --- a/factory-kit/src/main/java/com/iluwatar/factorykit/App.java +++ b/factory-kit/src/main/java/com/iluwatar/factorykit/App.java @@ -22,6 +22,9 @@ */ package com.iluwatar.factorykit; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * Factory-kit is a creational pattern which defines a factory of immutable content * with separated builder and factory interfaces to deal with the problem of @@ -36,6 +39,9 @@ package com.iluwatar.factorykit; * be mapped explicitly with desired class type in the factory instance. */ public class App { + + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point. * @@ -49,6 +55,6 @@ public class App { builder.add(WeaponType.BOW, Bow::new); }); Weapon axe = factory.create(WeaponType.AXE); - System.out.println(axe); + LOGGER.info(axe.toString()); } } diff --git a/factory-method/src/main/java/com/iluwatar/factory/method/App.java b/factory-method/src/main/java/com/iluwatar/factory/method/App.java index cd7a6e6e7..a49d8bd32 100644 --- a/factory-method/src/main/java/com/iluwatar/factory/method/App.java +++ b/factory-method/src/main/java/com/iluwatar/factory/method/App.java @@ -22,6 +22,9 @@ */ package com.iluwatar.factory.method; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * The Factory Method is a creational design pattern which uses factory methods to deal with the @@ -38,6 +41,8 @@ package com.iluwatar.factory.method; */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + private final Blacksmith blacksmith; /** @@ -70,8 +75,8 @@ public class App { private void manufactureWeapons() { Weapon weapon; weapon = blacksmith.manufactureWeapon(WeaponType.SPEAR); - System.out.println(weapon); + LOGGER.info(weapon.toString()); weapon = blacksmith.manufactureWeapon(WeaponType.AXE); - System.out.println(weapon); + LOGGER.info(weapon.toString()); } } diff --git a/feature-toggle/src/main/java/com/iluwatar/featuretoggle/App.java b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/App.java index debe99580..c2bccb851 100644 --- a/feature-toggle/src/main/java/com/iluwatar/featuretoggle/App.java +++ b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/App.java @@ -27,6 +27,8 @@ import com.iluwatar.featuretoggle.pattern.Service; import com.iluwatar.featuretoggle.pattern.propertiesversion.PropertiesFeatureToggleVersion; import com.iluwatar.featuretoggle.user.User; import com.iluwatar.featuretoggle.user.UserGroup; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.Properties; @@ -45,6 +47,8 @@ import java.util.Properties; */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Block 1 shows the {@link PropertiesFeatureToggleVersion} being run with {@link Properties} setting the feature * toggle to enabled. @@ -70,7 +74,7 @@ public class App { properties.put("enhancedWelcome", true); Service service = new PropertiesFeatureToggleVersion(properties); final String welcomeMessage = service.getWelcomeMessage(new User("Jamie No Code")); - System.out.println(welcomeMessage); + LOGGER.info(welcomeMessage); // --------------------------------------------- @@ -78,7 +82,7 @@ public class App { turnedOff.put("enhancedWelcome", false); Service turnedOffService = new PropertiesFeatureToggleVersion(turnedOff); final String welcomeMessageturnedOff = turnedOffService.getWelcomeMessage(new User("Jamie No Code")); - System.out.println(welcomeMessageturnedOff); + LOGGER.info(welcomeMessageturnedOff); // -------------------------------------------- @@ -90,7 +94,7 @@ public class App { final String welcomeMessagePaidUser = service.getWelcomeMessage(paidUser); final String welcomeMessageFreeUser = service.getWelcomeMessage(freeUser); - System.out.println(welcomeMessageFreeUser); - System.out.println(welcomeMessagePaidUser); + LOGGER.info(welcomeMessageFreeUser); + LOGGER.info(welcomeMessagePaidUser); } } diff --git a/fluentinterface/src/main/java/com/iluwatar/fluentinterface/app/App.java b/fluentinterface/src/main/java/com/iluwatar/fluentinterface/app/App.java index 1be2b1e70..30678359d 100644 --- a/fluentinterface/src/main/java/com/iluwatar/fluentinterface/app/App.java +++ b/fluentinterface/src/main/java/com/iluwatar/fluentinterface/app/App.java @@ -35,6 +35,8 @@ import java.util.function.Predicate; import com.iluwatar.fluentinterface.fluentiterable.FluentIterable; import com.iluwatar.fluentinterface.fluentiterable.lazy.LazyFluentIterable; import com.iluwatar.fluentinterface.fluentiterable.simple.SimpleFluentIterable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * The Fluent Interface pattern is useful when you want to provide an easy readable, flowing API. @@ -50,6 +52,8 @@ import com.iluwatar.fluentinterface.fluentiterable.simple.SimpleFluentIterable; */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point */ @@ -74,9 +78,7 @@ public class App { .fromCopyOf(integerList) .filter(number -> number % 2 == 0) .first() - .ifPresent( - evenNumber -> System.out.println(String.format("The first even number is: %d", - evenNumber))); + .ifPresent(evenNumber -> LOGGER.info("The first even number is: {}", evenNumber)); List transformedList = @@ -97,9 +99,7 @@ public class App { .filter(negatives()) .first(2) .last() - .ifPresent( - lastOfFirstTwo -> System.out.println(String.format( - "The last of the first two negatives is: %d", lastOfFirstTwo))); + .ifPresent(lastOfFirstTwo -> LOGGER.info("The last of the first two negatives is: {}", lastOfFirstTwo)); } private static Function transformToString() { @@ -126,6 +126,6 @@ public class App { joiner.add(iterator.next().toString()); } - System.out.println(joiner); + LOGGER.info(joiner.toString()); } } diff --git a/flux/src/main/java/com/iluwatar/flux/view/ContentView.java b/flux/src/main/java/com/iluwatar/flux/view/ContentView.java index cb351bfae..dd5405a02 100644 --- a/flux/src/main/java/com/iluwatar/flux/view/ContentView.java +++ b/flux/src/main/java/com/iluwatar/flux/view/ContentView.java @@ -25,6 +25,8 @@ package com.iluwatar.flux.view; import com.iluwatar.flux.action.Content; import com.iluwatar.flux.store.ContentStore; import com.iluwatar.flux.store.Store; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * @@ -33,6 +35,8 @@ import com.iluwatar.flux.store.Store; */ public class ContentView implements View { + private static final Logger LOGGER = LoggerFactory.getLogger(ContentView.class); + private Content content = Content.PRODUCTS; @Override @@ -44,6 +48,6 @@ public class ContentView implements View { @Override public void render() { - System.out.println(content.toString()); + LOGGER.info(content.toString()); } } diff --git a/flux/src/main/java/com/iluwatar/flux/view/MenuView.java b/flux/src/main/java/com/iluwatar/flux/view/MenuView.java index 6cd9005dc..81d1e49d5 100644 --- a/flux/src/main/java/com/iluwatar/flux/view/MenuView.java +++ b/flux/src/main/java/com/iluwatar/flux/view/MenuView.java @@ -26,6 +26,8 @@ import com.iluwatar.flux.action.MenuItem; import com.iluwatar.flux.dispatcher.Dispatcher; import com.iluwatar.flux.store.MenuStore; import com.iluwatar.flux.store.Store; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * @@ -34,6 +36,8 @@ import com.iluwatar.flux.store.Store; */ public class MenuView implements View { + private static final Logger LOGGER = LoggerFactory.getLogger(MenuView.class); + private MenuItem selected = MenuItem.HOME; @Override @@ -47,9 +51,9 @@ public class MenuView implements View { public void render() { for (MenuItem item : MenuItem.values()) { if (selected.equals(item)) { - System.out.println(String.format("* %s", item.toString())); + LOGGER.info("* {}", item); } else { - System.out.println(item.toString()); + LOGGER.info(item.toString()); } } } diff --git a/flyweight/src/main/java/com/iluwatar/flyweight/AlchemistShop.java b/flyweight/src/main/java/com/iluwatar/flyweight/AlchemistShop.java index 507de7a6a..5cde4c248 100644 --- a/flyweight/src/main/java/com/iluwatar/flyweight/AlchemistShop.java +++ b/flyweight/src/main/java/com/iluwatar/flyweight/AlchemistShop.java @@ -22,6 +22,9 @@ */ package com.iluwatar.flyweight; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -33,6 +36,8 @@ import java.util.List; */ public class AlchemistShop { + private static final Logger LOGGER = LoggerFactory.getLogger(AlchemistShop.class); + private List topShelf; private List bottomShelf; @@ -88,13 +93,13 @@ public class AlchemistShop { */ public void enumerate() { - System.out.println("Enumerating top shelf potions\n"); + LOGGER.info("Enumerating top shelf potions\n"); for (Potion p : topShelf) { p.drink(); } - System.out.println("\nEnumerating bottom shelf potions\n"); + LOGGER.info("Enumerating bottom shelf potions\n"); for (Potion p : bottomShelf) { p.drink(); diff --git a/flyweight/src/main/java/com/iluwatar/flyweight/HealingPotion.java b/flyweight/src/main/java/com/iluwatar/flyweight/HealingPotion.java index 464675a61..e25107bdb 100644 --- a/flyweight/src/main/java/com/iluwatar/flyweight/HealingPotion.java +++ b/flyweight/src/main/java/com/iluwatar/flyweight/HealingPotion.java @@ -22,6 +22,9 @@ */ package com.iluwatar.flyweight; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * HealingPotion @@ -29,8 +32,10 @@ package com.iluwatar.flyweight; */ public class HealingPotion implements Potion { + private static final Logger LOGGER = LoggerFactory.getLogger(HealingPotion.class); + @Override public void drink() { - System.out.println("You feel healed. (Potion=" + System.identityHashCode(this) + ")"); + LOGGER.info("You feel healed. (Potion={})", System.identityHashCode(this)); } } diff --git a/flyweight/src/main/java/com/iluwatar/flyweight/HolyWaterPotion.java b/flyweight/src/main/java/com/iluwatar/flyweight/HolyWaterPotion.java index b05b4af11..83a5ca6d1 100644 --- a/flyweight/src/main/java/com/iluwatar/flyweight/HolyWaterPotion.java +++ b/flyweight/src/main/java/com/iluwatar/flyweight/HolyWaterPotion.java @@ -22,6 +22,9 @@ */ package com.iluwatar.flyweight; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * HolyWaterPotion @@ -29,8 +32,10 @@ package com.iluwatar.flyweight; */ public class HolyWaterPotion implements Potion { + private static final Logger LOGGER = LoggerFactory.getLogger(HolyWaterPotion.class); + @Override public void drink() { - System.out.println("You feel blessed. (Potion=" + System.identityHashCode(this) + ")"); + LOGGER.info("You feel blessed. (Potion={})", System.identityHashCode(this)); } } diff --git a/flyweight/src/main/java/com/iluwatar/flyweight/InvisibilityPotion.java b/flyweight/src/main/java/com/iluwatar/flyweight/InvisibilityPotion.java index 5aeb5d3a4..1e3087c4b 100644 --- a/flyweight/src/main/java/com/iluwatar/flyweight/InvisibilityPotion.java +++ b/flyweight/src/main/java/com/iluwatar/flyweight/InvisibilityPotion.java @@ -22,6 +22,9 @@ */ package com.iluwatar.flyweight; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * InvisibilityPotion @@ -29,8 +32,10 @@ package com.iluwatar.flyweight; */ public class InvisibilityPotion implements Potion { + private static final Logger LOGGER = LoggerFactory.getLogger(InvisibilityPotion.class); + @Override public void drink() { - System.out.println("You become invisible. (Potion=" + System.identityHashCode(this) + ")"); + LOGGER.info("You become invisible. (Potion={})", System.identityHashCode(this)); } } diff --git a/flyweight/src/main/java/com/iluwatar/flyweight/PoisonPotion.java b/flyweight/src/main/java/com/iluwatar/flyweight/PoisonPotion.java index a9d13088e..83c32b192 100644 --- a/flyweight/src/main/java/com/iluwatar/flyweight/PoisonPotion.java +++ b/flyweight/src/main/java/com/iluwatar/flyweight/PoisonPotion.java @@ -22,6 +22,9 @@ */ package com.iluwatar.flyweight; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * PoisonPotion @@ -29,8 +32,10 @@ package com.iluwatar.flyweight; */ public class PoisonPotion implements Potion { + private static final Logger LOGGER = LoggerFactory.getLogger(PoisonPotion.class); + @Override public void drink() { - System.out.println("Urgh! This is poisonous. (Potion=" + System.identityHashCode(this) + ")"); + LOGGER.info("Urgh! This is poisonous. (Potion={})", System.identityHashCode(this)); } } diff --git a/flyweight/src/main/java/com/iluwatar/flyweight/StrengthPotion.java b/flyweight/src/main/java/com/iluwatar/flyweight/StrengthPotion.java index 2c21e7df1..81f5a9d46 100644 --- a/flyweight/src/main/java/com/iluwatar/flyweight/StrengthPotion.java +++ b/flyweight/src/main/java/com/iluwatar/flyweight/StrengthPotion.java @@ -22,6 +22,9 @@ */ package com.iluwatar.flyweight; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * StrengthPotion @@ -29,8 +32,10 @@ package com.iluwatar.flyweight; */ public class StrengthPotion implements Potion { + private static final Logger LOGGER = LoggerFactory.getLogger(StrengthPotion.class); + @Override public void drink() { - System.out.println("You feel strong. (Potion=" + System.identityHashCode(this) + ")"); + LOGGER.info("You feel strong. (Potion={})", System.identityHashCode(this)); } } diff --git a/front-controller/src/main/java/com/iluwatar/front/controller/ArcherView.java b/front-controller/src/main/java/com/iluwatar/front/controller/ArcherView.java index a7cf8ca27..ddd27d0e8 100644 --- a/front-controller/src/main/java/com/iluwatar/front/controller/ArcherView.java +++ b/front-controller/src/main/java/com/iluwatar/front/controller/ArcherView.java @@ -22,15 +22,20 @@ */ package com.iluwatar.front.controller; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * View for archers. * */ public class ArcherView implements View { + + private static final Logger LOGGER = LoggerFactory.getLogger(ArcherView.class); @Override public void display() { - System.out.println("Displaying archers"); + LOGGER.info("Displaying archers"); } } diff --git a/front-controller/src/main/java/com/iluwatar/front/controller/CatapultView.java b/front-controller/src/main/java/com/iluwatar/front/controller/CatapultView.java index 90e4c7896..f3b7e308e 100644 --- a/front-controller/src/main/java/com/iluwatar/front/controller/CatapultView.java +++ b/front-controller/src/main/java/com/iluwatar/front/controller/CatapultView.java @@ -22,6 +22,9 @@ */ package com.iluwatar.front.controller; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * View for catapults. @@ -29,8 +32,10 @@ package com.iluwatar.front.controller; */ public class CatapultView implements View { + private static final Logger LOGGER = LoggerFactory.getLogger(CatapultView.class); + @Override public void display() { - System.out.println("Displaying catapults"); + LOGGER.info("Displaying catapults"); } } diff --git a/front-controller/src/main/java/com/iluwatar/front/controller/ErrorView.java b/front-controller/src/main/java/com/iluwatar/front/controller/ErrorView.java index cbfd4bd2e..00dbc582b 100644 --- a/front-controller/src/main/java/com/iluwatar/front/controller/ErrorView.java +++ b/front-controller/src/main/java/com/iluwatar/front/controller/ErrorView.java @@ -22,6 +22,9 @@ */ package com.iluwatar.front.controller; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * View for errors. @@ -29,8 +32,10 @@ package com.iluwatar.front.controller; */ public class ErrorView implements View { + private static final Logger LOGGER = LoggerFactory.getLogger(ErrorView.class); + @Override public void display() { - System.out.println("Error 500"); + LOGGER.error("Error 500"); } } diff --git a/half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/App.java b/half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/App.java index 17839bb32..3186b292a 100644 --- a/half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/App.java +++ b/half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/App.java @@ -22,6 +22,9 @@ */ package com.iluwatar.halfsynchalfasync; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.util.concurrent.LinkedBlockingQueue; /** @@ -66,6 +69,8 @@ import java.util.concurrent.LinkedBlockingQueue; */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point * @@ -128,7 +133,7 @@ public class App { @Override public void onPostCall(Long result) { // Handle the result of computation - System.out.println(result); + LOGGER.info(result.toString()); } @Override @@ -141,7 +146,7 @@ public class App { try { Thread.sleep(i); } catch (InterruptedException e) { - System.out.println(e); + LOGGER.error("Exception caught.", e); } return i * (i + 1) / 2; } diff --git a/hexagonal/src/main/java/com/iluwatar/hexagonal/administration/ConsoleAdministration.java b/hexagonal/src/main/java/com/iluwatar/hexagonal/administration/ConsoleAdministration.java index ea2f33699..e83521c22 100644 --- a/hexagonal/src/main/java/com/iluwatar/hexagonal/administration/ConsoleAdministration.java +++ b/hexagonal/src/main/java/com/iluwatar/hexagonal/administration/ConsoleAdministration.java @@ -30,6 +30,8 @@ import com.iluwatar.hexagonal.domain.LotteryService; import com.iluwatar.hexagonal.module.LotteryModule; import com.iluwatar.hexagonal.mongo.MongoConnectionPropertiesLoader; import com.iluwatar.hexagonal.sampledata.SampleData; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.Scanner; @@ -38,6 +40,8 @@ import java.util.Scanner; */ public class ConsoleAdministration { + private static final Logger LOGGER = LoggerFactory.getLogger(ConsoleAdministration.class); + /** * Program entry point */ @@ -53,29 +57,29 @@ public class ConsoleAdministration { printMainMenu(); String cmd = readString(scanner); if (cmd.equals("1")) { - administartion.getAllSubmittedTickets().forEach((k,v)->System.out.println("Key: " + k + " Value: " + v)); + administartion.getAllSubmittedTickets().forEach((k,v)->LOGGER.info("Key: {}, Value: {}", k, v)); } else if (cmd.equals("2")) { LotteryNumbers numbers = administartion.performLottery(); - System.out.println("The winning numbers: " + numbers.getNumbersAsString()); - System.out.println("Time to reset the database for next round, eh?"); + LOGGER.info("The winning numbers: {}", numbers.getNumbersAsString()); + LOGGER.info("Time to reset the database for next round, eh?"); } else if (cmd.equals("3")) { administartion.resetLottery(); - System.out.println("The lottery ticket database was cleared."); + LOGGER.info("The lottery ticket database was cleared."); } else if (cmd.equals("4")) { exit = true; } else { - System.out.println("Unknown command: " + cmd); + LOGGER.info("Unknown command: {}", cmd); } } } private static void printMainMenu() { - System.out.println(""); - System.out.println("### Lottery Administration Console ###"); - System.out.println("(1) Show all submitted tickets"); - System.out.println("(2) Perform lottery draw"); - System.out.println("(3) Reset lottery ticket database"); - System.out.println("(4) Exit"); + LOGGER.info(""); + LOGGER.info("### Lottery Administration Console ###"); + LOGGER.info("(1) Show all submitted tickets"); + LOGGER.info("(2) Perform lottery draw"); + LOGGER.info("(3) Reset lottery ticket database"); + LOGGER.info("(4) Exit"); } private static String readString(Scanner scanner) { diff --git a/hexagonal/src/main/java/com/iluwatar/hexagonal/eventlog/StdOutEventLog.java b/hexagonal/src/main/java/com/iluwatar/hexagonal/eventlog/StdOutEventLog.java index 4150dd401..c63759e8e 100644 --- a/hexagonal/src/main/java/com/iluwatar/hexagonal/eventlog/StdOutEventLog.java +++ b/hexagonal/src/main/java/com/iluwatar/hexagonal/eventlog/StdOutEventLog.java @@ -23,42 +23,42 @@ package com.iluwatar.hexagonal.eventlog; import com.iluwatar.hexagonal.domain.PlayerDetails; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Standard output event log */ public class StdOutEventLog implements LotteryEventLog { + private static final Logger LOGGER = LoggerFactory.getLogger(StdOutEventLog.class); + @Override public void ticketSubmitted(PlayerDetails details) { - System.out.println(String.format("Lottery ticket for %s was submitted. Bank account %s was charged for 3 credits.", - details.getEmail(), details.getBankAccount())); + LOGGER.info("Lottery ticket for {} was submitted. Bank account {} was charged for 3 credits.", + details.getEmail(), details.getBankAccount()); } @Override public void ticketDidNotWin(PlayerDetails details) { - System.out.println(String.format("Lottery ticket for %s was checked and unfortunately did not win this time.", - details.getEmail())); + LOGGER.info("Lottery ticket for {} was checked and unfortunately did not win this time.", details.getEmail()); } @Override public void ticketWon(PlayerDetails details, int prizeAmount) { - System.out - .println(String.format("Lottery ticket for %s has won! The bank account %s was deposited with %d credits.", - details.getEmail(), details.getBankAccount(), prizeAmount)); + LOGGER.info("Lottery ticket for {} has won! The bank account {} was deposited with {} credits.", + details.getEmail(), details.getBankAccount(), prizeAmount); } @Override public void prizeError(PlayerDetails details, int prizeAmount) { - System.out - .println(String.format("Lottery ticket for %s has won! Unfortunately the bank credit transfer of %d failed.", - details.getEmail(), prizeAmount)); + LOGGER.error("Lottery ticket for {} has won! Unfortunately the bank credit transfer of {} failed.", + details.getEmail(), prizeAmount); } @Override public void ticketSubmitError(PlayerDetails details) { - System.out.println( - String.format("Lottery ticket for %s could not be submitted because the credit transfer of 3 credits failed.", - details.getEmail())); + LOGGER.error("Lottery ticket for {} could not be submitted because the credit transfer of 3 credits failed.", + details.getEmail()); } } diff --git a/hexagonal/src/main/java/com/iluwatar/hexagonal/service/ConsoleLottery.java b/hexagonal/src/main/java/com/iluwatar/hexagonal/service/ConsoleLottery.java index cc13d389d..00d61b668 100644 --- a/hexagonal/src/main/java/com/iluwatar/hexagonal/service/ConsoleLottery.java +++ b/hexagonal/src/main/java/com/iluwatar/hexagonal/service/ConsoleLottery.java @@ -24,6 +24,7 @@ package com.iluwatar.hexagonal.service; import com.google.inject.Guice; import com.google.inject.Injector; +import com.iluwatar.hexagonal.administration.ConsoleAdministration; import com.iluwatar.hexagonal.banking.WireTransfers; import com.iluwatar.hexagonal.domain.LotteryNumbers; import com.iluwatar.hexagonal.domain.LotteryService; @@ -33,6 +34,8 @@ import com.iluwatar.hexagonal.domain.LotteryTicketId; import com.iluwatar.hexagonal.domain.PlayerDetails; import com.iluwatar.hexagonal.module.LotteryModule; import com.iluwatar.hexagonal.mongo.MongoConnectionPropertiesLoader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.HashSet; import java.util.Optional; @@ -44,6 +47,7 @@ import java.util.Set; */ public class ConsoleLottery { + private static final Logger LOGGER = LoggerFactory.getLogger(ConsoleLottery.class); /** * Program entry point @@ -59,25 +63,25 @@ public class ConsoleLottery { printMainMenu(); String cmd = readString(scanner); if (cmd.equals("1")) { - System.out.println("What is the account number?"); + LOGGER.info("What is the account number?"); String account = readString(scanner); - System.out.println(String.format("The account %s has %d credits.", account, bank.getFunds(account))); + LOGGER.info("The account {} has {} credits.", account, bank.getFunds(account)); } else if (cmd.equals("2")) { - System.out.println("What is the account number?"); + LOGGER.info("What is the account number?"); String account = readString(scanner); - System.out.println("How many credits do you want to deposit?"); + LOGGER.info("How many credits do you want to deposit?"); String amount = readString(scanner); bank.setFunds(account, Integer.parseInt(amount)); - System.out.println(String.format("The account %s now has %d credits.", account, bank.getFunds(account))); + LOGGER.info("The account {} now has {} credits.", account, bank.getFunds(account)); } else if (cmd.equals("3")) { - System.out.println("What is your email address?"); + LOGGER.info("What is your email address?"); String email = readString(scanner); - System.out.println("What is your bank account number?"); + LOGGER.info("What is your bank account number?"); String account = readString(scanner); - System.out.println("What is your phone number?"); + LOGGER.info("What is your phone number?"); String phone = readString(scanner); PlayerDetails details = new PlayerDetails(email, account, phone); - System.out.println("Give 4 comma separated lottery numbers?"); + LOGGER.info("Give 4 comma separated lottery numbers?"); String numbers = readString(scanner); try { String[] parts = numbers.split(","); @@ -89,17 +93,17 @@ public class ConsoleLottery { LotteryTicket lotteryTicket = new LotteryTicket(new LotteryTicketId(), details, lotteryNumbers); Optional id = service.submitTicket(lotteryTicket); if (id.isPresent()) { - System.out.println("Submitted lottery ticket with id: " + id.get()); + LOGGER.info("Submitted lottery ticket with id: {}", id.get()); } else { - System.out.println("Failed submitting lottery ticket - please try again."); + LOGGER.info("Failed submitting lottery ticket - please try again."); } } catch (Exception e) { - System.out.println("Failed submitting lottery ticket - please try again."); + LOGGER.info("Failed submitting lottery ticket - please try again."); } } else if (cmd.equals("4")) { - System.out.println("What is the ID of the lottery ticket?"); + LOGGER.info("What is the ID of the lottery ticket?"); String id = readString(scanner); - System.out.println("Give the 4 comma separated winning numbers?"); + LOGGER.info("Give the 4 comma separated winning numbers?"); String numbers = readString(scanner); try { String[] parts = numbers.split(","); @@ -110,31 +114,31 @@ public class ConsoleLottery { LotteryTicketCheckResult result = service.checkTicketForPrize( new LotteryTicketId(Integer.parseInt(id)), LotteryNumbers.create(winningNumbers)); if (result.getResult().equals(LotteryTicketCheckResult.CheckResult.WIN_PRIZE)) { - System.out.println("Congratulations! The lottery ticket has won!"); + LOGGER.info("Congratulations! The lottery ticket has won!"); } else if (result.getResult().equals(LotteryTicketCheckResult.CheckResult.NO_PRIZE)) { - System.out.println("Unfortunately the lottery ticket did not win."); + LOGGER.info("Unfortunately the lottery ticket did not win."); } else { - System.out.println("Such lottery ticket has not been submitted."); + LOGGER.info("Such lottery ticket has not been submitted."); } } catch (Exception e) { - System.out.println("Failed checking the lottery ticket - please try again."); + LOGGER.info("Failed checking the lottery ticket - please try again."); } } else if (cmd.equals("5")) { exit = true; } else { - System.out.println("Unknown command"); + LOGGER.info("Unknown command"); } } } private static void printMainMenu() { - System.out.println(""); - System.out.println("### Lottery Service Console ###"); - System.out.println("(1) Query lottery account funds"); - System.out.println("(2) Add funds to lottery account"); - System.out.println("(3) Submit ticket"); - System.out.println("(4) Check ticket"); - System.out.println("(5) Exit"); + LOGGER.info(""); + LOGGER.info("### Lottery Service Console ###"); + LOGGER.info("(1) Query lottery account funds"); + LOGGER.info("(2) Add funds to lottery account"); + LOGGER.info("(3) Submit ticket"); + LOGGER.info("(4) Check ticket"); + LOGGER.info("(5) Exit"); } private static String readString(Scanner scanner) { diff --git a/interpreter/src/main/java/com/iluwatar/interpreter/App.java b/interpreter/src/main/java/com/iluwatar/interpreter/App.java index 708f06e6f..1cf732b0d 100644 --- a/interpreter/src/main/java/com/iluwatar/interpreter/App.java +++ b/interpreter/src/main/java/com/iluwatar/interpreter/App.java @@ -22,6 +22,9 @@ */ package com.iluwatar.interpreter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.util.Stack; /** @@ -37,6 +40,8 @@ import java.util.Stack; */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * * Program entry point. @@ -56,21 +61,21 @@ public class App { if (isOperator(s)) { Expression rightExpression = stack.pop(); Expression leftExpression = stack.pop(); - System.out.println(String.format("popped from stack left: %d right: %d", - leftExpression.interpret(), rightExpression.interpret())); + LOGGER.info("popped from stack left: {} right: {}", + leftExpression.interpret(), rightExpression.interpret()); Expression operator = getOperatorInstance(s, leftExpression, rightExpression); - System.out.println(String.format("operator: %s", operator)); + LOGGER.info("operator: {}", operator); int result = operator.interpret(); NumberExpression resultExpression = new NumberExpression(result); stack.push(resultExpression); - System.out.println(String.format("push result to stack: %d", resultExpression.interpret())); + LOGGER.info("push result to stack: {}", resultExpression.interpret()); } else { Expression i = new NumberExpression(s); stack.push(i); - System.out.println(String.format("push to stack: %d", i.interpret())); + LOGGER.info("push to stack: {}", i.interpret()); } } - System.out.println(String.format("result: %d", stack.pop().interpret())); + LOGGER.info("result: {}", stack.pop().interpret()); } public static boolean isOperator(String s) { diff --git a/iterator/src/main/java/com/iluwatar/iterator/App.java b/iterator/src/main/java/com/iluwatar/iterator/App.java index 8da0a7433..44bc1dacd 100644 --- a/iterator/src/main/java/com/iluwatar/iterator/App.java +++ b/iterator/src/main/java/com/iluwatar/iterator/App.java @@ -22,6 +22,9 @@ */ package com.iluwatar.iterator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * The Iterator pattern is a design pattern in which an iterator is used to traverse a container and @@ -34,6 +37,8 @@ package com.iluwatar.iterator; */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point * @@ -44,28 +49,28 @@ public class App { ItemIterator ringIterator = chest.iterator(ItemType.RING); while (ringIterator.hasNext()) { - System.out.println(ringIterator.next()); + LOGGER.info(ringIterator.next().toString()); } - System.out.println("----------"); + LOGGER.info("----------"); ItemIterator potionIterator = chest.iterator(ItemType.POTION); while (potionIterator.hasNext()) { - System.out.println(potionIterator.next()); + LOGGER.info(potionIterator.next().toString()); } - System.out.println("----------"); + LOGGER.info("----------"); ItemIterator weaponIterator = chest.iterator(ItemType.WEAPON); while (weaponIterator.hasNext()) { - System.out.println(weaponIterator.next()); + LOGGER.info(weaponIterator.next().toString()); } - System.out.println("----------"); + LOGGER.info("----------"); ItemIterator it = chest.iterator(ItemType.ANY); while (it.hasNext()) { - System.out.println(it.next()); + LOGGER.info(it.next().toString()); } } } diff --git a/layers/src/main/java/com/iluwatar/layers/CakeViewImpl.java b/layers/src/main/java/com/iluwatar/layers/CakeViewImpl.java index bc489e16e..bb636af7a 100644 --- a/layers/src/main/java/com/iluwatar/layers/CakeViewImpl.java +++ b/layers/src/main/java/com/iluwatar/layers/CakeViewImpl.java @@ -22,6 +22,9 @@ */ package com.iluwatar.layers; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * View implementation for displaying cakes @@ -29,6 +32,8 @@ package com.iluwatar.layers; */ public class CakeViewImpl implements View { + private static final Logger LOGGER = LoggerFactory.getLogger(CakeViewImpl.class); + private CakeBakingService cakeBakingService; public CakeViewImpl(CakeBakingService cakeBakingService) { @@ -36,6 +41,6 @@ public class CakeViewImpl implements View { } public void render() { - cakeBakingService.getAllCakes().stream().forEach(cake -> System.out.println(cake)); + cakeBakingService.getAllCakes().stream().forEach(cake -> LOGGER.info(cake.toString())); } } diff --git a/layers/src/test/java/com/iluwatar/layers/StdOutTest.java b/layers/src/test/java/com/iluwatar/layers/StdOutTest.java index 3c94b178c..67a554873 100644 --- a/layers/src/test/java/com/iluwatar/layers/StdOutTest.java +++ b/layers/src/test/java/com/iluwatar/layers/StdOutTest.java @@ -24,6 +24,8 @@ package com.iluwatar.layers; import org.junit.After; import org.junit.Before; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.PrintStream; diff --git a/lazy-loading/src/main/java/com/iluwatar/lazy/loading/App.java b/lazy-loading/src/main/java/com/iluwatar/lazy/loading/App.java index 7a658a8c6..b33520243 100644 --- a/lazy-loading/src/main/java/com/iluwatar/lazy/loading/App.java +++ b/lazy-loading/src/main/java/com/iluwatar/lazy/loading/App.java @@ -22,6 +22,9 @@ */ package com.iluwatar.lazy.loading; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * Lazy loading idiom defers object creation until needed. @@ -33,6 +36,9 @@ package com.iluwatar.lazy.loading; * */ public class App { + + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point * @@ -43,16 +49,16 @@ public class App { // Simple lazy loader - not thread safe HolderNaive holderNaive = new HolderNaive(); Heavy heavy = holderNaive.getHeavy(); - System.out.println("heavy=" + heavy); + LOGGER.info("heavy={}", heavy); // Thread safe lazy loader, but with heavy synchronization on each access HolderThreadSafe holderThreadSafe = new HolderThreadSafe(); Heavy another = holderThreadSafe.getHeavy(); - System.out.println("another=" + another); + LOGGER.info("another={}", another); // The most efficient lazy loader utilizing Java 8 features Java8Holder java8Holder = new Java8Holder(); Heavy next = java8Holder.getHeavy(); - System.out.println("next=" + next); + LOGGER.info("next={}", next); } } diff --git a/lazy-loading/src/main/java/com/iluwatar/lazy/loading/Heavy.java b/lazy-loading/src/main/java/com/iluwatar/lazy/loading/Heavy.java index 57e8e263e..ad4eb3de2 100644 --- a/lazy-loading/src/main/java/com/iluwatar/lazy/loading/Heavy.java +++ b/lazy-loading/src/main/java/com/iluwatar/lazy/loading/Heavy.java @@ -22,6 +22,9 @@ */ package com.iluwatar.lazy.loading; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * Heavy objects are expensive to create. @@ -29,16 +32,18 @@ package com.iluwatar.lazy.loading; */ public class Heavy { + private static final Logger LOGGER = LoggerFactory.getLogger(Heavy.class); + /** * Constructor */ public Heavy() { - System.out.println("Creating Heavy ..."); + LOGGER.info("Creating Heavy ..."); try { Thread.sleep(1000); } catch (InterruptedException e) { - e.printStackTrace(); + LOGGER.error("Exception caught.", e); } - System.out.println("... Heavy created"); + LOGGER.info("... Heavy created"); } } diff --git a/lazy-loading/src/main/java/com/iluwatar/lazy/loading/HolderNaive.java b/lazy-loading/src/main/java/com/iluwatar/lazy/loading/HolderNaive.java index 75c65d1b9..0e3d2c718 100644 --- a/lazy-loading/src/main/java/com/iluwatar/lazy/loading/HolderNaive.java +++ b/lazy-loading/src/main/java/com/iluwatar/lazy/loading/HolderNaive.java @@ -22,6 +22,9 @@ */ package com.iluwatar.lazy.loading; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * Simple implementation of the lazy loading idiom. However, this is not thread safe. @@ -29,13 +32,15 @@ package com.iluwatar.lazy.loading; */ public class HolderNaive { + private static final Logger LOGGER = LoggerFactory.getLogger(HolderNaive.class); + private Heavy heavy; /** * Constructor */ public HolderNaive() { - System.out.println("HolderNaive created"); + LOGGER.info("HolderNaive created"); } /** diff --git a/lazy-loading/src/main/java/com/iluwatar/lazy/loading/HolderThreadSafe.java b/lazy-loading/src/main/java/com/iluwatar/lazy/loading/HolderThreadSafe.java index c6e0fcfd9..35dd2e4f0 100644 --- a/lazy-loading/src/main/java/com/iluwatar/lazy/loading/HolderThreadSafe.java +++ b/lazy-loading/src/main/java/com/iluwatar/lazy/loading/HolderThreadSafe.java @@ -22,6 +22,9 @@ */ package com.iluwatar.lazy.loading; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * Same as HolderNaive but with added synchronization. This implementation is thread safe, but each @@ -30,13 +33,15 @@ package com.iluwatar.lazy.loading; */ public class HolderThreadSafe { + private static final Logger LOGGER = LoggerFactory.getLogger(HolderThreadSafe.class); + private Heavy heavy; /** * Constructor */ public HolderThreadSafe() { - System.out.println("HolderThreadSafe created"); + LOGGER.info("HolderThreadSafe created"); } /** diff --git a/lazy-loading/src/main/java/com/iluwatar/lazy/loading/Java8Holder.java b/lazy-loading/src/main/java/com/iluwatar/lazy/loading/Java8Holder.java index e4ce394cc..95e8856c9 100644 --- a/lazy-loading/src/main/java/com/iluwatar/lazy/loading/Java8Holder.java +++ b/lazy-loading/src/main/java/com/iluwatar/lazy/loading/Java8Holder.java @@ -22,6 +22,9 @@ */ package com.iluwatar.lazy.loading; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.util.function.Supplier; /** @@ -32,10 +35,12 @@ import java.util.function.Supplier; */ public class Java8Holder { + private static final Logger LOGGER = LoggerFactory.getLogger(Java8Holder.class); + private Supplier heavy = () -> createAndCacheHeavy(); public Java8Holder() { - System.out.println("Java8Holder created"); + LOGGER.info("Java8Holder created"); } public Heavy getHeavy() { diff --git a/mediator/src/main/java/com/iluwatar/mediator/PartyMemberBase.java b/mediator/src/main/java/com/iluwatar/mediator/PartyMemberBase.java index 7d3ca3dbf..9d9b9cd2d 100644 --- a/mediator/src/main/java/com/iluwatar/mediator/PartyMemberBase.java +++ b/mediator/src/main/java/com/iluwatar/mediator/PartyMemberBase.java @@ -22,6 +22,9 @@ */ package com.iluwatar.mediator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * Abstract base class for party members. @@ -29,23 +32,25 @@ package com.iluwatar.mediator; */ public abstract class PartyMemberBase implements PartyMember { + private static final Logger LOGGER = LoggerFactory.getLogger(PartyMemberBase.class); + protected Party party; @Override public void joinedParty(Party party) { - System.out.println(this + " joins the party"); + LOGGER.info("{} joins the party", this); this.party = party; } @Override public void partyAction(Action action) { - System.out.println(this + " " + action.getDescription()); + LOGGER.info("{} {}", this, action.getDescription()); } @Override public void act(Action action) { if (party != null) { - System.out.println(this + " " + action.toString()); + LOGGER.info("{} {}", this, action); party.act(this, action); } } diff --git a/memento/src/main/java/com/iluwatar/memento/App.java b/memento/src/main/java/com/iluwatar/memento/App.java index e1ee349b1..c346b7941 100644 --- a/memento/src/main/java/com/iluwatar/memento/App.java +++ b/memento/src/main/java/com/iluwatar/memento/App.java @@ -22,6 +22,9 @@ */ package com.iluwatar.memento; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.util.Stack; /** @@ -45,6 +48,8 @@ import java.util.Stack; */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point */ @@ -52,22 +57,22 @@ public class App { Stack states = new Stack<>(); Star star = new Star(StarType.SUN, 10000000, 500000); - System.out.println(star); + LOGGER.info(star.toString()); states.add(star.getMemento()); star.timePasses(); - System.out.println(star); + LOGGER.info(star.toString()); states.add(star.getMemento()); star.timePasses(); - System.out.println(star); + LOGGER.info(star.toString()); states.add(star.getMemento()); star.timePasses(); - System.out.println(star); + LOGGER.info(star.toString()); states.add(star.getMemento()); star.timePasses(); - System.out.println(star); + LOGGER.info(star.toString()); while (states.size() > 0) { star.setMemento(states.pop()); - System.out.println(star); + LOGGER.info(star.toString()); } } } diff --git a/message-channel/src/main/java/com/iluwatar/message/channel/App.java b/message-channel/src/main/java/com/iluwatar/message/channel/App.java index dab04bd37..2e132213d 100644 --- a/message-channel/src/main/java/com/iluwatar/message/channel/App.java +++ b/message-channel/src/main/java/com/iluwatar/message/channel/App.java @@ -25,6 +25,8 @@ package com.iluwatar.message.channel; import org.apache.camel.CamelContext; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.impl.DefaultCamelContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * @@ -50,6 +52,8 @@ import org.apache.camel.impl.DefaultCamelContext; */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point */ @@ -66,7 +70,7 @@ public class App { }); context.start(); - context.getRoutes().stream().forEach(r -> System.out.println(r)); + context.getRoutes().stream().forEach(r -> LOGGER.info(r.toString())); context.stop(); } } diff --git a/model-view-controller/src/main/java/com/iluwatar/model/view/controller/GiantView.java b/model-view-controller/src/main/java/com/iluwatar/model/view/controller/GiantView.java index dd4361487..61815aab8 100644 --- a/model-view-controller/src/main/java/com/iluwatar/model/view/controller/GiantView.java +++ b/model-view-controller/src/main/java/com/iluwatar/model/view/controller/GiantView.java @@ -22,6 +22,9 @@ */ package com.iluwatar.model.view.controller; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * GiantView displays the giant @@ -29,7 +32,9 @@ package com.iluwatar.model.view.controller; */ public class GiantView { + private static final Logger LOGGER = LoggerFactory.getLogger(GiantView.class); + public void displayGiant(GiantModel giant) { - System.out.println(giant); + LOGGER.info(giant.toString()); } } diff --git a/monad/src/main/java/com/iluwatar/monad/App.java b/monad/src/main/java/com/iluwatar/monad/App.java index 7b28fdcf8..e707156d6 100644 --- a/monad/src/main/java/com/iluwatar/monad/App.java +++ b/monad/src/main/java/com/iluwatar/monad/App.java @@ -22,6 +22,9 @@ */ package com.iluwatar.monad; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.util.Objects; import java.util.function.Function; import java.util.function.Predicate; @@ -42,6 +45,8 @@ import java.util.function.Predicate; */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point. * @@ -49,7 +54,7 @@ public class App { */ public static void main(String[] args) { User user = new User("user", 24, Sex.FEMALE, "foobar.com"); - System.out.println(Validator.of(user).validate(User::getName, Objects::nonNull, "name is null") + LOGGER.info(Validator.of(user).validate(User::getName, Objects::nonNull, "name is null") .validate(User::getName, name -> !name.isEmpty(), "name is empty") .validate(User::getEmail, email -> !email.contains("@"), "email doesn't containt '@'") .validate(User::getAge, age -> age > 20 && age < 30, "age isn't between...").get().toString()); diff --git a/monostate/src/main/java/com/iluwatar/monostate/Server.java b/monostate/src/main/java/com/iluwatar/monostate/Server.java index bf700a57a..86a4985cc 100644 --- a/monostate/src/main/java/com/iluwatar/monostate/Server.java +++ b/monostate/src/main/java/com/iluwatar/monostate/Server.java @@ -22,6 +22,9 @@ */ package com.iluwatar.monostate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * The Server class. Each Server sits behind a LoadBalancer which delegates the call to the servers @@ -29,6 +32,9 @@ package com.iluwatar.monostate; * */ public class Server { + + private static final Logger LOGGER = LoggerFactory.getLogger(Server.class); + public final String host; public final int port; public final int id; @@ -51,7 +57,7 @@ public class Server { } public void serve(Request request) { - System.out.println("Server ID " + id + " associated to host : " + getHost() + " and Port " - + getPort() + " Processed request with value " + request.value); + LOGGER.info("Server ID {} associated to host : {} and port {}. Processed request with value {}", + id, host, port, request.value); } } diff --git a/multiton/src/main/java/com/iluwatar/multiton/App.java b/multiton/src/main/java/com/iluwatar/multiton/App.java index 1ffd57a34..55cc8a2aa 100644 --- a/multiton/src/main/java/com/iluwatar/multiton/App.java +++ b/multiton/src/main/java/com/iluwatar/multiton/App.java @@ -22,6 +22,9 @@ */ package com.iluwatar.multiton; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * Whereas Singleton design pattern introduces single globally accessible object the Multiton @@ -35,20 +38,22 @@ package com.iluwatar.multiton; */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point * * @param args command line args */ public static void main(String[] args) { - System.out.println("KHAMUL=" + Nazgul.getInstance(NazgulName.KHAMUL)); - System.out.println("MURAZOR=" + Nazgul.getInstance(NazgulName.MURAZOR)); - System.out.println("DWAR=" + Nazgul.getInstance(NazgulName.DWAR)); - System.out.println("JI_INDUR=" + Nazgul.getInstance(NazgulName.JI_INDUR)); - System.out.println("AKHORAHIL=" + Nazgul.getInstance(NazgulName.AKHORAHIL)); - System.out.println("HOARMURATH=" + Nazgul.getInstance(NazgulName.HOARMURATH)); - System.out.println("ADUNAPHEL=" + Nazgul.getInstance(NazgulName.ADUNAPHEL)); - System.out.println("REN=" + Nazgul.getInstance(NazgulName.REN)); - System.out.println("UVATHA=" + Nazgul.getInstance(NazgulName.UVATHA)); + LOGGER.info("KHAMUL={}", Nazgul.getInstance(NazgulName.KHAMUL)); + LOGGER.info("MURAZOR={}", Nazgul.getInstance(NazgulName.MURAZOR)); + LOGGER.info("DWAR={}", Nazgul.getInstance(NazgulName.DWAR)); + LOGGER.info("JI_INDUR={}", Nazgul.getInstance(NazgulName.JI_INDUR)); + LOGGER.info("AKHORAHIL={}", Nazgul.getInstance(NazgulName.AKHORAHIL)); + LOGGER.info("HOARMURATH={}", Nazgul.getInstance(NazgulName.HOARMURATH)); + LOGGER.info("ADUNAPHEL={}", Nazgul.getInstance(NazgulName.ADUNAPHEL)); + LOGGER.info("REN={}", Nazgul.getInstance(NazgulName.REN)); + LOGGER.info("UVATHA={}", Nazgul.getInstance(NazgulName.UVATHA)); } } diff --git a/mute-idiom/src/main/java/com/iluwatar/mute/App.java b/mute-idiom/src/main/java/com/iluwatar/mute/App.java index 8a2aca41e..35c9d2a55 100644 --- a/mute-idiom/src/main/java/com/iluwatar/mute/App.java +++ b/mute-idiom/src/main/java/com/iluwatar/mute/App.java @@ -23,6 +23,9 @@ package com.iluwatar.mute; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.io.ByteArrayOutputStream; import java.io.IOException; import java.sql.SQLException; @@ -46,6 +49,8 @@ import java.sql.SQLException; */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point. * @@ -88,7 +93,7 @@ public class App { } private static void utilizeResource(Resource resource) throws SQLException { - System.out.println("Utilizing acquired resource: " + resource); + LOGGER.info("Utilizing acquired resource: {}", resource); } private static Resource acquireResource() throws SQLException { diff --git a/mute-idiom/src/test/java/com/iluwatar/mute/MuteTest.java b/mute-idiom/src/test/java/com/iluwatar/mute/MuteTest.java index 58cbfe893..a7a010c3c 100644 --- a/mute-idiom/src/test/java/com/iluwatar/mute/MuteTest.java +++ b/mute-idiom/src/test/java/com/iluwatar/mute/MuteTest.java @@ -32,9 +32,13 @@ import java.io.PrintStream; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class MuteTest { + private static final Logger LOGGER = LoggerFactory.getLogger(MuteTest.class); + private static final String MESSAGE = "should not occur"; @Rule public ExpectedException exception = ExpectedException.none(); @@ -69,7 +73,7 @@ public class MuteTest { private void methodNotThrowingAnyException() { - System.out.println("Executed successfully"); + LOGGER.info("Executed successfully"); } private void methodThrowingException() throws Exception { diff --git a/mutex/src/main/java/com/iluwatar/mutex/Thief.java b/mutex/src/main/java/com/iluwatar/mutex/Thief.java index d2225876c..d31ec3fa8 100644 --- a/mutex/src/main/java/com/iluwatar/mutex/Thief.java +++ b/mutex/src/main/java/com/iluwatar/mutex/Thief.java @@ -22,12 +22,17 @@ */ package com.iluwatar.mutex; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * Thief is a class which continually tries to acquire a jar and take a bean * from it. When the jar is empty the thief stops. */ public class Thief extends Thread { + private static final Logger LOGGER = LoggerFactory.getLogger(Thief.class); + /** * The name of the thief. */ @@ -53,10 +58,10 @@ public class Thief extends Thread { while (jar.takeBean()) { beans = beans + 1; - System.out.println(name + " took a bean."); + LOGGER.info("{} took a bean.", name); } - System.out.println(name + " took " + beans + " beans."); + LOGGER.info("{} took {} beans.", name, beans); } } diff --git a/naked-objects/dom/log4j.properties b/naked-objects/dom/log4j.properties deleted file mode 100644 index ca165acc7..000000000 --- a/naked-objects/dom/log4j.properties +++ /dev/null @@ -1,41 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -# LOG4J Configuration -# =================== - -# Basic logging goes to "datanucleus.log" -log4j.appender.A1=org.apache.log4j.FileAppender -log4j.appender.A1.File=datanucleus.log -log4j.appender.A1.layout=org.apache.log4j.PatternLayout -log4j.appender.A1.layout.ConversionPattern=%d{HH:mm:ss,SSS} (%t) %-5p [%c] - %m%n -#log4j.appender.A1.Threshold=INFO - -# Categories -# Each category can be set to a "level", and to direct to an appender - -# Default to DEBUG level for all DataNucleus categories -log4j.logger.DataNucleus = DEBUG, A1 - -log4j.category.com.mchange.v2.c3p0=INFO, A1 -log4j.category.com.mchange.v2.resourcepool=INFO, A1 -log4j.category.org.logicalcobwebs.proxool=INFO,A1 - - -# Hbase libs logging -log4j.category.org.apache.hadoop=INFO,A1 -log4j.category.org.apache.zookeeper=INFO,A1 \ No newline at end of file diff --git a/naked-objects/integtests/logging.properties b/naked-objects/integtests/logging.properties deleted file mode 100644 index b55249569..000000000 --- a/naked-objects/integtests/logging.properties +++ /dev/null @@ -1,111 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - - -# -# Isis uses log4j is used to provide system logging -# -log4j.rootCategory=INFO, Console - -# The console appender -log4j.appender.Console=org.apache.log4j.ConsoleAppender -log4j.appender.Console.target=System.out -log4j.appender.Console.layout=org.apache.log4j.PatternLayout -log4j.appender.Console.layout.ConversionPattern=%d{ABSOLUTE} [%-20c{1} %-10t %-5p] %m%n - -log4j.appender.File=org.apache.log4j.RollingFileAppender -log4j.appender.File.file=isis.log -log4j.appender.File.append=false -log4j.appender.File.layout=org.apache.log4j.PatternLayout -log4j.appender.File.layout.ConversionPattern=%d [%-20c{1} %-10t %-5p] %m%n - -log4j.appender.translations-po=org.apache.log4j.FileAppender -log4j.appender.translations-po.File=./translations.pot -log4j.appender.translations-po.Append=false -log4j.appender.translations-po.layout=org.apache.log4j.PatternLayout -log4j.appender.translations-po.layout.ConversionPattern=%m%n - -! turn on the internal log4j debugging flag so we can see what it is doing -#log4j.debug=true - - -# DataNucleus -# the first two log the DML and DDL (if set to DEBUG) -log4j.logger.DataNucleus.Datastore.Native=WARN, Console -log4j.logger.DataNucleus.Datastore.Schema=DEBUG, Console -# the remainder can probably be left to WARN -log4j.logger.DataNucleus.Persistence=WARN, Console -log4j.logger.DataNucleus.Transaction=WARN, Console -log4j.logger.DataNucleus.Connection=WARN, Console -log4j.logger.DataNucleus.Query=WARN, Console -log4j.logger.DataNucleus.Cache=WARN, Console -log4j.logger.DataNucleus.MetaData=WARN, Console -log4j.logger.DataNucleus.Datastore=WARN, Console -log4j.logger.DataNucleus.Datastore.Persist=WARN, Console -log4j.logger.DataNucleus.Datastore.Retrieve=WARN, Console -log4j.logger.DataNucleus.General=WARN, Console -log4j.logger.DataNucleus.Lifecycle=WARN, Console -log4j.logger.DataNucleus.ValueGeneration=WARN, Console -log4j.logger.DataNucleus.Enhancer=WARN, Console -log4j.logger.DataNucleus.SchemaTool=ERROR, Console -log4j.logger.DataNucleus.JDO=WARN, Console -log4j.logger.DataNucleus.JPA=ERROR, Console -log4j.logger.DataNucleus.JCA=WARN, Console -log4j.logger.DataNucleus.IDE=ERROR, Console - -log4j.additivity.DataNucleus.Datastore.Native=false -log4j.additivity.DataNucleus.Datastore.Schema=false -log4j.additivity.DataNucleus.Datastore.Persistence=false -log4j.additivity.DataNucleus.Datastore.Transaction=false -log4j.additivity.DataNucleus.Datastore.Connection=false -log4j.additivity.DataNucleus.Datastore.Query=false -log4j.additivity.DataNucleus.Datastore.Cache=false -log4j.additivity.DataNucleus.Datastore.MetaData=false -log4j.additivity.DataNucleus.Datastore.Datastore=false -log4j.additivity.DataNucleus.Datastore.Datastore.Persist=false -log4j.additivity.DataNucleus.Datastore.Datastore.Retrieve=false -log4j.additivity.DataNucleus.Datastore.General=false -log4j.additivity.DataNucleus.Datastore.Lifecycle=false -log4j.additivity.DataNucleus.Datastore.ValueGeneration=false -log4j.additivity.DataNucleus.Datastore.Enhancer=false -log4j.additivity.DataNucleus.Datastore.SchemaTool=false -log4j.additivity.DataNucleus.Datastore.JDO=false -log4j.additivity.DataNucleus.Datastore.JPA=false -log4j.additivity.DataNucleus.Datastore.JCA=false -log4j.additivity.DataNucleus.Datastore.IDE=false - - - - -# if using log4jdbc-remix as JDBC driver -#log4j.logger.jdbc.sqlonly=DEBUG, sql, Console -#log4j.additivity.jdbc.sqlonly=false -#log4j.logger.jdbc.resultsettable=DEBUG, jdbc, Console -#log4j.additivity.jdbc.resultsettable=false - -#log4j.logger.jdbc.audit=WARN,jdbc, Console -#log4j.additivity.jdbc.audit=false -#log4j.logger.jdbc.resultset=WARN,jdbc -#log4j.additivity.jdbc.resultset=false -#log4j.logger.jdbc.sqltiming=WARN,sqltiming -#log4j.additivity.jdbc.sqltiming=false -#log4j.logger.jdbc.connection=FATAL,connection -#log4j.additivity.jdbc.connection=false - - -log4j.logger.org.apache.isis.core.runtime.services.i18n.po.PoWriter=INFO,translations-po -log4j.additivity.org.apache.isis.core.runtime.services.i18n.po.PotWriter=false diff --git a/naked-objects/webapp/src/main/webapp/WEB-INF/logging.properties b/naked-objects/webapp/src/main/webapp/WEB-INF/logging.properties deleted file mode 100644 index 62fd8ea5e..000000000 --- a/naked-objects/webapp/src/main/webapp/WEB-INF/logging.properties +++ /dev/null @@ -1,187 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - - -# -# Isis uses log4j is used to provide system logging -# -log4j.rootCategory=INFO, Console -#log4j.rootCategory=DEBUG, Console - - -# The console appender -log4j.appender.Console=org.apache.log4j.ConsoleAppender -log4j.appender.Console.target=System.out -log4j.appender.Console.layout=org.apache.log4j.PatternLayout -log4j.appender.Console.layout.ConversionPattern=%d{ABSOLUTE} [%-20c{1} %-10t %-5p] %m%n - - -# The stderr appender -log4j.appender.Stderr=org.apache.log4j.ConsoleAppender -log4j.appender.Stderr.target=System.err -log4j.appender.Stderr.layout=org.apache.log4j.PatternLayout -log4j.appender.Stderr.layout.ConversionPattern=%d{ABSOLUTE} [%-20c{1} %-10t %-5p] %m%n - - -# other appenders -log4j.appender.File=org.apache.log4j.RollingFileAppender -log4j.appender.File.file=isis.log -log4j.appender.File.append=false -log4j.appender.File.layout=org.apache.log4j.PatternLayout -log4j.appender.File.layout.ConversionPattern=%d [%-20c{1} %-10t %-5p] %m%n - -log4j.appender.sql=org.apache.log4j.FileAppender -log4j.appender.sql.File=./logs/sql.log -log4j.appender.sql.Append=false -log4j.appender.sql.layout=org.apache.log4j.PatternLayout -log4j.appender.sql.layout.ConversionPattern=-----> %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n%n - -log4j.appender.sqltiming=org.apache.log4j.FileAppender -log4j.appender.sqltiming.File=./logs/sqltiming.log -log4j.appender.sqltiming.Append=false -log4j.appender.sqltiming.layout=org.apache.log4j.PatternLayout -log4j.appender.sqltiming.layout.ConversionPattern=-----> %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n%n - -log4j.appender.jdbc=org.apache.log4j.FileAppender -log4j.appender.jdbc.File=./logs/jdbc.log -log4j.appender.jdbc.Append=false -log4j.appender.jdbc.layout=org.apache.log4j.PatternLayout -log4j.appender.jdbc.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss.SSS} %m%n - -log4j.appender.connection=org.apache.log4j.FileAppender -log4j.appender.connection.File=./logs/connection.log -log4j.appender.connection.Append=false -log4j.appender.connection.layout=org.apache.log4j.PatternLayout -log4j.appender.connection.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss.SSS} %m%n - - - - -! turn on the internal log4j debugging flag so we can see what it is doing -#log4j.debug=true - - -# DataNucleus -# the first two log the DML and DDL (if set to DEBUG) -log4j.logger.DataNucleus.Datastore.Native=WARN, Console -log4j.logger.DataNucleus.Datastore.Schema=DEBUG, Console -# the remainder can probably be left to WARN -log4j.logger.DataNucleus.Persistence=WARN, Console -log4j.logger.DataNucleus.Transaction=WARN, Console -log4j.logger.DataNucleus.Connection=WARN, Console -log4j.logger.DataNucleus.Query=WARN, Console -log4j.logger.DataNucleus.Cache=WARN, Console -log4j.logger.DataNucleus.MetaData=WARN, Console -log4j.logger.DataNucleus.Datastore=WARN, Console -log4j.logger.DataNucleus.Datastore.Persist=WARN, Console -log4j.logger.DataNucleus.Datastore.Retrieve=WARN, Console -log4j.logger.DataNucleus.General=WARN, Console -log4j.logger.DataNucleus.Lifecycle=WARN, Console -log4j.logger.DataNucleus.ValueGeneration=WARN, Console -log4j.logger.DataNucleus.Enhancer=WARN, Console -log4j.logger.DataNucleus.SchemaTool=ERROR, Console -log4j.logger.DataNucleus.JDO=WARN, Console -log4j.logger.DataNucleus.JPA=ERROR, Console -log4j.logger.DataNucleus.JCA=WARN, Console -log4j.logger.DataNucleus.IDE=ERROR, Console - -log4j.additivity.DataNucleus.Datastore.Native=false -log4j.additivity.DataNucleus.Datastore.Schema=false -log4j.additivity.DataNucleus.Datastore.Persistence=false -log4j.additivity.DataNucleus.Datastore.Transaction=false -log4j.additivity.DataNucleus.Datastore.Connection=false -log4j.additivity.DataNucleus.Datastore.Query=false -log4j.additivity.DataNucleus.Datastore.Cache=false -log4j.additivity.DataNucleus.Datastore.MetaData=false -log4j.additivity.DataNucleus.Datastore.Datastore=false -log4j.additivity.DataNucleus.Datastore.Datastore.Persist=false -log4j.additivity.DataNucleus.Datastore.Datastore.Retrieve=false -log4j.additivity.DataNucleus.Datastore.General=false -log4j.additivity.DataNucleus.Datastore.Lifecycle=false -log4j.additivity.DataNucleus.Datastore.ValueGeneration=false -log4j.additivity.DataNucleus.Datastore.Enhancer=false -log4j.additivity.DataNucleus.Datastore.SchemaTool=false -log4j.additivity.DataNucleus.Datastore.JDO=false -log4j.additivity.DataNucleus.Datastore.JPA=false -log4j.additivity.DataNucleus.Datastore.JCA=false -log4j.additivity.DataNucleus.Datastore.IDE=false - - -# if using log4jdbc-remix as JDBC driver -#log4j.logger.jdbc.sqlonly=DEBUG, sql, Console -#log4j.additivity.jdbc.sqlonly=false -#log4j.logger.jdbc.resultsettable=DEBUG, jdbc, Console -#log4j.additivity.jdbc.resultsettable=false - -#log4j.logger.jdbc.audit=WARN,jdbc, Console -#log4j.additivity.jdbc.audit=false -#log4j.logger.jdbc.resultset=WARN,jdbc -#log4j.additivity.jdbc.resultset=false -#log4j.logger.jdbc.sqltiming=WARN,sqltiming -#log4j.additivity.jdbc.sqltiming=false -#log4j.logger.jdbc.connection=FATAL,connection -#log4j.additivity.jdbc.connection=false - - - -# track Isis/JDO lifecycle integration - -#log4j.logger.org.apache.isis.runtimes.dflt.objectstores.jdo.datanucleus.persistence.FrameworkSynchronizer=DEBUG, Console -#log4j.additivity.org.apache.isis.runtimes.dflt.objectstores.jdo.datanucleus.persistence.FrameworkSynchronizer=false - -#log4j.logger.org.apache.isis.objectstore.jdo.datanucleus.persistence.IsisLifecycleListener=DEBUG,Console -#log4j.additivity.org.apache.isis.objectstore.jdo.datanucleus.persistence.IsisLifecycleListener=false - - - - -# track Isis/Wicket lifecycle integration - -#log4j.logger.org.apache.isis.viewer.wicket.viewer.integration.wicket.WebRequestCycleForIsis=DEBUG, Console -#log4j.additivity.org.apache.isis.viewer.wicket.viewer.integration.wicket.WebRequestCycleForIsis=false - -#log4j.logger.org.apache.isis.viewer.wicket.viewer.integration.isis.IsisContextForWicket=INFO,Console -#log4j.additivity.org.apache.isis.viewer.wicket.viewer.integration.isis.IsisContextForWicket=false - - - - -# quieten some of the noisier classes in Isis' bootstrapping -log4j.logger.org.apache.isis.core.metamodel.specloader.specimpl.FacetedMethodsBuilder=WARN,Console -log4j.additivity.org.apache.isis.core.metamodel.specloader.specimpl.FacetedMethodsBuilder=false - -log4j.logger.org.apache.isis.core.metamodel.specloader.ServiceInitializer=WARN,Console -log4j.additivity.org.apache.isis.core.metamodel.specloader.ServiceInitializer=false - -log4j.logger.org.apache.isis.core.runtime.services.ServicesInstallerFromConfiguration=WARN,Console -log4j.additivity.org.apache.isis.core.runtime.services.ServicesInstallerFromConfiguration=false - -log4j.logger.org.apache.isis.core.commons.config.IsisConfigurationDefault=WARN,Console -log4j.additivity.org.apache.isis.core.commons.config.IsisConfigurationDefault=false - -log4j.logger.org.apache.isis.core.runtime.installers.InstallerLookupDefault=WARN,Console -log4j.additivity.org.apache.isis.core.runtime.installers.InstallerLookupDefault=false - - -# quieten Shiro -log4j.logger.org.apache.shiro.realm.AuthorizingRealm=WARN,Console -log4j.additivity.log4j.logger.org.apache.shiro.realm.AuthorizingRealm=false - - -# Application-specific logging -log4j.logger.dom.simple.SimpleObject=DEBUG, Stderr -log4j.additivity.dom.simple.SimpleObject=false \ No newline at end of file diff --git a/null-object/src/main/java/com/iluwatar/nullobject/NodeImpl.java b/null-object/src/main/java/com/iluwatar/nullobject/NodeImpl.java index 46787ac96..c2fd66849 100644 --- a/null-object/src/main/java/com/iluwatar/nullobject/NodeImpl.java +++ b/null-object/src/main/java/com/iluwatar/nullobject/NodeImpl.java @@ -22,6 +22,9 @@ */ package com.iluwatar.nullobject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * Implementation for binary tree's normal nodes. @@ -29,6 +32,8 @@ package com.iluwatar.nullobject; */ public class NodeImpl implements Node { + private static final Logger LOGGER = LoggerFactory.getLogger(NodeImpl.class); + private final String name; private final Node left; private final Node right; @@ -64,7 +69,7 @@ public class NodeImpl implements Node { @Override public void walk() { - System.out.println(name); + LOGGER.info(name); if (left.getTreeSize() > 0) { left.walk(); } diff --git a/object-pool/src/main/java/com/iluwatar/object/pool/App.java b/object-pool/src/main/java/com/iluwatar/object/pool/App.java index 66b3e3f90..b49dd70d7 100644 --- a/object-pool/src/main/java/com/iluwatar/object/pool/App.java +++ b/object-pool/src/main/java/com/iluwatar/object/pool/App.java @@ -22,6 +22,9 @@ */ package com.iluwatar.object.pool; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * When it is necessary to work with a large number of objects that are particularly expensive to @@ -44,6 +47,8 @@ package com.iluwatar.object.pool; */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point * @@ -51,24 +56,24 @@ public class App { */ public static void main(String[] args) { OliphauntPool pool = new OliphauntPool(); - System.out.println(pool); + LOGGER.info(pool.toString()); Oliphaunt oliphaunt1 = pool.checkOut(); - System.out.println("Checked out " + oliphaunt1); - System.out.println(pool); + LOGGER.info("Checked out {}", oliphaunt1); + LOGGER.info(pool.toString()); Oliphaunt oliphaunt2 = pool.checkOut(); - System.out.println("Checked out " + oliphaunt2); + LOGGER.info("Checked out {}", oliphaunt2); Oliphaunt oliphaunt3 = pool.checkOut(); - System.out.println("Checked out " + oliphaunt3); - System.out.println(pool); - System.out.println("Checking in " + oliphaunt1); + LOGGER.info("Checked out {}", oliphaunt3); + LOGGER.info(pool.toString()); + LOGGER.info("Checking in {}", oliphaunt1); pool.checkIn(oliphaunt1); - System.out.println("Checking in " + oliphaunt2); + LOGGER.info("Checking in {}", oliphaunt2); pool.checkIn(oliphaunt2); - System.out.println(pool); + LOGGER.info(pool.toString()); Oliphaunt oliphaunt4 = pool.checkOut(); - System.out.println("Checked out " + oliphaunt4); + LOGGER.info("Checked out {}", oliphaunt4); Oliphaunt oliphaunt5 = pool.checkOut(); - System.out.println("Checked out " + oliphaunt5); - System.out.println(pool); + LOGGER.info("Checked out {}", oliphaunt5); + LOGGER.info(pool.toString()); } } diff --git a/observer/src/main/java/com/iluwatar/observer/App.java b/observer/src/main/java/com/iluwatar/observer/App.java index dcced00d4..d6a8e0df6 100644 --- a/observer/src/main/java/com/iluwatar/observer/App.java +++ b/observer/src/main/java/com/iluwatar/observer/App.java @@ -25,6 +25,8 @@ package com.iluwatar.observer; import com.iluwatar.observer.generic.GHobbits; import com.iluwatar.observer.generic.GOrcs; import com.iluwatar.observer.generic.GWeather; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * @@ -41,6 +43,8 @@ import com.iluwatar.observer.generic.GWeather; */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point * @@ -58,7 +62,7 @@ public class App { weather.timePasses(); // Generic observer inspired by Java Generics and Collection by Naftalin & Wadler - System.out.println("\n--Running generic version--"); + LOGGER.info("--Running generic version--"); GWeather gWeather = new GWeather(); gWeather.addObserver(new GOrcs()); gWeather.addObserver(new GHobbits()); diff --git a/observer/src/main/java/com/iluwatar/observer/Hobbits.java b/observer/src/main/java/com/iluwatar/observer/Hobbits.java index ed9636bd6..74ffee713 100644 --- a/observer/src/main/java/com/iluwatar/observer/Hobbits.java +++ b/observer/src/main/java/com/iluwatar/observer/Hobbits.java @@ -22,6 +22,9 @@ */ package com.iluwatar.observer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * Hobbits @@ -29,20 +32,22 @@ package com.iluwatar.observer; */ public class Hobbits implements WeatherObserver { + private static final Logger LOGGER = LoggerFactory.getLogger(Hobbits.class); + @Override public void update(WeatherType currentWeather) { switch (currentWeather) { case COLD: - System.out.println("The hobbits are shivering in the cold weather."); + LOGGER.info("The hobbits are shivering in the cold weather."); break; case RAINY: - System.out.println("The hobbits look for cover from the rain."); + LOGGER.info("The hobbits look for cover from the rain."); break; case SUNNY: - System.out.println("The happy hobbits bade in the warm sun."); + LOGGER.info("The happy hobbits bade in the warm sun."); break; case WINDY: - System.out.println("The hobbits hold their hats tightly in the windy weather."); + LOGGER.info("The hobbits hold their hats tightly in the windy weather."); break; default: break; diff --git a/observer/src/main/java/com/iluwatar/observer/Orcs.java b/observer/src/main/java/com/iluwatar/observer/Orcs.java index ce9c09944..65ddc840f 100644 --- a/observer/src/main/java/com/iluwatar/observer/Orcs.java +++ b/observer/src/main/java/com/iluwatar/observer/Orcs.java @@ -22,6 +22,9 @@ */ package com.iluwatar.observer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * Orcs @@ -29,20 +32,22 @@ package com.iluwatar.observer; */ public class Orcs implements WeatherObserver { + private static final Logger LOGGER = LoggerFactory.getLogger(Orcs.class); + @Override public void update(WeatherType currentWeather) { switch (currentWeather) { case COLD: - System.out.println("The orcs are freezing cold."); + LOGGER.info("The orcs are freezing cold."); break; case RAINY: - System.out.println("The orcs are dripping wet."); + LOGGER.info("The orcs are dripping wet."); break; case SUNNY: - System.out.println("The sun hurts the orcs' eyes."); + LOGGER.info("The sun hurts the orcs' eyes."); break; case WINDY: - System.out.println("The orc smell almost vanishes in the wind."); + LOGGER.info("The orc smell almost vanishes in the wind."); break; default: break; diff --git a/observer/src/main/java/com/iluwatar/observer/Weather.java b/observer/src/main/java/com/iluwatar/observer/Weather.java index f6aad3881..c89ffd366 100644 --- a/observer/src/main/java/com/iluwatar/observer/Weather.java +++ b/observer/src/main/java/com/iluwatar/observer/Weather.java @@ -22,6 +22,9 @@ */ package com.iluwatar.observer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.util.ArrayList; import java.util.List; @@ -33,6 +36,8 @@ import java.util.List; */ public class Weather { + private static final Logger LOGGER = LoggerFactory.getLogger(Weather.class); + private WeatherType currentWeather; private List observers; @@ -55,7 +60,7 @@ public class Weather { public void timePasses() { WeatherType[] enumValues = WeatherType.values(); currentWeather = enumValues[(currentWeather.ordinal() + 1) % enumValues.length]; - System.out.println("The weather changed to " + currentWeather + "."); + LOGGER.info("The weather changed to {}.", currentWeather); notifyObservers(); } diff --git a/observer/src/main/java/com/iluwatar/observer/generic/GHobbits.java b/observer/src/main/java/com/iluwatar/observer/generic/GHobbits.java index da84b9aab..f70a1a62e 100644 --- a/observer/src/main/java/com/iluwatar/observer/generic/GHobbits.java +++ b/observer/src/main/java/com/iluwatar/observer/generic/GHobbits.java @@ -23,6 +23,8 @@ package com.iluwatar.observer.generic; import com.iluwatar.observer.WeatherType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * @@ -30,20 +32,23 @@ import com.iluwatar.observer.WeatherType; * */ public class GHobbits implements Race { + + private static final Logger LOGGER = LoggerFactory.getLogger(GHobbits.class); + @Override public void update(GWeather weather, WeatherType weatherType) { switch (weatherType) { case COLD: - System.out.println("The hobbits are shivering in the cold weather."); + LOGGER.info("The hobbits are shivering in the cold weather."); break; case RAINY: - System.out.println("The hobbits look for cover from the rain."); + LOGGER.info("The hobbits look for cover from the rain."); break; case SUNNY: - System.out.println("The happy hobbits bade in the warm sun."); + LOGGER.info("The happy hobbits bade in the warm sun."); break; case WINDY: - System.out.println("The hobbits hold their hats tightly in the windy weather."); + LOGGER.info("The hobbits hold their hats tightly in the windy weather."); break; default: break; diff --git a/observer/src/main/java/com/iluwatar/observer/generic/GOrcs.java b/observer/src/main/java/com/iluwatar/observer/generic/GOrcs.java index 9f41aa6cc..3171f4e7c 100644 --- a/observer/src/main/java/com/iluwatar/observer/generic/GOrcs.java +++ b/observer/src/main/java/com/iluwatar/observer/generic/GOrcs.java @@ -23,6 +23,8 @@ package com.iluwatar.observer.generic; import com.iluwatar.observer.WeatherType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * @@ -31,20 +33,22 @@ import com.iluwatar.observer.WeatherType; */ public class GOrcs implements Race { + private static final Logger LOGGER = LoggerFactory.getLogger(GOrcs.class); + @Override public void update(GWeather weather, WeatherType weatherType) { switch (weatherType) { case COLD: - System.out.println("The orcs are freezing cold."); + LOGGER.info("The orcs are freezing cold."); break; case RAINY: - System.out.println("The orcs are dripping wet."); + LOGGER.info("The orcs are dripping wet."); break; case SUNNY: - System.out.println("The sun hurts the orcs' eyes."); + LOGGER.info("The sun hurts the orcs' eyes."); break; case WINDY: - System.out.println("The orc smell almost vanishes in the wind."); + LOGGER.info("The orc smell almost vanishes in the wind."); break; default: break; diff --git a/observer/src/main/java/com/iluwatar/observer/generic/GWeather.java b/observer/src/main/java/com/iluwatar/observer/generic/GWeather.java index 137000760..631da479e 100644 --- a/observer/src/main/java/com/iluwatar/observer/generic/GWeather.java +++ b/observer/src/main/java/com/iluwatar/observer/generic/GWeather.java @@ -23,6 +23,8 @@ package com.iluwatar.observer.generic; import com.iluwatar.observer.WeatherType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * @@ -31,6 +33,8 @@ import com.iluwatar.observer.WeatherType; */ public class GWeather extends Observable { + private static final Logger LOGGER = LoggerFactory.getLogger(GWeather.class); + private WeatherType currentWeather; public GWeather() { @@ -43,7 +47,7 @@ public class GWeather extends Observable { public void timePasses() { WeatherType[] enumValues = WeatherType.values(); currentWeather = enumValues[(currentWeather.ordinal() + 1) % enumValues.length]; - System.out.println("The weather changed to " + currentWeather + "."); + LOGGER.info("The weather changed to {}.", currentWeather); notifyObservers(currentWeather); } } diff --git a/poison-pill/src/main/java/com/iluwatar/poison/pill/Consumer.java b/poison-pill/src/main/java/com/iluwatar/poison/pill/Consumer.java index c811225e1..6a586c52d 100644 --- a/poison-pill/src/main/java/com/iluwatar/poison/pill/Consumer.java +++ b/poison-pill/src/main/java/com/iluwatar/poison/pill/Consumer.java @@ -23,11 +23,15 @@ package com.iluwatar.poison.pill; import com.iluwatar.poison.pill.Message.Headers; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Class responsible for receiving and handling submitted to the queue messages */ public class Consumer { + + private static final Logger LOGGER = LoggerFactory.getLogger(Consumer.class); private final MqSubscribePoint queue; private final String name; @@ -46,19 +50,18 @@ public class Consumer { try { msg = queue.take(); if (Message.POISON_PILL.equals(msg)) { - System.out.println(String.format("Consumer %s receive request to terminate.", name)); + LOGGER.info("Consumer {} receive request to terminate.", name); break; } } catch (InterruptedException e) { // allow thread to exit - System.err.println(e); + LOGGER.error("Exception caught.", e); return; } String sender = msg.getHeader(Headers.SENDER); String body = msg.getBody(); - System.out.println(String.format("Message [%s] from [%s] received by [%s]", body, sender, - name)); + LOGGER.info("Message [{}] from [{}] received by [{}]", body, sender, name); } } } diff --git a/poison-pill/src/main/java/com/iluwatar/poison/pill/Producer.java b/poison-pill/src/main/java/com/iluwatar/poison/pill/Producer.java index 15dcad40e..af07ed679 100644 --- a/poison-pill/src/main/java/com/iluwatar/poison/pill/Producer.java +++ b/poison-pill/src/main/java/com/iluwatar/poison/pill/Producer.java @@ -25,6 +25,8 @@ package com.iluwatar.poison.pill; import java.util.Date; import com.iluwatar.poison.pill.Message.Headers; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Class responsible for producing unit of work that can be expressed as message and submitted to @@ -32,6 +34,8 @@ import com.iluwatar.poison.pill.Message.Headers; */ public class Producer { + private static final Logger LOGGER = LoggerFactory.getLogger(Producer.class); + private final MqPublishPoint queue; private final String name; private boolean isStopped; @@ -62,7 +66,7 @@ public class Producer { queue.put(msg); } catch (InterruptedException e) { // allow thread to exit - System.err.println(e); + LOGGER.error("Exception caught.", e); } } @@ -75,7 +79,7 @@ public class Producer { queue.put(Message.POISON_PILL); } catch (InterruptedException e) { // allow thread to exit - System.err.println(e); + LOGGER.error("Exception caught.", e); } } } diff --git a/pom.xml b/pom.xml index 144b8efff..d4d7ff581 100644 --- a/pom.xml +++ b/pom.xml @@ -39,7 +39,6 @@ 0.7.2.201409121644 1.4 2.16.1 - 1.2.17 19.0 1.15.1 1.10.19 @@ -49,6 +48,8 @@ 1.4.1 4.0 3.3.0 + 1.7.21 + 1.1.7 abstract-factory @@ -210,11 +211,6 @@ ${mockito.version} test - - log4j - log4j - ${log4j.version} - com.google.guava guava @@ -251,6 +247,23 @@ + + + org.slf4j + slf4j-api + ${slf4j.version} + + + ch.qos.logback + logback-classic + ${logback.version} + + + ch.qos.logback + logback-core + ${logback.version} + + diff --git a/private-class-data/src/main/java/com/iluwatar/privateclassdata/ImmutableStew.java b/private-class-data/src/main/java/com/iluwatar/privateclassdata/ImmutableStew.java index b9d2ad09c..73bfb948f 100644 --- a/private-class-data/src/main/java/com/iluwatar/privateclassdata/ImmutableStew.java +++ b/private-class-data/src/main/java/com/iluwatar/privateclassdata/ImmutableStew.java @@ -22,6 +22,9 @@ */ package com.iluwatar.privateclassdata; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * Immutable stew class, protected with Private Class Data pattern @@ -29,6 +32,8 @@ package com.iluwatar.privateclassdata; */ public class ImmutableStew { + private static final Logger LOGGER = LoggerFactory.getLogger(ImmutableStew.class); + private StewData data; public ImmutableStew(int numPotatoes, int numCarrots, int numMeat, int numPeppers) { @@ -39,8 +44,7 @@ public class ImmutableStew { * Mix the stew */ public void mix() { - System.out.println(String.format( - "Mixing the immutable stew we find: %d potatoes, %d carrots, %d meat and %d peppers", - data.getNumPotatoes(), data.getNumCarrots(), data.getNumMeat(), data.getNumPeppers())); + LOGGER.info("Mixing the immutable stew we find: {} potatoes, {} carrots, {} meat and {} peppers", + data.getNumPotatoes(), data.getNumCarrots(), data.getNumMeat(), data.getNumPeppers()); } } diff --git a/private-class-data/src/main/java/com/iluwatar/privateclassdata/Stew.java b/private-class-data/src/main/java/com/iluwatar/privateclassdata/Stew.java index 9c9033018..665edf418 100644 --- a/private-class-data/src/main/java/com/iluwatar/privateclassdata/Stew.java +++ b/private-class-data/src/main/java/com/iluwatar/privateclassdata/Stew.java @@ -22,6 +22,9 @@ */ package com.iluwatar.privateclassdata; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * Mutable stew class @@ -29,6 +32,8 @@ package com.iluwatar.privateclassdata; */ public class Stew { + private static final Logger LOGGER = LoggerFactory.getLogger(Stew.class); + private int numPotatoes; private int numCarrots; private int numMeat; @@ -48,16 +53,15 @@ public class Stew { * Mix the stew */ public void mix() { - System.out.println(String.format( - "Mixing the stew we find: %d potatoes, %d carrots, %d meat and %d peppers", numPotatoes, - numCarrots, numMeat, numPeppers)); + LOGGER.info("Mixing the stew we find: {} potatoes, {} carrots, {} meat and {} peppers", + numPotatoes, numCarrots, numMeat, numPeppers); } /** * Taste the stew */ public void taste() { - System.out.println("Tasting the stew"); + LOGGER.info("Tasting the stew"); if (numPotatoes > 0) { numPotatoes--; } diff --git a/producer-consumer/src/main/java/com/iluwatar/producer/consumer/App.java b/producer-consumer/src/main/java/com/iluwatar/producer/consumer/App.java index 42f6dfa79..dca2457c4 100644 --- a/producer-consumer/src/main/java/com/iluwatar/producer/consumer/App.java +++ b/producer-consumer/src/main/java/com/iluwatar/producer/consumer/App.java @@ -22,6 +22,9 @@ */ package com.iluwatar.producer.consumer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; @@ -37,6 +40,8 @@ import java.util.concurrent.TimeUnit; */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point * @@ -72,7 +77,7 @@ public class App { executorService.awaitTermination(10, TimeUnit.SECONDS); executorService.shutdownNow(); } catch (InterruptedException e) { - System.out.println("Error waiting for ExecutorService shutdown"); + LOGGER.error("Error waiting for ExecutorService shutdown"); } } } diff --git a/producer-consumer/src/main/java/com/iluwatar/producer/consumer/Consumer.java b/producer-consumer/src/main/java/com/iluwatar/producer/consumer/Consumer.java index f1fa920f3..880b76ba5 100644 --- a/producer-consumer/src/main/java/com/iluwatar/producer/consumer/Consumer.java +++ b/producer-consumer/src/main/java/com/iluwatar/producer/consumer/Consumer.java @@ -22,11 +22,16 @@ */ package com.iluwatar.producer.consumer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * Class responsible for consume the {@link Item} produced by {@link Producer} */ public class Consumer { + private static final Logger LOGGER = LoggerFactory.getLogger(Consumer.class); + private final ItemQueue queue; private final String name; @@ -42,8 +47,7 @@ public class Consumer { public void consume() throws InterruptedException { Item item = queue.take(); - System.out.println(String.format("Consumer [%s] consume item [%s] produced by [%s]", name, - item.getId(), item.getProducer())); + LOGGER.info("Consumer [{}] consume item [{}] produced by [{}]", name, item.getId(), item.getProducer()); } } diff --git a/promise/src/main/java/com/iluwatar/promise/App.java b/promise/src/main/java/com/iluwatar/promise/App.java index 672c20bfa..7e1f174ef 100644 --- a/promise/src/main/java/com/iluwatar/promise/App.java +++ b/promise/src/main/java/com/iluwatar/promise/App.java @@ -21,6 +21,9 @@ * THE SOFTWARE. */ package com.iluwatar.promise; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CountDownLatch; @@ -60,6 +63,8 @@ import java.util.concurrent.Executors; */ 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 final ExecutorService executor; private final CountDownLatch stopLatch; @@ -98,7 +103,7 @@ public class App { lowestFrequencyChar() .thenAccept( charFrequency -> { - System.out.println("Char with lowest frequency is: " + charFrequency); + LOGGER.info("Char with lowest frequency is: {}", charFrequency); taskCompleted(); } ); @@ -112,7 +117,7 @@ public class App { countLines() .thenAccept( count -> { - System.out.println("Line count is: " + count); + LOGGER.info("Line count is: {}", count); taskCompleted(); } ); diff --git a/promise/src/main/java/com/iluwatar/promise/Utility.java b/promise/src/main/java/com/iluwatar/promise/Utility.java index d451600a3..769a6fcd1 100644 --- a/promise/src/main/java/com/iluwatar/promise/Utility.java +++ b/promise/src/main/java/com/iluwatar/promise/Utility.java @@ -22,6 +22,9 @@ */ package com.iluwatar.promise; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.io.BufferedReader; import java.io.File; import java.io.FileReader; @@ -38,6 +41,8 @@ import java.util.Map.Entry; public class Utility { + private static final Logger LOGGER = LoggerFactory.getLogger(Utility.class); + /** * Calculates character frequency of the file provided. * @param fileLocation location of the file. @@ -104,7 +109,7 @@ public class Utility { * @return the absolute path of the file downloaded. */ public static String downloadFile(String urlString) throws MalformedURLException, IOException { - System.out.println("Downloading contents from url: " + urlString); + LOGGER.info("Downloading contents from url: {}", urlString); URL url = new URL(urlString); File file = File.createTempFile("promise_pattern", null); try (Reader reader = new InputStreamReader(url.openStream()); @@ -114,7 +119,7 @@ public class Utility { writer.write(line); writer.write("\n"); } - System.out.println("File downloaded at: " + file.getAbsolutePath()); + LOGGER.info("File downloaded at: {}", file.getAbsolutePath()); return file.getAbsolutePath(); } catch (IOException ex) { throw ex; diff --git a/property/src/main/java/com/iluwatar/property/App.java b/property/src/main/java/com/iluwatar/property/App.java index e3f7cc92b..576bada18 100644 --- a/property/src/main/java/com/iluwatar/property/App.java +++ b/property/src/main/java/com/iluwatar/property/App.java @@ -23,6 +23,8 @@ package com.iluwatar.property; import com.iluwatar.property.Character.Type; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * @@ -39,6 +41,8 @@ import com.iluwatar.property.Character.Type; */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point * @@ -67,16 +71,16 @@ public class App { /* usage */ Character mag = new Character("Player_1", mageProto); mag.set(Stats.ARMOR, 8); - System.out.println(mag); + LOGGER.info(mag.toString()); Character warrior = new Character("Player_2", warProto); - System.out.println(warrior); + LOGGER.info(warrior.toString()); Character rogue = new Character("Player_3", rogueProto); - System.out.println(rogue); + LOGGER.info(rogue.toString()); Character rogueDouble = new Character("Player_4", rogue); rogueDouble.set(Stats.ATTACK_POWER, 12); - System.out.println(rogueDouble); + LOGGER.info(rogueDouble.toString()); } } diff --git a/prototype/src/main/java/com/iluwatar/prototype/App.java b/prototype/src/main/java/com/iluwatar/prototype/App.java index cb04ec5f2..bb98194ce 100644 --- a/prototype/src/main/java/com/iluwatar/prototype/App.java +++ b/prototype/src/main/java/com/iluwatar/prototype/App.java @@ -22,6 +22,9 @@ */ package com.iluwatar.prototype; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * The Prototype pattern is a creational design pattern in software development. It is used when the @@ -36,6 +39,8 @@ package com.iluwatar.prototype; */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point * @@ -51,16 +56,16 @@ public class App { mage = factory.createMage(); warlord = factory.createWarlord(); beast = factory.createBeast(); - System.out.println(mage); - System.out.println(warlord); - System.out.println(beast); + LOGGER.info(mage.toString()); + LOGGER.info(warlord.toString()); + LOGGER.info(beast.toString()); factory = new HeroFactoryImpl(new OrcMage(), new OrcWarlord(), new OrcBeast()); mage = factory.createMage(); warlord = factory.createWarlord(); beast = factory.createBeast(); - System.out.println(mage); - System.out.println(warlord); - System.out.println(beast); + LOGGER.info(mage.toString()); + LOGGER.info(warlord.toString()); + LOGGER.info(beast.toString()); } } diff --git a/proxy/src/main/java/com/iluwatar/proxy/WizardTower.java b/proxy/src/main/java/com/iluwatar/proxy/WizardTower.java index 573d38374..d5daab305 100644 --- a/proxy/src/main/java/com/iluwatar/proxy/WizardTower.java +++ b/proxy/src/main/java/com/iluwatar/proxy/WizardTower.java @@ -22,6 +22,9 @@ */ package com.iluwatar.proxy; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * The object to be proxyed. @@ -29,8 +32,10 @@ package com.iluwatar.proxy; */ public class WizardTower { + private static final Logger LOGGER = LoggerFactory.getLogger(WizardTower.class); + public void enter(Wizard wizard) { - System.out.println(wizard + " enters the tower."); + LOGGER.info("{} enters the tower.", wizard); } } diff --git a/proxy/src/main/java/com/iluwatar/proxy/WizardTowerProxy.java b/proxy/src/main/java/com/iluwatar/proxy/WizardTowerProxy.java index 985184afe..1048724d4 100644 --- a/proxy/src/main/java/com/iluwatar/proxy/WizardTowerProxy.java +++ b/proxy/src/main/java/com/iluwatar/proxy/WizardTowerProxy.java @@ -22,6 +22,9 @@ */ package com.iluwatar.proxy; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * The proxy controlling access to the {@link WizardTower}. @@ -29,6 +32,8 @@ package com.iluwatar.proxy; */ public class WizardTowerProxy extends WizardTower { + private static final Logger LOGGER = LoggerFactory.getLogger(WizardTowerProxy.class); + private static final int NUM_WIZARDS_ALLOWED = 3; private int numWizards; @@ -39,7 +44,7 @@ public class WizardTowerProxy extends WizardTower { super.enter(wizard); numWizards++; } else { - System.out.println(wizard + " is not allowed to enter!"); + LOGGER.info("{} is not allowed to enter!", wizard); } } } diff --git a/publish-subscribe/src/main/java/com/iluwatar/publish/subscribe/App.java b/publish-subscribe/src/main/java/com/iluwatar/publish/subscribe/App.java index c4e423b04..ff66e4e58 100644 --- a/publish-subscribe/src/main/java/com/iluwatar/publish/subscribe/App.java +++ b/publish-subscribe/src/main/java/com/iluwatar/publish/subscribe/App.java @@ -26,6 +26,8 @@ import org.apache.camel.CamelContext; import org.apache.camel.ProducerTemplate; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.impl.DefaultCamelContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * @@ -48,6 +50,8 @@ import org.apache.camel.impl.DefaultCamelContext; */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point */ @@ -61,7 +65,7 @@ public class App { }); ProducerTemplate template = context.createProducerTemplate(); context.start(); - context.getRoutes().stream().forEach(r -> System.out.println(r)); + context.getRoutes().stream().forEach(r -> LOGGER.info(r.toString())); template.sendBody("direct:origin", "Hello from origin"); context.stop(); } diff --git a/reactor/src/main/java/com/iluwatar/reactor/app/AppClient.java b/reactor/src/main/java/com/iluwatar/reactor/app/AppClient.java index 29c2f83fa..77e4e1f4f 100644 --- a/reactor/src/main/java/com/iluwatar/reactor/app/AppClient.java +++ b/reactor/src/main/java/com/iluwatar/reactor/app/AppClient.java @@ -22,6 +22,9 @@ */ package com.iluwatar.reactor.app; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -41,6 +44,9 @@ import java.util.concurrent.TimeUnit; * requests to Reactor. */ public class AppClient { + + private static final Logger LOGGER = LoggerFactory.getLogger(AppClient.class); + private final ExecutorService service = Executors.newFixedThreadPool(4); /** @@ -126,9 +132,9 @@ public class AppClient { byte[] data = new byte[1024]; int read = inputStream.read(data, 0, data.length); if (read == 0) { - System.out.println("Read zero bytes"); + LOGGER.info("Read zero bytes"); } else { - System.out.println(new String(data, 0, read)); + LOGGER.info(new String(data, 0, read)); } artificialDelayOf(100); @@ -171,9 +177,9 @@ public class AppClient { DatagramPacket reply = new DatagramPacket(data, data.length); socket.receive(reply); if (reply.getLength() == 0) { - System.out.println("Read zero bytes"); + LOGGER.info("Read zero bytes"); } else { - System.out.println(new String(reply.getData(), 0, reply.getLength())); + LOGGER.info(new String(reply.getData(), 0, reply.getLength())); } artificialDelayOf(100); diff --git a/reactor/src/main/java/com/iluwatar/reactor/app/LoggingHandler.java b/reactor/src/main/java/com/iluwatar/reactor/app/LoggingHandler.java index ab2bcfb1a..e1095d34e 100644 --- a/reactor/src/main/java/com/iluwatar/reactor/app/LoggingHandler.java +++ b/reactor/src/main/java/com/iluwatar/reactor/app/LoggingHandler.java @@ -28,6 +28,8 @@ import java.nio.channels.SelectionKey; import com.iluwatar.reactor.framework.AbstractNioChannel; import com.iluwatar.reactor.framework.ChannelHandler; import com.iluwatar.reactor.framework.NioDatagramChannel.DatagramPacket; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Logging server application logic. It logs the incoming requests on standard console and returns a @@ -35,6 +37,8 @@ import com.iluwatar.reactor.framework.NioDatagramChannel.DatagramPacket; */ public class LoggingHandler implements ChannelHandler { + private static final Logger LOGGER = LoggerFactory.getLogger(LoggingHandler.class); + private static final byte[] ACK = "Data logged successfully".getBytes(); /** @@ -76,6 +80,6 @@ public class LoggingHandler implements ChannelHandler { private static void doLogging(ByteBuffer data) { // assuming UTF-8 :( - System.out.println(new String(data.array(), 0, data.limit())); + LOGGER.info(new String(data.array(), 0, data.limit())); } } diff --git a/reactor/src/main/java/com/iluwatar/reactor/framework/NioDatagramChannel.java b/reactor/src/main/java/com/iluwatar/reactor/framework/NioDatagramChannel.java index 4e493163f..52d2d68b0 100644 --- a/reactor/src/main/java/com/iluwatar/reactor/framework/NioDatagramChannel.java +++ b/reactor/src/main/java/com/iluwatar/reactor/framework/NioDatagramChannel.java @@ -22,6 +22,9 @@ */ package com.iluwatar.reactor.framework; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; @@ -35,6 +38,8 @@ import java.nio.channels.SelectionKey; */ public class NioDatagramChannel extends AbstractNioChannel { + private static final Logger LOGGER = LoggerFactory.getLogger(NioDatagramChannel.class); + private final int port; /** @@ -99,7 +104,7 @@ public class NioDatagramChannel extends AbstractNioChannel { public void bind() throws IOException { getJavaChannel().socket().bind(new InetSocketAddress(InetAddress.getLocalHost(), port)); getJavaChannel().configureBlocking(false); - System.out.println("Bound UDP socket at port: " + port); + LOGGER.info("Bound UDP socket at port: {}", port); } /** diff --git a/reactor/src/main/java/com/iluwatar/reactor/framework/NioReactor.java b/reactor/src/main/java/com/iluwatar/reactor/framework/NioReactor.java index 3d5ebf5a0..0facf1935 100644 --- a/reactor/src/main/java/com/iluwatar/reactor/framework/NioReactor.java +++ b/reactor/src/main/java/com/iluwatar/reactor/framework/NioReactor.java @@ -22,6 +22,9 @@ */ package com.iluwatar.reactor.framework; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.io.IOException; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; @@ -53,6 +56,8 @@ import java.util.concurrent.TimeUnit; */ public class NioReactor { + private static final Logger LOGGER = LoggerFactory.getLogger(NioReactor.class); + private final Selector selector; private final Dispatcher dispatcher; /** @@ -86,7 +91,7 @@ public class NioReactor { public void start() throws IOException { reactorMain.execute(() -> { try { - System.out.println("Reactor started, waiting for events..."); + LOGGER.info("Reactor started, waiting for events..."); eventLoop(); } catch (IOException e) { e.printStackTrace(); diff --git a/reactor/src/main/java/com/iluwatar/reactor/framework/NioServerSocketChannel.java b/reactor/src/main/java/com/iluwatar/reactor/framework/NioServerSocketChannel.java index c7d67fd13..d1c6bb62a 100644 --- a/reactor/src/main/java/com/iluwatar/reactor/framework/NioServerSocketChannel.java +++ b/reactor/src/main/java/com/iluwatar/reactor/framework/NioServerSocketChannel.java @@ -22,6 +22,9 @@ */ package com.iluwatar.reactor.framework; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; @@ -36,6 +39,8 @@ import java.nio.channels.SocketChannel; */ public class NioServerSocketChannel extends AbstractNioChannel { + private static final Logger LOGGER = LoggerFactory.getLogger(NioServerSocketChannel.class); + private final int port; /** @@ -96,7 +101,7 @@ public class NioServerSocketChannel extends AbstractNioChannel { ((ServerSocketChannel) getJavaChannel()).socket().bind( new InetSocketAddress(InetAddress.getLocalHost(), port)); ((ServerSocketChannel) getJavaChannel()).configureBlocking(false); - System.out.println("Bound TCP socket at port: " + port); + LOGGER.info("Bound TCP socket at port: {}", port); } /** diff --git a/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/App.java b/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/App.java index fd5d28ed5..90f7d5e59 100644 --- a/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/App.java +++ b/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/App.java @@ -23,6 +23,9 @@ package com.iluwatar.reader.writer.lock; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; @@ -48,6 +51,8 @@ import java.util.stream.IntStream; */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point * @@ -71,7 +76,7 @@ public class App { try { executeService.awaitTermination(5, TimeUnit.SECONDS); } catch (InterruptedException e) { - System.out.println("Error waiting for ExecutorService shutdown"); + LOGGER.error("Error waiting for ExecutorService shutdown"); } } diff --git a/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/Reader.java b/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/Reader.java index 2b837b341..644772bf1 100644 --- a/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/Reader.java +++ b/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/Reader.java @@ -22,6 +22,9 @@ */ package com.iluwatar.reader.writer.lock; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.util.concurrent.locks.Lock; /** @@ -29,6 +32,8 @@ import java.util.concurrent.locks.Lock; */ public class Reader implements Runnable { + private static final Logger LOGGER = LoggerFactory.getLogger(Reader.class); + private Lock readLock; private String name; @@ -55,8 +60,8 @@ public class Reader implements Runnable { * */ public void read() throws InterruptedException { - System.out.println(name + " begin"); + LOGGER.info("{} begin", name); Thread.sleep(250); - System.out.println(name + " finish"); + LOGGER.info("{} finish", name); } } diff --git a/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/Writer.java b/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/Writer.java index fc3c3bb88..ce946f74f 100644 --- a/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/Writer.java +++ b/reader-writer-lock/src/main/java/com/iluwatar/reader/writer/lock/Writer.java @@ -22,6 +22,9 @@ */ package com.iluwatar.reader.writer.lock; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.util.concurrent.locks.Lock; /** @@ -29,6 +32,8 @@ import java.util.concurrent.locks.Lock; */ public class Writer implements Runnable { + private static final Logger LOGGER = LoggerFactory.getLogger(Writer.class); + private Lock writeLock; private String name; @@ -55,8 +60,8 @@ public class Writer implements Runnable { * Simulate the write operation */ public void write() throws InterruptedException { - System.out.println(name + " begin"); + LOGGER.info("{} begin", name); Thread.sleep(250); - System.out.println(name + " finish"); + LOGGER.info("{} finish", name); } } diff --git a/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/ReaderAndWriterTest.java b/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/ReaderAndWriterTest.java index a2496a3c0..dc8feb04f 100644 --- a/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/ReaderAndWriterTest.java +++ b/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/ReaderAndWriterTest.java @@ -31,13 +31,15 @@ import java.util.concurrent.TimeUnit; import org.junit.Test; import org.mockito.InOrder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * @author hongshuwei@gmail.com */ public class ReaderAndWriterTest extends StdOutTest { - + private static final Logger LOGGER = LoggerFactory.getLogger(ReaderAndWriterTest.class); /** * Verify reader and writer can only get the lock to read and write orderly @@ -60,7 +62,7 @@ public class ReaderAndWriterTest extends StdOutTest { try { executeService.awaitTermination(10, TimeUnit.SECONDS); } catch (InterruptedException e) { - System.out.println("Error waiting for ExecutorService shutdown"); + LOGGER.error("Error waiting for ExecutorService shutdown", e); } final InOrder inOrder = inOrder(getStdOutMock()); @@ -91,7 +93,7 @@ public class ReaderAndWriterTest extends StdOutTest { try { executeService.awaitTermination(10, TimeUnit.SECONDS); } catch (InterruptedException e) { - System.out.println("Error waiting for ExecutorService shutdown"); + LOGGER.error("Error waiting for ExecutorService shutdown", e); } final InOrder inOrder = inOrder(getStdOutMock()); diff --git a/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/ReaderTest.java b/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/ReaderTest.java index 7d51e977c..a51120bf8 100644 --- a/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/ReaderTest.java +++ b/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/ReaderTest.java @@ -31,12 +31,16 @@ import java.util.concurrent.TimeUnit; import org.junit.Test; import org.mockito.InOrder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * @author hongshuwei@gmail.com */ public class ReaderTest extends StdOutTest { + private static final Logger LOGGER = LoggerFactory.getLogger(ReaderTest.class); + /** * Verify that multiple readers can get the read lock concurrently */ @@ -57,7 +61,7 @@ public class ReaderTest extends StdOutTest { try { executeService.awaitTermination(10, TimeUnit.SECONDS); } catch (InterruptedException e) { - System.out.println("Error waiting for ExecutorService shutdown"); + LOGGER.error("Error waiting for ExecutorService shutdown", e); } // Read operation will hold the read lock 250 milliseconds, so here we prove that multiple reads diff --git a/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/WriterTest.java b/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/WriterTest.java index 765c491ff..729b5eff3 100644 --- a/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/WriterTest.java +++ b/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/WriterTest.java @@ -31,12 +31,16 @@ import java.util.concurrent.TimeUnit; import org.junit.Test; import org.mockito.InOrder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * @author hongshuwei@gmail.com */ public class WriterTest extends StdOutTest { + private static final Logger LOGGER = LoggerFactory.getLogger(WriterTest.class); + /** * Verify that multiple writers will get the lock in order. */ @@ -58,7 +62,7 @@ public class WriterTest extends StdOutTest { try { executeService.awaitTermination(10, TimeUnit.SECONDS); } catch (InterruptedException e) { - System.out.println("Error waiting for ExecutorService shutdown"); + LOGGER.error("Error waiting for ExecutorService shutdown", e); } // Write operation will hold the write lock 250 milliseconds, so here we verify that when two // writer execute concurrently, the second writer can only writes only when the first one is diff --git a/repository/src/main/java/com/iluwatar/repository/App.java b/repository/src/main/java/com/iluwatar/repository/App.java index 2807ae7ca..ab61852d2 100644 --- a/repository/src/main/java/com/iluwatar/repository/App.java +++ b/repository/src/main/java/com/iluwatar/repository/App.java @@ -24,6 +24,8 @@ package com.iluwatar.repository; import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; /** @@ -43,6 +45,8 @@ import org.springframework.context.support.ClassPathXmlApplicationContext; */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point * @@ -67,12 +71,12 @@ public class App { repository.save(terry); // Count Person records - System.out.println("Count Person records: " + repository.count()); + LOGGER.info("Count Person records: {}", repository.count()); // Print all records List persons = (List) repository.findAll(); for (Person person : persons) { - System.out.println(person); + LOGGER.info(person.toString()); } // Update Person @@ -80,24 +84,24 @@ public class App { nasta.setSurname("Spotakova"); repository.save(nasta); - System.out.println("Find by id 2: " + repository.findOne(2L)); + LOGGER.info("Find by id 2: {}", repository.findOne(2L)); // Remove record from Person repository.delete(2L); // count records - System.out.println("Count Person records: " + repository.count()); + LOGGER.info("Count Person records: {}", repository.count()); // find by name Person p = repository.findOne(new PersonSpecifications.NameEqualSpec("John")); - System.out.println("Find by John is " + p); + LOGGER.info("Find by John is {}", p); // find by age persons = repository.findAll(new PersonSpecifications.AgeBetweenSpec(20, 40)); - System.out.println("Find Person with age between 20,40: "); + LOGGER.info("Find Person with age between 20,40: "); for (Person person : persons) { - System.out.println(person); + LOGGER.info(person.toString()); } repository.deleteAll(); diff --git a/repository/src/main/java/com/iluwatar/repository/AppConfig.java b/repository/src/main/java/com/iluwatar/repository/AppConfig.java index 3e7093358..09f6753bb 100644 --- a/repository/src/main/java/com/iluwatar/repository/AppConfig.java +++ b/repository/src/main/java/com/iluwatar/repository/AppConfig.java @@ -30,6 +30,8 @@ import javax.sql.DataSource; import org.apache.commons.dbcp.BasicDataSource; import org.hibernate.jpa.HibernatePersistenceProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; @@ -44,6 +46,8 @@ import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; @EnableJpaRepositories public class AppConfig { + private static final Logger LOGGER = LoggerFactory.getLogger(AppConfig.class); + /** * Creation of H2 db * @@ -117,12 +121,12 @@ public class AppConfig { repository.save(terry); // Count Person records - System.out.println("Count Person records: " + repository.count()); + LOGGER.info("Count Person records: {}", repository.count()); // Print all records List persons = (List) repository.findAll(); for (Person person : persons) { - System.out.println(person); + LOGGER.info(person.toString()); } // Update Person @@ -130,24 +134,24 @@ public class AppConfig { nasta.setSurname("Spotakova"); repository.save(nasta); - System.out.println("Find by id 2: " + repository.findOne(2L)); + LOGGER.info("Find by id 2: {}", repository.findOne(2L)); // Remove record from Person repository.delete(2L); // count records - System.out.println("Count Person records: " + repository.count()); + LOGGER.info("Count Person records: {}", repository.count()); // find by name Person p = repository.findOne(new PersonSpecifications.NameEqualSpec("John")); - System.out.println("Find by John is " + p); + LOGGER.info("Find by John is {}", p); // find by age persons = repository.findAll(new PersonSpecifications.AgeBetweenSpec(20, 40)); - System.out.println("Find Person with age between 20,40: "); + LOGGER.info("Find Person with age between 20,40: "); for (Person person : persons) { - System.out.println(person); + LOGGER.info(person.toString()); } context.close(); diff --git a/resource-acquisition-is-initialization/src/main/java/com/iluwatar/resource/acquisition/is/initialization/App.java b/resource-acquisition-is-initialization/src/main/java/com/iluwatar/resource/acquisition/is/initialization/App.java index 413fb0eab..bb722a36d 100644 --- a/resource-acquisition-is-initialization/src/main/java/com/iluwatar/resource/acquisition/is/initialization/App.java +++ b/resource-acquisition-is-initialization/src/main/java/com/iluwatar/resource/acquisition/is/initialization/App.java @@ -22,6 +22,9 @@ */ package com.iluwatar.resource.acquisition.is.initialization; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * Resource Acquisition Is Initialization pattern was developed for exception safe resource @@ -44,17 +47,19 @@ package com.iluwatar.resource.acquisition.is.initialization; */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point */ public static void main(String[] args) throws Exception { try (SlidingDoor slidingDoor = new SlidingDoor()) { - System.out.println("Walking in."); + LOGGER.info("Walking in."); } try (TreasureChest treasureChest = new TreasureChest()) { - System.out.println("Looting contents."); + LOGGER.info("Looting contents."); } } } diff --git a/resource-acquisition-is-initialization/src/main/java/com/iluwatar/resource/acquisition/is/initialization/SlidingDoor.java b/resource-acquisition-is-initialization/src/main/java/com/iluwatar/resource/acquisition/is/initialization/SlidingDoor.java index 3a1a35f2d..ac8512d15 100644 --- a/resource-acquisition-is-initialization/src/main/java/com/iluwatar/resource/acquisition/is/initialization/SlidingDoor.java +++ b/resource-acquisition-is-initialization/src/main/java/com/iluwatar/resource/acquisition/is/initialization/SlidingDoor.java @@ -22,6 +22,9 @@ */ package com.iluwatar.resource.acquisition.is.initialization; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * SlidingDoor resource @@ -29,12 +32,14 @@ package com.iluwatar.resource.acquisition.is.initialization; */ public class SlidingDoor implements AutoCloseable { + private static final Logger LOGGER = LoggerFactory.getLogger(SlidingDoor.class); + public SlidingDoor() { - System.out.println("Sliding door opens."); + LOGGER.info("Sliding door opens."); } @Override public void close() throws Exception { - System.out.println("Sliding door closes."); + LOGGER.info("Sliding door closes."); } } diff --git a/resource-acquisition-is-initialization/src/main/java/com/iluwatar/resource/acquisition/is/initialization/TreasureChest.java b/resource-acquisition-is-initialization/src/main/java/com/iluwatar/resource/acquisition/is/initialization/TreasureChest.java index e7b7ebab6..f020b5fa3 100644 --- a/resource-acquisition-is-initialization/src/main/java/com/iluwatar/resource/acquisition/is/initialization/TreasureChest.java +++ b/resource-acquisition-is-initialization/src/main/java/com/iluwatar/resource/acquisition/is/initialization/TreasureChest.java @@ -22,6 +22,9 @@ */ package com.iluwatar.resource.acquisition.is.initialization; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.io.Closeable; import java.io.IOException; @@ -32,12 +35,14 @@ import java.io.IOException; */ public class TreasureChest implements Closeable { + private static final Logger LOGGER = LoggerFactory.getLogger(TreasureChest.class); + public TreasureChest() { - System.out.println("Treasure chest opens."); + LOGGER.info("Treasure chest opens."); } @Override public void close() throws IOException { - System.out.println("Treasure chest closes."); + LOGGER.info("Treasure chest closes."); } } diff --git a/semaphore/src/main/java/com/iluwatar/semaphore/Customer.java b/semaphore/src/main/java/com/iluwatar/semaphore/Customer.java index 0a4713438..e0546edbe 100644 --- a/semaphore/src/main/java/com/iluwatar/semaphore/Customer.java +++ b/semaphore/src/main/java/com/iluwatar/semaphore/Customer.java @@ -22,12 +22,17 @@ */ package com.iluwatar.semaphore; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * A Customer attempts to repeatedly take Fruit from the FruitShop by * taking Fruit from FruitBowl instances. */ public class Customer extends Thread { + private static final Logger LOGGER = LoggerFactory.getLogger(Customer.class); + /** * Name of the Customer. */ @@ -63,13 +68,13 @@ public class Customer extends Thread { Fruit fruit; if (bowl != null && (fruit = bowl.take()) != null) { - System.out.println(name + " took an " + fruit); + LOGGER.info("{} took an {}", name, fruit); fruitBowl.put(fruit); fruitShop.returnBowl(bowl); } } - - System.out.println(name + " took " + fruitBowl); + + LOGGER.info("{} took {}", name, fruitBowl); } diff --git a/servant/src/main/java/com/iluwatar/servant/App.java b/servant/src/main/java/com/iluwatar/servant/App.java index 92829441d..aeb379846 100644 --- a/servant/src/main/java/com/iluwatar/servant/App.java +++ b/servant/src/main/java/com/iluwatar/servant/App.java @@ -22,6 +22,9 @@ */ package com.iluwatar.servant; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.util.ArrayList; @@ -35,6 +38,8 @@ import java.util.ArrayList; */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + static Servant jenkins = new Servant("Jenkins"); static Servant travis = new Servant("Travis"); @@ -73,9 +78,9 @@ public class App { // check your luck if (servant.checkIfYouWillBeHanged(guests)) { - System.out.println(servant.name + " will live another day"); + LOGGER.info("{} will live another day", servant.name); } else { - System.out.println("Poor " + servant.name + ". His days are numbered"); + LOGGER.info("Poor {}. His days are numbered", servant.name); } } } diff --git a/service-layer/src/main/java/com/iluwatar/servicelayer/app/App.java b/service-layer/src/main/java/com/iluwatar/servicelayer/app/App.java index 8282d800c..bf15c5885 100644 --- a/service-layer/src/main/java/com/iluwatar/servicelayer/app/App.java +++ b/service-layer/src/main/java/com/iluwatar/servicelayer/app/App.java @@ -35,6 +35,8 @@ import com.iluwatar.servicelayer.spellbook.SpellbookDaoImpl; import com.iluwatar.servicelayer.wizard.Wizard; import com.iluwatar.servicelayer.wizard.WizardDao; import com.iluwatar.servicelayer.wizard.WizardDaoImpl; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** @@ -57,6 +59,8 @@ import com.iluwatar.servicelayer.wizard.WizardDaoImpl; */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point * @@ -180,27 +184,27 @@ public class App { public static void queryData() { MagicService service = new MagicServiceImpl(new WizardDaoImpl(), new SpellbookDaoImpl(), new SpellDaoImpl()); - System.out.println("Enumerating all wizards"); + LOGGER.info("Enumerating all wizards"); for (Wizard w : service.findAllWizards()) { - System.out.println(w.getName()); + LOGGER.info(w.getName()); } - System.out.println("Enumerating all spellbooks"); + LOGGER.info("Enumerating all spellbooks"); for (Spellbook s : service.findAllSpellbooks()) { - System.out.println(s.getName()); + LOGGER.info(s.getName()); } - System.out.println("Enumerating all spells"); + LOGGER.info("Enumerating all spells"); for (Spell s : service.findAllSpells()) { - System.out.println(s.getName()); + LOGGER.info(s.getName()); } - System.out.println("Find wizards with spellbook 'Book of Idores'"); + LOGGER.info("Find wizards with spellbook 'Book of Idores'"); List wizardsWithSpellbook = service.findWizardsWithSpellbook("Book of Idores"); for (Wizard w : wizardsWithSpellbook) { - System.out.println(String.format("%s has 'Book of Idores'", w.getName())); + LOGGER.info("{} has 'Book of Idores'", w.getName()); } - System.out.println("Find wizards with spell 'Fireball'"); + LOGGER.info("Find wizards with spell 'Fireball'"); List wizardsWithSpell = service.findWizardsWithSpell("Fireball"); for (Wizard w : wizardsWithSpell) { - System.out.println(String.format("%s has 'Fireball'", w.getName())); + LOGGER.info("{} has 'Fireball'", w.getName()); } } } diff --git a/service-layer/src/main/java/com/iluwatar/servicelayer/hibernate/HibernateUtil.java b/service-layer/src/main/java/com/iluwatar/servicelayer/hibernate/HibernateUtil.java index b30b97b65..eead0e197 100644 --- a/service-layer/src/main/java/com/iluwatar/servicelayer/hibernate/HibernateUtil.java +++ b/service-layer/src/main/java/com/iluwatar/servicelayer/hibernate/HibernateUtil.java @@ -28,12 +28,16 @@ import com.iluwatar.servicelayer.wizard.Wizard; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Produces the Hibernate {@link SessionFactory}. */ public final class HibernateUtil { + private static final Logger LOGGER = LoggerFactory.getLogger(HibernateUtil.class); + /** * The cached session factory */ @@ -59,7 +63,7 @@ public final class HibernateUtil { .setProperty("hibernate.show_sql", "true") .setProperty("hibernate.hbm2ddl.auto", "create-drop").buildSessionFactory(); } catch (Throwable ex) { - System.err.println("Initial SessionFactory creation failed." + ex); + LOGGER.error("Initial SessionFactory creation failed.", ex); throw new ExceptionInInitializerError(ex); } } diff --git a/service-locator/src/main/java/com/iluwatar/servicelocator/InitContext.java b/service-locator/src/main/java/com/iluwatar/servicelocator/InitContext.java index 8063fc818..134eb6d89 100644 --- a/service-locator/src/main/java/com/iluwatar/servicelocator/InitContext.java +++ b/service-locator/src/main/java/com/iluwatar/servicelocator/InitContext.java @@ -22,6 +22,9 @@ */ package com.iluwatar.servicelocator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * For JNDI lookup of services from the web.xml. Will match name of the service name that is being * requested and return a newly created service object with the name @@ -30,6 +33,8 @@ package com.iluwatar.servicelocator; */ public class InitContext { + private static final Logger LOGGER = LoggerFactory.getLogger(InitContext.class); + /** * Perform the lookup based on the service name. The returned object will need to be casted into a * {@link Service} @@ -39,10 +44,10 @@ public class InitContext { */ public Object lookup(String serviceName) { if (serviceName.equals("jndi/serviceA")) { - System.out.println("Looking up service A and creating new service for A"); + LOGGER.info("Looking up service A and creating new service for A"); return new ServiceImpl("jndi/serviceA"); } else if (serviceName.equals("jndi/serviceB")) { - System.out.println("Looking up service B and creating new service for B"); + LOGGER.info("Looking up service B and creating new service for B"); return new ServiceImpl("jndi/serviceB"); } else { return null; diff --git a/service-locator/src/main/java/com/iluwatar/servicelocator/ServiceCache.java b/service-locator/src/main/java/com/iluwatar/servicelocator/ServiceCache.java index 7e2169fcb..89b2a6638 100644 --- a/service-locator/src/main/java/com/iluwatar/servicelocator/ServiceCache.java +++ b/service-locator/src/main/java/com/iluwatar/servicelocator/ServiceCache.java @@ -22,6 +22,9 @@ */ package com.iluwatar.servicelocator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.util.HashMap; import java.util.Map; @@ -35,6 +38,8 @@ import java.util.Map; */ public class ServiceCache { + private static final Logger LOGGER = LoggerFactory.getLogger(ServiceCache.class); + private final Map serviceCache; public ServiceCache() { @@ -52,8 +57,8 @@ public class ServiceCache { for (String serviceJndiName : serviceCache.keySet()) { if (serviceJndiName.equals(serviceName)) { cachedService = serviceCache.get(serviceJndiName); - System.out.println("(cache call) Fetched service " + cachedService.getName() + "(" - + cachedService.getId() + ") from cache... !"); + LOGGER.info("(cache call) Fetched service {}({}) from cache... !", + cachedService.getName(), cachedService.getId()); } } return cachedService; diff --git a/service-locator/src/main/java/com/iluwatar/servicelocator/ServiceImpl.java b/service-locator/src/main/java/com/iluwatar/servicelocator/ServiceImpl.java index 543fb8480..328926ce2 100644 --- a/service-locator/src/main/java/com/iluwatar/servicelocator/ServiceImpl.java +++ b/service-locator/src/main/java/com/iluwatar/servicelocator/ServiceImpl.java @@ -22,6 +22,9 @@ */ package com.iluwatar.servicelocator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * This is a single service implementation of a sample service. This is the actual service that will * process the request. The reference for this service is to be looked upon in the JNDI server that @@ -31,6 +34,8 @@ package com.iluwatar.servicelocator; */ public class ServiceImpl implements Service { + private static final Logger LOGGER = LoggerFactory.getLogger(ServiceImpl.class); + private final String serviceName; private final int id; @@ -57,6 +62,6 @@ public class ServiceImpl implements Service { @Override public void execute() { - System.out.println("Service " + getName() + " is now executing with id " + getId()); + LOGGER.info("Service {} is now executing with id {}", getName(), getId()); } } diff --git a/singleton/src/main/java/com/iluwatar/singleton/App.java b/singleton/src/main/java/com/iluwatar/singleton/App.java index 4b505085a..31dcd1803 100644 --- a/singleton/src/main/java/com/iluwatar/singleton/App.java +++ b/singleton/src/main/java/com/iluwatar/singleton/App.java @@ -22,6 +22,9 @@ */ package com.iluwatar.singleton; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * Singleton pattern ensures that the class can have only one existing instance per Java classloader * instance and provides global access to it. @@ -60,6 +63,8 @@ package com.iluwatar.singleton; */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point. * @@ -70,35 +75,35 @@ public class App { // eagerly initialized singleton IvoryTower ivoryTower1 = IvoryTower.getInstance(); IvoryTower ivoryTower2 = IvoryTower.getInstance(); - System.out.println("ivoryTower1=" + ivoryTower1); - System.out.println("ivoryTower2=" + ivoryTower2); + LOGGER.info("ivoryTower1={}", ivoryTower1); + LOGGER.info("ivoryTower2={}", ivoryTower2); // lazily initialized singleton ThreadSafeLazyLoadedIvoryTower threadSafeIvoryTower1 = ThreadSafeLazyLoadedIvoryTower.getInstance(); ThreadSafeLazyLoadedIvoryTower threadSafeIvoryTower2 = ThreadSafeLazyLoadedIvoryTower.getInstance(); - System.out.println("threadSafeIvoryTower1=" + threadSafeIvoryTower1); - System.out.println("threadSafeIvoryTower2=" + threadSafeIvoryTower2); + LOGGER.info("threadSafeIvoryTower1={}", threadSafeIvoryTower1); + LOGGER.info("threadSafeIvoryTower2={}", threadSafeIvoryTower2); // enum singleton EnumIvoryTower enumIvoryTower1 = EnumIvoryTower.INSTANCE; EnumIvoryTower enumIvoryTower2 = EnumIvoryTower.INSTANCE; - System.out.println("enumIvoryTower1=" + enumIvoryTower1); - System.out.println("enumIvoryTower2=" + enumIvoryTower2); + LOGGER.info("enumIvoryTower1={}", enumIvoryTower1); + LOGGER.info("enumIvoryTower2={}", enumIvoryTower2); // double checked locking ThreadSafeDoubleCheckLocking dcl1 = ThreadSafeDoubleCheckLocking.getInstance(); - System.out.println(dcl1); + LOGGER.info(dcl1.toString()); ThreadSafeDoubleCheckLocking dcl2 = ThreadSafeDoubleCheckLocking.getInstance(); - System.out.println(dcl2); + LOGGER.info(dcl2.toString()); // initialize on demand holder idiom InitializingOnDemandHolderIdiom demandHolderIdiom = InitializingOnDemandHolderIdiom.getInstance(); - System.out.println(demandHolderIdiom); + LOGGER.info(demandHolderIdiom.toString()); InitializingOnDemandHolderIdiom demandHolderIdiom2 = InitializingOnDemandHolderIdiom.getInstance(); - System.out.println(demandHolderIdiom2); + LOGGER.info(demandHolderIdiom2.toString()); } } diff --git a/specification/src/main/java/com/iluwatar/specification/app/App.java b/specification/src/main/java/com/iluwatar/specification/app/App.java index 7cbd38470..7e85d2713 100644 --- a/specification/src/main/java/com/iluwatar/specification/app/App.java +++ b/specification/src/main/java/com/iluwatar/specification/app/App.java @@ -37,6 +37,8 @@ import com.iluwatar.specification.property.Color; import com.iluwatar.specification.property.Movement; import com.iluwatar.specification.selector.ColorSelector; import com.iluwatar.specification.selector.MovementSelector; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * @@ -52,6 +54,8 @@ import com.iluwatar.specification.selector.MovementSelector; * */ public class App { + + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); /** * Program entry point @@ -62,22 +66,22 @@ public class App { Arrays.asList(new Goblin(), new Octopus(), new Dragon(), new Shark(), new Troll(), new KillerBee()); // find all walking creatures - System.out.println("Find all walking creatures"); + LOGGER.info("Find all walking creatures"); List walkingCreatures = creatures.stream().filter(new MovementSelector(Movement.WALKING)) .collect(Collectors.toList()); - walkingCreatures.stream().forEach(System.out::println); + walkingCreatures.stream().forEach(c -> LOGGER.info(c.toString())); // find all dark creatures - System.out.println("Find all dark creatures"); + LOGGER.info("Find all dark creatures"); List darkCreatures = creatures.stream().filter(new ColorSelector(Color.DARK)).collect(Collectors.toList()); - darkCreatures.stream().forEach(System.out::println); + darkCreatures.stream().forEach(c -> LOGGER.info(c.toString())); // find all red and flying creatures - System.out.println("Find all red and flying creatures"); + LOGGER.info("Find all red and flying creatures"); List redAndFlyingCreatures = creatures.stream() .filter(new ColorSelector(Color.RED).and(new MovementSelector(Movement.FLYING))) .collect(Collectors.toList()); - redAndFlyingCreatures.stream().forEach(System.out::println); + redAndFlyingCreatures.stream().forEach(c -> LOGGER.info(c.toString())); } } diff --git a/state/src/main/java/com/iluwatar/state/AngryState.java b/state/src/main/java/com/iluwatar/state/AngryState.java index c58f85ae1..3ebbed142 100644 --- a/state/src/main/java/com/iluwatar/state/AngryState.java +++ b/state/src/main/java/com/iluwatar/state/AngryState.java @@ -22,6 +22,9 @@ */ package com.iluwatar.state; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * Angry state. @@ -29,6 +32,8 @@ package com.iluwatar.state; */ public class AngryState implements State { + private static final Logger LOGGER = LoggerFactory.getLogger(AngryState.class); + private Mammoth mammoth; public AngryState(Mammoth mammoth) { @@ -37,12 +42,12 @@ public class AngryState implements State { @Override public void observe() { - System.out.println(String.format("%s is furious!", mammoth)); + LOGGER.info("{} is furious!", mammoth); } @Override public void onEnterState() { - System.out.println(String.format("%s gets angry!", mammoth)); + LOGGER.info("{} gets angry!", mammoth); } } diff --git a/state/src/main/java/com/iluwatar/state/PeacefulState.java b/state/src/main/java/com/iluwatar/state/PeacefulState.java index 23f4e893c..870298632 100644 --- a/state/src/main/java/com/iluwatar/state/PeacefulState.java +++ b/state/src/main/java/com/iluwatar/state/PeacefulState.java @@ -22,6 +22,9 @@ */ package com.iluwatar.state; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * Peaceful state. @@ -29,6 +32,8 @@ package com.iluwatar.state; */ public class PeacefulState implements State { + private static final Logger LOGGER = LoggerFactory.getLogger(PeacefulState.class); + private Mammoth mammoth; public PeacefulState(Mammoth mammoth) { @@ -37,12 +42,12 @@ public class PeacefulState implements State { @Override public void observe() { - System.out.println(String.format("%s is calm and peaceful.", mammoth)); + LOGGER.info("{} is calm and peaceful.", mammoth); } @Override public void onEnterState() { - System.out.println(String.format("%s calms down.", mammoth)); + LOGGER.info("{} calms down.", mammoth); } } diff --git a/step-builder/src/main/java/com/iluwatar/stepbuilder/App.java b/step-builder/src/main/java/com/iluwatar/stepbuilder/App.java index aeb759ba8..fe5c5a8cd 100644 --- a/step-builder/src/main/java/com/iluwatar/stepbuilder/App.java +++ b/step-builder/src/main/java/com/iluwatar/stepbuilder/App.java @@ -22,6 +22,9 @@ */ package com.iluwatar.stepbuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * Step Builder Pattern * @@ -56,6 +59,8 @@ package com.iluwatar.stepbuilder; */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point * @@ -67,18 +72,18 @@ public class App { CharacterStepBuilder.newBuilder().name("Amberjill").fighterClass("Paladin") .withWeapon("Sword").noAbilities().build(); - System.out.println(warrior); + LOGGER.info(warrior.toString()); Character mage = CharacterStepBuilder.newBuilder().name("Riobard").wizardClass("Sorcerer") .withSpell("Fireball").withAbility("Fire Aura").withAbility("Teleport") .noMoreAbilities().build(); - System.out.println(mage); + LOGGER.info(mage.toString()); Character thief = CharacterStepBuilder.newBuilder().name("Desmond").fighterClass("Rogue").noWeapon().build(); - System.out.println(thief); + LOGGER.info(thief.toString()); } } diff --git a/strategy/src/main/java/com/iluwatar/strategy/App.java b/strategy/src/main/java/com/iluwatar/strategy/App.java index be8826fe3..28485701c 100644 --- a/strategy/src/main/java/com/iluwatar/strategy/App.java +++ b/strategy/src/main/java/com/iluwatar/strategy/App.java @@ -22,6 +22,9 @@ */ package com.iluwatar.strategy; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * The Strategy pattern (also known as the policy pattern) is a software design pattern that enables @@ -37,6 +40,8 @@ package com.iluwatar.strategy; */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point * @@ -44,27 +49,27 @@ public class App { */ public static void main(String[] args) { // GoF Strategy pattern - System.out.println("Green dragon spotted ahead!"); + LOGGER.info("Green dragon spotted ahead!"); DragonSlayer dragonSlayer = new DragonSlayer(new MeleeStrategy()); dragonSlayer.goToBattle(); - System.out.println("Red dragon emerges."); + LOGGER.info("Red dragon emerges."); dragonSlayer.changeStrategy(new ProjectileStrategy()); dragonSlayer.goToBattle(); - System.out.println("Black dragon lands before you."); + LOGGER.info("Black dragon lands before you."); dragonSlayer.changeStrategy(new SpellStrategy()); dragonSlayer.goToBattle(); // Java 8 Strategy pattern - System.out.println("Green dragon spotted ahead!"); + LOGGER.info("Green dragon spotted ahead!"); dragonSlayer = new DragonSlayer( - () -> System.out.println("With your Excalibur you severe the dragon's head!")); + () -> LOGGER.info("With your Excalibur you severe the dragon's head!")); dragonSlayer.goToBattle(); - System.out.println("Red dragon emerges."); - dragonSlayer.changeStrategy(() -> System.out.println( + LOGGER.info("Red dragon emerges."); + dragonSlayer.changeStrategy(() -> LOGGER.info( "You shoot the dragon with the magical crossbow and it falls dead on the ground!")); dragonSlayer.goToBattle(); - System.out.println("Black dragon lands before you."); - dragonSlayer.changeStrategy(() -> System.out.println( + LOGGER.info("Black dragon lands before you."); + dragonSlayer.changeStrategy(() -> LOGGER.info( "You cast the spell of disintegration and the dragon vaporizes in a pile of dust!")); dragonSlayer.goToBattle(); } diff --git a/strategy/src/main/java/com/iluwatar/strategy/MeleeStrategy.java b/strategy/src/main/java/com/iluwatar/strategy/MeleeStrategy.java index d17ff9041..d67f8b559 100644 --- a/strategy/src/main/java/com/iluwatar/strategy/MeleeStrategy.java +++ b/strategy/src/main/java/com/iluwatar/strategy/MeleeStrategy.java @@ -22,6 +22,9 @@ */ package com.iluwatar.strategy; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * Melee strategy. @@ -29,8 +32,10 @@ package com.iluwatar.strategy; */ public class MeleeStrategy implements DragonSlayingStrategy { + private static final Logger LOGGER = LoggerFactory.getLogger(MeleeStrategy.class); + @Override public void execute() { - System.out.println("With your Excalibur you sever the dragon's head!"); + LOGGER.info("With your Excalibur you sever the dragon's head!"); } } diff --git a/strategy/src/main/java/com/iluwatar/strategy/ProjectileStrategy.java b/strategy/src/main/java/com/iluwatar/strategy/ProjectileStrategy.java index 7cd731167..ea88fdc8b 100644 --- a/strategy/src/main/java/com/iluwatar/strategy/ProjectileStrategy.java +++ b/strategy/src/main/java/com/iluwatar/strategy/ProjectileStrategy.java @@ -22,6 +22,9 @@ */ package com.iluwatar.strategy; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * Projectile strategy. @@ -29,9 +32,10 @@ package com.iluwatar.strategy; */ public class ProjectileStrategy implements DragonSlayingStrategy { + private static final Logger LOGGER = LoggerFactory.getLogger(ProjectileStrategy.class); + @Override public void execute() { - System.out - .println("You shoot the dragon with the magical crossbow and it falls dead on the ground!"); + LOGGER.info("You shoot the dragon with the magical crossbow and it falls dead on the ground!"); } } diff --git a/strategy/src/main/java/com/iluwatar/strategy/SpellStrategy.java b/strategy/src/main/java/com/iluwatar/strategy/SpellStrategy.java index 6309ed31b..3264799bf 100644 --- a/strategy/src/main/java/com/iluwatar/strategy/SpellStrategy.java +++ b/strategy/src/main/java/com/iluwatar/strategy/SpellStrategy.java @@ -22,6 +22,9 @@ */ package com.iluwatar.strategy; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * Spell strategy. @@ -29,10 +32,11 @@ package com.iluwatar.strategy; */ public class SpellStrategy implements DragonSlayingStrategy { + private static final Logger LOGGER = LoggerFactory.getLogger(SpellStrategy.class); + @Override public void execute() { - System.out - .println("You cast the spell of disintegration and the dragon vaporizes in a pile of dust!"); + LOGGER.info("You cast the spell of disintegration and the dragon vaporizes in a pile of dust!"); } } diff --git a/template-method/src/main/java/com/iluwatar/templatemethod/HitAndRunMethod.java b/template-method/src/main/java/com/iluwatar/templatemethod/HitAndRunMethod.java index 7a78576a1..49cbbd7dc 100644 --- a/template-method/src/main/java/com/iluwatar/templatemethod/HitAndRunMethod.java +++ b/template-method/src/main/java/com/iluwatar/templatemethod/HitAndRunMethod.java @@ -22,6 +22,9 @@ */ package com.iluwatar.templatemethod; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * HitAndRunMethod implementation of {@link StealingMethod}. @@ -29,6 +32,8 @@ package com.iluwatar.templatemethod; */ public class HitAndRunMethod extends StealingMethod { + private static final Logger LOGGER = LoggerFactory.getLogger(HitAndRunMethod.class); + @Override protected String pickTarget() { return "old goblin woman"; @@ -36,11 +41,11 @@ public class HitAndRunMethod extends StealingMethod { @Override protected void confuseTarget(String target) { - System.out.println("Approach the " + target + " from behind."); + LOGGER.info("Approach the {} from behind.", target); } @Override protected void stealTheItem(String target) { - System.out.println("Grab the handbag and run away fast!"); + LOGGER.info("Grab the handbag and run away fast!"); } } diff --git a/template-method/src/main/java/com/iluwatar/templatemethod/StealingMethod.java b/template-method/src/main/java/com/iluwatar/templatemethod/StealingMethod.java index c8c584cdd..85896d922 100644 --- a/template-method/src/main/java/com/iluwatar/templatemethod/StealingMethod.java +++ b/template-method/src/main/java/com/iluwatar/templatemethod/StealingMethod.java @@ -22,6 +22,9 @@ */ package com.iluwatar.templatemethod; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * StealingMethod defines skeleton for the algorithm. @@ -29,6 +32,8 @@ package com.iluwatar.templatemethod; */ public abstract class StealingMethod { + private static final Logger LOGGER = LoggerFactory.getLogger(StealingMethod.class); + protected abstract String pickTarget(); protected abstract void confuseTarget(String target); @@ -40,7 +45,7 @@ public abstract class StealingMethod { */ public void steal() { String target = pickTarget(); - System.out.println("The target has been chosen as " + target + "."); + LOGGER.info("The target has been chosen as {}.", target); confuseTarget(target); stealTheItem(target); } diff --git a/template-method/src/main/java/com/iluwatar/templatemethod/SubtleMethod.java b/template-method/src/main/java/com/iluwatar/templatemethod/SubtleMethod.java index 4fdb5d758..c7855fe4e 100644 --- a/template-method/src/main/java/com/iluwatar/templatemethod/SubtleMethod.java +++ b/template-method/src/main/java/com/iluwatar/templatemethod/SubtleMethod.java @@ -22,6 +22,9 @@ */ package com.iluwatar.templatemethod; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * SubtleMethod implementation of {@link StealingMethod}. @@ -29,6 +32,8 @@ package com.iluwatar.templatemethod; */ public class SubtleMethod extends StealingMethod { + private static final Logger LOGGER = LoggerFactory.getLogger(SubtleMethod.class); + @Override protected String pickTarget() { return "shop keeper"; @@ -36,11 +41,11 @@ public class SubtleMethod extends StealingMethod { @Override protected void confuseTarget(String target) { - System.out.println("Approach the " + target + " with tears running and hug him!"); + LOGGER.info("Approach the {} with tears running and hug him!", target); } @Override protected void stealTheItem(String target) { - System.out.println("While in close contact grab the " + target + "'s wallet."); + LOGGER.info("While in close contact grab the {}'s wallet.", target); } } diff --git a/thread-pool/src/main/java/com/iluwatar/threadpool/App.java b/thread-pool/src/main/java/com/iluwatar/threadpool/App.java index 16fbca35a..20d773c82 100644 --- a/thread-pool/src/main/java/com/iluwatar/threadpool/App.java +++ b/thread-pool/src/main/java/com/iluwatar/threadpool/App.java @@ -22,6 +22,9 @@ */ package com.iluwatar.threadpool; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutorService; @@ -43,6 +46,8 @@ import java.util.concurrent.Executors; * */ public class App { + + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); /** * Program entry point @@ -51,7 +56,7 @@ public class App { */ public static void main(String[] args) { - System.out.println("Program started"); + LOGGER.info("Program started"); // Create a list of tasks to be executed List tasks = new ArrayList<>(); @@ -89,6 +94,6 @@ public class App { while (!executor.isTerminated()) { Thread.yield(); } - System.out.println("Program finished"); + LOGGER.info("Program finished"); } } diff --git a/thread-pool/src/main/java/com/iluwatar/threadpool/Worker.java b/thread-pool/src/main/java/com/iluwatar/threadpool/Worker.java index 1354cab41..1740b289e 100644 --- a/thread-pool/src/main/java/com/iluwatar/threadpool/Worker.java +++ b/thread-pool/src/main/java/com/iluwatar/threadpool/Worker.java @@ -22,6 +22,9 @@ */ package com.iluwatar.threadpool; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * Worker implements {@link Runnable} and thus can be executed by {@link ExecutorService} @@ -29,6 +32,8 @@ package com.iluwatar.threadpool; */ public class Worker implements Runnable { + private static final Logger LOGGER = LoggerFactory.getLogger(Worker.class); + private final Task task; public Worker(final Task task) { @@ -37,8 +42,7 @@ public class Worker implements Runnable { @Override public void run() { - System.out.println(String.format("%s processing %s", Thread.currentThread().getName(), - task.toString())); + LOGGER.info("{} processing {}", Thread.currentThread().getName(), task.toString()); try { Thread.sleep(task.getTimeMs()); } catch (InterruptedException e) { diff --git a/tolerant-reader/src/main/java/com/iluwatar/tolerantreader/App.java b/tolerant-reader/src/main/java/com/iluwatar/tolerantreader/App.java index 066b6e737..14ebcab40 100644 --- a/tolerant-reader/src/main/java/com/iluwatar/tolerantreader/App.java +++ b/tolerant-reader/src/main/java/com/iluwatar/tolerantreader/App.java @@ -22,6 +22,9 @@ */ package com.iluwatar.tolerantreader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.io.IOException; /** @@ -41,31 +44,33 @@ import java.io.IOException; */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point */ public static void main(String[] args) throws IOException, ClassNotFoundException { // Write V1 RainbowFish fishV1 = new RainbowFish("Zed", 10, 11, 12); - System.out.println(String.format("fishV1 name=%s age=%d length=%d weight=%d", fishV1.getName(), - fishV1.getAge(), fishV1.getLengthMeters(), fishV1.getWeightTons())); + LOGGER.info("fishV1 name={} age={} length={} weight={}", fishV1.getName(), + fishV1.getAge(), fishV1.getLengthMeters(), fishV1.getWeightTons()); RainbowFishSerializer.writeV1(fishV1, "fish1.out"); // Read V1 RainbowFish deserializedFishV1 = RainbowFishSerializer.readV1("fish1.out"); - System.out.println(String.format("deserializedFishV1 name=%s age=%d length=%d weight=%d", + LOGGER.info("deserializedFishV1 name={} age={} length={} weight={}", deserializedFishV1.getName(), deserializedFishV1.getAge(), - deserializedFishV1.getLengthMeters(), deserializedFishV1.getWeightTons())); + deserializedFishV1.getLengthMeters(), deserializedFishV1.getWeightTons()); // Write V2 RainbowFishV2 fishV2 = new RainbowFishV2("Scar", 5, 12, 15, true, true, true); - System.out.println(String.format( - "fishV2 name=%s age=%d length=%d weight=%d sleeping=%b hungry=%b angry=%b", + LOGGER.info( + "fishV2 name={} age={} length={} weight={} sleeping={} hungry={} angry={}", fishV2.getName(), fishV2.getAge(), fishV2.getLengthMeters(), fishV2.getWeightTons(), - fishV2.getHungry(), fishV2.getAngry(), fishV2.getSleeping())); + fishV2.getHungry(), fishV2.getAngry(), fishV2.getSleeping()); RainbowFishSerializer.writeV2(fishV2, "fish2.out"); // Read V2 with V1 method RainbowFish deserializedFishV2 = RainbowFishSerializer.readV1("fish2.out"); - System.out.println(String.format("deserializedFishV2 name=%s age=%d length=%d weight=%d", + LOGGER.info("deserializedFishV2 name={} age={} length={} weight={}", deserializedFishV2.getName(), deserializedFishV2.getAge(), - deserializedFishV2.getLengthMeters(), deserializedFishV2.getWeightTons())); + deserializedFishV2.getLengthMeters(), deserializedFishV2.getWeightTons()); } } diff --git a/twin/src/main/java/com/iluwatar/twin/BallItem.java b/twin/src/main/java/com/iluwatar/twin/BallItem.java index 0188b5731..0c47bc91c 100644 --- a/twin/src/main/java/com/iluwatar/twin/BallItem.java +++ b/twin/src/main/java/com/iluwatar/twin/BallItem.java @@ -23,6 +23,9 @@ package com.iluwatar.twin; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * This class represents a Ball which extends {@link GameItem} and implements the logic for ball * item, like move and draw. It hold a reference of {@link BallThread} to delegate the suspend and @@ -30,6 +33,8 @@ package com.iluwatar.twin; */ public class BallItem extends GameItem { + private static final Logger LOGGER = LoggerFactory.getLogger(BallItem.class); + private boolean isSuspended; private BallThread twin; @@ -41,11 +46,11 @@ public class BallItem extends GameItem { @Override public void doDraw() { - System.out.println("doDraw"); + LOGGER.info("doDraw"); } public void move() { - System.out.println("move"); + LOGGER.info("move"); } @Override diff --git a/twin/src/main/java/com/iluwatar/twin/BallThread.java b/twin/src/main/java/com/iluwatar/twin/BallThread.java index 194d85b06..6dea979be 100644 --- a/twin/src/main/java/com/iluwatar/twin/BallThread.java +++ b/twin/src/main/java/com/iluwatar/twin/BallThread.java @@ -23,6 +23,9 @@ package com.iluwatar.twin; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * This class is a UI thread for drawing the {@link BallItem}, and provide the method for suspend * and resume. It hold the reference of {@link BallItem} to delegate the draw task. @@ -31,6 +34,8 @@ package com.iluwatar.twin; public class BallThread extends Thread { + private static final Logger LOGGER = LoggerFactory.getLogger(BallThread.class); + private BallItem twin; private volatile boolean isSuspended; @@ -61,12 +66,12 @@ public class BallThread extends Thread { public void suspendMe() { isSuspended = true; - System.out.println("Begin to suspend BallThread"); + LOGGER.info("Begin to suspend BallThread"); } public void resumeMe() { isSuspended = false; - System.out.println("Begin to resume BallThread"); + LOGGER.info("Begin to resume BallThread"); } public void stopMe() { diff --git a/twin/src/main/java/com/iluwatar/twin/GameItem.java b/twin/src/main/java/com/iluwatar/twin/GameItem.java index 08d7dcce7..da2cef7a2 100644 --- a/twin/src/main/java/com/iluwatar/twin/GameItem.java +++ b/twin/src/main/java/com/iluwatar/twin/GameItem.java @@ -24,16 +24,21 @@ package com.iluwatar.twin; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * GameItem is a common class which provides some common methods for game object. */ public abstract class GameItem { + private static final Logger LOGGER = LoggerFactory.getLogger(GameItem.class); + /** * Template method, do some common logic before draw */ public void draw() { - System.out.println("draw"); + LOGGER.info("draw"); doDraw(); } diff --git a/value-object/src/main/java/com/iluwatar/value/object/App.java b/value-object/src/main/java/com/iluwatar/value/object/App.java index 1e943d054..238258441 100644 --- a/value-object/src/main/java/com/iluwatar/value/object/App.java +++ b/value-object/src/main/java/com/iluwatar/value/object/App.java @@ -22,6 +22,9 @@ */ package com.iluwatar.value.object; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * A Value Object are objects which follow value semantics rather than reference semantics. This * means value objects' equality are not based on identity. Two value objects are equal when they @@ -38,6 +41,9 @@ package com.iluwatar.value.object; * Colebourne's term VALJO : http://blog.joda.org/2014/03/valjos-value-java-objects.html */ public class App { + + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * This practice creates three HeroStats(Value object) and checks equality between those. */ @@ -46,9 +52,9 @@ public class App { HeroStat statB = HeroStat.valueOf(10, 5, 0); HeroStat statC = HeroStat.valueOf(5, 1, 8); - System.out.println(statA.toString()); + LOGGER.info(statA.toString()); - System.out.println("Is statA and statB equal : " + statA.equals(statB)); - System.out.println("Is statA and statC equal : " + statA.equals(statC)); + LOGGER.info("Is statA and statB equal : {}", statA.equals(statB)); + LOGGER.info("Is statA and statC equal : {}", statA.equals(statC)); } } diff --git a/visitor/src/main/java/com/iluwatar/visitor/CommanderVisitor.java b/visitor/src/main/java/com/iluwatar/visitor/CommanderVisitor.java index 6e54c7861..466c12f51 100644 --- a/visitor/src/main/java/com/iluwatar/visitor/CommanderVisitor.java +++ b/visitor/src/main/java/com/iluwatar/visitor/CommanderVisitor.java @@ -22,6 +22,9 @@ */ package com.iluwatar.visitor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * CommanderVisitor @@ -29,6 +32,8 @@ package com.iluwatar.visitor; */ public class CommanderVisitor implements UnitVisitor { + private static final Logger LOGGER = LoggerFactory.getLogger(CommanderVisitor.class); + @Override public void visitSoldier(Soldier soldier) { // Do nothing @@ -41,6 +46,6 @@ public class CommanderVisitor implements UnitVisitor { @Override public void visitCommander(Commander commander) { - System.out.println("Good to see you " + commander); + LOGGER.info("Good to see you {}", commander); } } diff --git a/visitor/src/main/java/com/iluwatar/visitor/SergeantVisitor.java b/visitor/src/main/java/com/iluwatar/visitor/SergeantVisitor.java index 4fca0a5bd..aa06cb2ad 100644 --- a/visitor/src/main/java/com/iluwatar/visitor/SergeantVisitor.java +++ b/visitor/src/main/java/com/iluwatar/visitor/SergeantVisitor.java @@ -22,6 +22,9 @@ */ package com.iluwatar.visitor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * SergeantVisitor @@ -29,6 +32,8 @@ package com.iluwatar.visitor; */ public class SergeantVisitor implements UnitVisitor { + private static final Logger LOGGER = LoggerFactory.getLogger(SergeantVisitor.class); + @Override public void visitSoldier(Soldier soldier) { // Do nothing @@ -36,7 +41,7 @@ public class SergeantVisitor implements UnitVisitor { @Override public void visitSergeant(Sergeant sergeant) { - System.out.println("Hello " + sergeant); + LOGGER.info("Hello {}", sergeant); } @Override diff --git a/visitor/src/main/java/com/iluwatar/visitor/SoldierVisitor.java b/visitor/src/main/java/com/iluwatar/visitor/SoldierVisitor.java index fff24f699..0907a2531 100644 --- a/visitor/src/main/java/com/iluwatar/visitor/SoldierVisitor.java +++ b/visitor/src/main/java/com/iluwatar/visitor/SoldierVisitor.java @@ -22,6 +22,9 @@ */ package com.iluwatar.visitor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * * SoldierVisitor @@ -29,9 +32,11 @@ package com.iluwatar.visitor; */ public class SoldierVisitor implements UnitVisitor { + private static final Logger LOGGER = LoggerFactory.getLogger(SoldierVisitor.class); + @Override public void visitSoldier(Soldier soldier) { - System.out.println("Greetings " + soldier); + LOGGER.info("Greetings {}", soldier); } @Override From 56b088425814c975e9983a3aa3d99be2ada6d1e8 Mon Sep 17 00:00:00 2001 From: igeligel Date: Mon, 24 Oct 2016 15:28:27 +0200 Subject: [PATCH 04/37] Change name of variables in test #498 --- .../test/RoyaltyObjectMotherTest.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/object-mother/src/test/java/com/iluwatar/objectmother/test/RoyaltyObjectMotherTest.java b/object-mother/src/test/java/com/iluwatar/objectmother/test/RoyaltyObjectMotherTest.java index feba71a1b..ebe536d24 100644 --- a/object-mother/src/test/java/com/iluwatar/objectmother/test/RoyaltyObjectMotherTest.java +++ b/object-mother/src/test/java/com/iluwatar/objectmother/test/RoyaltyObjectMotherTest.java @@ -45,26 +45,26 @@ public class RoyaltyObjectMotherTest { @Test public void queenIsBlockingFlirtCauseDrunkKing() { - King soberUnhappyKing = RoyaltyObjectMother.createDrunkKing(); + King drunkUnhappyKing = RoyaltyObjectMother.createDrunkKing(); Queen notFlirtyQueen = RoyaltyObjectMother.createNotFlirtyQueen(); - soberUnhappyKing.flirt(notFlirtyQueen); - assertFalse(soberUnhappyKing.isHappy()); + drunkUnhappyKing.flirt(notFlirtyQueen); + assertFalse(drunkUnhappyKing.isHappy()); } @Test public void queenIsBlockingFlirt() { - King soberUnhappyKing = RoyaltyObjectMother.createHappyKing(); + King soberHappyKing = RoyaltyObjectMother.createHappyKing(); Queen notFlirtyQueen = RoyaltyObjectMother.createNotFlirtyQueen(); - soberUnhappyKing.flirt(notFlirtyQueen); - assertFalse(soberUnhappyKing.isHappy()); + soberHappyKing.flirt(notFlirtyQueen); + assertFalse(soberHappyKing.isHappy()); } @Test public void successfullKingFlirt() { - King soberUnhappyKing = RoyaltyObjectMother.createHappyKing(); + King soberHappyKing = RoyaltyObjectMother.createHappyKing(); Queen flirtyQueen = RoyaltyObjectMother.createFlirtyQueen(); - soberUnhappyKing.flirt(flirtyQueen); - assertTrue(soberUnhappyKing.isHappy()); + soberHappyKing.flirt(flirtyQueen); + assertTrue(soberHappyKing.isHappy()); } @Test From 20295316c2f43e36ac3748551bf45ce60194c635 Mon Sep 17 00:00:00 2001 From: igeligel Date: Mon, 24 Oct 2016 15:30:17 +0200 Subject: [PATCH 05/37] add entry to parent pom.xml #498 --- pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/pom.xml b/pom.xml index 144b8efff..7aec509d4 100644 --- a/pom.xml +++ b/pom.xml @@ -132,6 +132,7 @@ aggregator-microservices promise page-object + object-mother From 74ac79b01ecb5fe47810e3cfba71e274349144a6 Mon Sep 17 00:00:00 2001 From: igeligel Date: Mon, 24 Oct 2016 15:33:25 +0200 Subject: [PATCH 06/37] Fix pom.xml --- pom.xml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 598386753..fc68a3830 100644 --- a/pom.xml +++ b/pom.xml @@ -132,13 +132,10 @@ aggregator-microservices promise page-object -<<<<<<< HEAD + event-asynchronous object-mother -======= - event-asynchronous ->>>>>>> refs/remotes/iluwatar/master From 6aed26e61e2af5d3574eaf6b842094ea041947da Mon Sep 17 00:00:00 2001 From: igeligel Date: Mon, 24 Oct 2016 15:43:52 +0200 Subject: [PATCH 07/37] Fix pom.xml Deleted tag because i added it one time more than neccessary --- pom.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/pom.xml b/pom.xml index fc68a3830..76e108a57 100644 --- a/pom.xml +++ b/pom.xml @@ -135,7 +135,6 @@ event-asynchronous object-mother - From 2a77ac29e994cecc50f5ee5e461abdcb316dbaa3 Mon Sep 17 00:00:00 2001 From: Amit Dixit Date: Wed, 26 Oct 2016 16:59:36 +0530 Subject: [PATCH 08/37] FirstCut++ FirstCut++ --- module/README.md | 29 +++ module/pom.xml | 45 +++++ .../main/java/com/iluwatar/module/App.java | 73 +++++++ .../iluwatar/module/FilePrinterModule.java | 100 ++++++++++ module/src/main/resources/log4j.xml | 41 ++++ .../java/com/iluwatar/module/AppTest.java | 37 ++++ .../java/com/iluwatar/module/ModuleTest.java | 180 ++++++++++++++++++ pom.xml | 1 + 8 files changed, 506 insertions(+) create mode 100644 module/README.md create mode 100644 module/pom.xml create mode 100644 module/src/main/java/com/iluwatar/module/App.java create mode 100644 module/src/main/java/com/iluwatar/module/FilePrinterModule.java create mode 100644 module/src/main/resources/log4j.xml create mode 100644 module/src/test/java/com/iluwatar/module/AppTest.java create mode 100644 module/src/test/java/com/iluwatar/module/ModuleTest.java diff --git a/module/README.md b/module/README.md new file mode 100644 index 000000000..d3d6b8746 --- /dev/null +++ b/module/README.md @@ -0,0 +1,29 @@ +--- +layout: pattern +title: Module +folder: module +permalink: /patterns/module/ +pumlid: JShB3OGm303HLg20nFVjnYGM1CN6ycTfVtFSsnjfzY5jPgUqkLqHwXy0mxUU8wuyqidQ8q4IjJqCO-QBWGOtVh5qyd5AKOmW4mT6Nu2-ZiAekapH_hkcSTNa-GC0 +categories: Persistence Tier +tags: + - Java + - Difficulty-Beginner +--- + +## Intent +A layer of mappers that moves data between objects and a database while keeping them independent of each other and the mapper itself + +![alt text](./etc/module.png "Module") + +## Applicability +The module pattern is a design pattern used to implement the concept of software modules, defined by modular programming, in a programming language with incomplete direct support for the concept. + +The Module pattern can be considered a creational pattern and a structural pattern. It manages the creation and organization of other elements, and groups them as the structural pattern does. + +An object that applies this pattern can provide the equivalent of a namespace, providing the initialization and finalization process of a static class or a class with static members with cleaner, more concise syntax and semantics. + +It supports specific cases where a class or object can be considered structured, procedural data. And, vice versa, migrate structured, procedural data, and considered as object-oriented. + +## Credits + +* [Module](https://en.wikipedia.org/wiki/Module_pattern) diff --git a/module/pom.xml b/module/pom.xml new file mode 100644 index 000000000..bc43e3e09 --- /dev/null +++ b/module/pom.xml @@ -0,0 +1,45 @@ + + + + 4.0.0 + + com.iluwatar + java-design-patterns + 1.14.0-SNAPSHOT + + module + + + junit + junit + test + + + log4j + log4j + + + diff --git a/module/src/main/java/com/iluwatar/module/App.java b/module/src/main/java/com/iluwatar/module/App.java new file mode 100644 index 000000000..9dab6a00c --- /dev/null +++ b/module/src/main/java/com/iluwatar/module/App.java @@ -0,0 +1,73 @@ +/** + * The MIT License Copyright (c) 2016 Amit Dixit + * + * 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.module; + +import java.io.FileNotFoundException; + +/** + * The Data Mapper (DM) is a layer of software that separates the in-memory + * objects from the database. Its responsibility is to transfer data between the + * two and also to isolate them from each other. With Data Mapper the in-memory + * objects needn't know even that there's a database present; they need no SQL + * interface code, and certainly no knowledge of the database schema. (The + * database schema is always ignorant of the objects that use it.) Since it's a + * form of Mapper , Data Mapper itself is even unknown to the domain layer. + *

+ * The below example demonstrates basic CRUD operations: Create, Read, Update, + * and Delete. + * + */ +public final class App { + + private static final String OUTPUT_FILE = "output.txt"; + private static final String ERROR_FILE = "error.txt"; + + public static FilePrinterModule filePrinterModule = null; + + public static void prepare() throws FileNotFoundException { + filePrinterModule = FilePrinterModule.getSingleton(); + + filePrinterModule.prepare(OUTPUT_FILE, ERROR_FILE); + } + + public static void unprepare() { + filePrinterModule.unprepare(); + } + + public static final void execute(final String... args) { + filePrinterModule.printString("Hello World"); + } + + /** + * Program entry point. + * + * @param args + * command line args. + * @throws FileNotFoundException + */ + public static final void main(final String... args) + throws FileNotFoundException { + prepare(); + execute(args); + unprepare(); + } + + private App() { + } +} diff --git a/module/src/main/java/com/iluwatar/module/FilePrinterModule.java b/module/src/main/java/com/iluwatar/module/FilePrinterModule.java new file mode 100644 index 000000000..879492248 --- /dev/null +++ b/module/src/main/java/com/iluwatar/module/FilePrinterModule.java @@ -0,0 +1,100 @@ +package com.iluwatar.module; + +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.PrintStream; + +import org.apache.log4j.Logger; + +/** + * The MIT License Copyright (c) 2016 Amit Dixit + * + * 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. + */ +public final class FilePrinterModule { + + private static final Logger logger = Logger + .getLogger(FilePrinterModule.class); + + private static FilePrinterModule singleton = null; + + public PrintStream output = null; + public PrintStream error = null; + + private FilePrinterModule() { + } + + public static final FilePrinterModule getSingleton() { + + if (FilePrinterModule.singleton == null) { + FilePrinterModule.singleton = new FilePrinterModule(); + } + + return FilePrinterModule.singleton; + } + + /** + * + * @throws FileNotFoundException + */ + public final void prepare(final String outputFile, final String errorFile) + throws FileNotFoundException { + + logger.debug("MainModule::prepare();"); + + this.output = new PrintStream(new FileOutputStream(outputFile)); + this.error = new PrintStream(new FileOutputStream(errorFile)); + } + + /** + * + */ + public final void unprepare() { + + if (this.output != null) { + + this.output.flush(); + this.output.close(); + } + + if (this.error != null) { + + this.error.flush(); + this.error.close(); + } + + logger.debug("MainModule::unprepare();"); + } + + /** + * + * @param value + */ + public final void printString(final String value) { + this.output.print(value); + } + + /** + * + * @param value + */ + public final void printErrorString(final String value) { + this.error.print(value); + } +} diff --git a/module/src/main/resources/log4j.xml b/module/src/main/resources/log4j.xml new file mode 100644 index 000000000..b591c17e1 --- /dev/null +++ b/module/src/main/resources/log4j.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/module/src/test/java/com/iluwatar/module/AppTest.java b/module/src/test/java/com/iluwatar/module/AppTest.java new file mode 100644 index 000000000..46c12ef38 --- /dev/null +++ b/module/src/test/java/com/iluwatar/module/AppTest.java @@ -0,0 +1,37 @@ +/** + * The MIT License Copyright (c) 2016 Amit Dixit + * + * 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.module; + +import java.io.FileNotFoundException; + +import com.iluwatar.module.App; + +import org.junit.Test; + +/** + * Tests that Data-Mapper example runs without errors. + */ +public final class AppTest { + + @Test + public void test() throws FileNotFoundException { + final String[] args = {}; + App.main(args); + } +} diff --git a/module/src/test/java/com/iluwatar/module/ModuleTest.java b/module/src/test/java/com/iluwatar/module/ModuleTest.java new file mode 100644 index 000000000..797e7f26a --- /dev/null +++ b/module/src/test/java/com/iluwatar/module/ModuleTest.java @@ -0,0 +1,180 @@ +/** + * The MIT License Copyright (c) 2016 Amit Dixit + * + * 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.module; + +import static org.junit.Assert.assertEquals; + +import java.io.BufferedReader; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; + +import org.apache.log4j.Logger; +import org.junit.Test; + +/** + * The Data Mapper (DM) is a layer of software that separates the in-memory + * objects from the database. Its responsibility is to transfer data between the + * two and also to isolate them from each other. With Data Mapper the in-memory + * objects needn't know even that there's a database present; they need no SQL + * interface code, and certainly no knowledge of the database schema. (The + * database schema is always ignorant of the objects that use it.) Since it's a + * form of Mapper , Data Mapper itself is even unknown to the domain layer. + *

+ */ +public class ModuleTest { + + private static final Logger logger = Logger.getLogger(ModuleTest.class); + + private static final String OUTPUT_FILE = "output.txt"; + private static final String ERROR_FILE = "error.txt"; + + private static final String MESSAGE = "MESSAGE"; + private static final String ERROR = "ERROR"; + + /** + * This test verify that 'MESSAGE' is perfectly printed in output file + * + * @throws IOException + */ + @Test + public void testPositiveMessage() throws IOException { + + /* Prepare the essential sub modules, to perform the sequence of jobs */ + final FilePrinterModule filePrinterModule = FilePrinterModule + .getSingleton(); + + /* Prepare the essential sub modules, to perform the sequence of jobs */ + filePrinterModule.prepare(OUTPUT_FILE, ERROR_FILE); + + /* Print 'Message' in file */ + filePrinterModule.printString(MESSAGE); + + /* Test if 'Message' is printed in file */ + assertEquals(readFirstLine(OUTPUT_FILE), MESSAGE); + + /* Unprepare to cleanup the modules */ + filePrinterModule.unprepare(); + } + + /** + * This test verify that nothing is printed in output file + * + * @throws IOException + */ + @Test + public void testNegativeMessage() throws IOException { + + /* Prepare the essential sub modules, to perform the sequence of jobs */ + final FilePrinterModule filePrinterModule = FilePrinterModule + .getSingleton(); + + /* Prepare the essential sub modules, to perform the sequence of jobs */ + filePrinterModule.prepare(OUTPUT_FILE, ERROR_FILE); + + /* Test if nothing is printed in file */ + assertEquals(readFirstLine(OUTPUT_FILE), null); + + /* Unprepare to cleanup the modules */ + filePrinterModule.unprepare(); + } + + /** + * This test verify that 'ERROR' is perfectly printed in error file + * + * @throws FileNotFoundException + */ + @Test + public void testPositiveErrorMessage() throws FileNotFoundException { + + /* Prepare the essential sub modules, to perform the sequence of jobs */ + final FilePrinterModule filePrinterModule = FilePrinterModule + .getSingleton(); + + /* Prepare the essential sub modules, to perform the sequence of jobs */ + filePrinterModule.prepare(OUTPUT_FILE, ERROR_FILE); + + /* Print 'Error' in file */ + filePrinterModule.printErrorString(ERROR); + + /* Test if 'Message' is printed in file */ + assertEquals(readFirstLine(ERROR_FILE), ERROR); + + /* Unprepare to cleanup the modules */ + filePrinterModule.unprepare(); + } + + /** + * This test verify that nothing is printed in error file + * + * @throws FileNotFoundException + */ + @Test + public void testNegativeErrorMessage() throws FileNotFoundException { + + /* Prepare the essential sub modules, to perform the sequence of jobs */ + final FilePrinterModule filePrinterModule = FilePrinterModule + .getSingleton(); + + /* Prepare the essential sub modules, to perform the sequence of jobs */ + filePrinterModule.prepare(OUTPUT_FILE, ERROR_FILE); + + /* Test if nothing is printed in file */ + assertEquals(readFirstLine(ERROR_FILE), null); + + /* Unprepare to cleanup the modules */ + filePrinterModule.unprepare(); + } + + /** + * Utility method to read first line of a file + * + * @param file + * @return + */ + private static final String readFirstLine(final String file) { + + String firstLine = null; + BufferedReader bufferedReader = null; + try { + + /* Create a buffered reader */ + bufferedReader = new BufferedReader(new FileReader(file)); + + /* Read the line */ + firstLine = bufferedReader.readLine(); + + logger.info("ModuleTest::readFile() : firstLine : " + firstLine); + + } catch (final IOException e) { + logger.error("ModuleTest::readFile()", e); + } finally { + + if (bufferedReader != null) { + try { + bufferedReader.close(); + } catch (final IOException e) { + logger.error("ModuleTest::readFile()", e); + } + } + } + + return firstLine; + } +} diff --git a/pom.xml b/pom.xml index 538058a81..a73992607 100644 --- a/pom.xml +++ b/pom.xml @@ -123,6 +123,7 @@ factory-kit feature-toggle value-object + module monad mute-idiom mutex From 7015e95ac3b8560423b0a417683ab90ea5814599 Mon Sep 17 00:00:00 2001 From: Amit Dixit Date: Thu, 27 Oct 2016 15:55:08 +0530 Subject: [PATCH 09/37] SecondCut++ SecondCut++ --- module/README.md | 8 +- module/etc/module.png | Bin 0 -> 18027 bytes module/etc/module.ucls | 69 ++++++ .../main/java/com/iluwatar/module/App.java | 28 ++- .../iluwatar/module/ConsoleLoggerModule.java | 106 +++++++++ ...interModule.java => FileLoggerModule.java} | 61 +++--- .../java/com/iluwatar/module/ModuleTest.java | 203 +++++++++++++++--- 7 files changed, 403 insertions(+), 72 deletions(-) create mode 100644 module/etc/module.png create mode 100644 module/etc/module.ucls create mode 100644 module/src/main/java/com/iluwatar/module/ConsoleLoggerModule.java rename module/src/main/java/com/iluwatar/module/{FilePrinterModule.java => FileLoggerModule.java} (57%) diff --git a/module/README.md b/module/README.md index d3d6b8746..24bd3f543 100644 --- a/module/README.md +++ b/module/README.md @@ -4,26 +4,22 @@ title: Module folder: module permalink: /patterns/module/ pumlid: JShB3OGm303HLg20nFVjnYGM1CN6ycTfVtFSsnjfzY5jPgUqkLqHwXy0mxUU8wuyqidQ8q4IjJqCO-QBWGOtVh5qyd5AKOmW4mT6Nu2-ZiAekapH_hkcSTNa-GC0 -categories: Persistence Tier +categories: Creational Pattern tags: - Java - Difficulty-Beginner --- ## Intent -A layer of mappers that moves data between objects and a database while keeping them independent of each other and the mapper itself +Module pattern is used to implement the concept of software modules, defined by modular programming, in a programming language with incomplete direct support for the concept. ![alt text](./etc/module.png "Module") ## Applicability -The module pattern is a design pattern used to implement the concept of software modules, defined by modular programming, in a programming language with incomplete direct support for the concept. - The Module pattern can be considered a creational pattern and a structural pattern. It manages the creation and organization of other elements, and groups them as the structural pattern does. An object that applies this pattern can provide the equivalent of a namespace, providing the initialization and finalization process of a static class or a class with static members with cleaner, more concise syntax and semantics. -It supports specific cases where a class or object can be considered structured, procedural data. And, vice versa, migrate structured, procedural data, and considered as object-oriented. - ## Credits * [Module](https://en.wikipedia.org/wiki/Module_pattern) diff --git a/module/etc/module.png b/module/etc/module.png new file mode 100644 index 0000000000000000000000000000000000000000..a26807d290c0d2aced42c5e5d48cf0780e9c4d2b GIT binary patch literal 18027 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�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 b&*xx@wCm+^Q{eyCf+Z;`E0Qa$`}Y3>Bi8;O literal 0 HcmV?d00001 diff --git a/module/etc/module.ucls b/module/etc/module.ucls new file mode 100644 index 000000000..d2519b856 --- /dev/null +++ b/module/etc/module.ucls @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/module/src/main/java/com/iluwatar/module/App.java b/module/src/main/java/com/iluwatar/module/App.java index 9dab6a00c..0ca43d5c2 100644 --- a/module/src/main/java/com/iluwatar/module/App.java +++ b/module/src/main/java/com/iluwatar/module/App.java @@ -35,23 +35,35 @@ import java.io.FileNotFoundException; */ public final class App { - private static final String OUTPUT_FILE = "output.txt"; - private static final String ERROR_FILE = "error.txt"; - - public static FilePrinterModule filePrinterModule = null; + public static FileLoggerModule fileLoggerModule = null; + public static ConsoleLoggerModule consoleLoggerModule = null; public static void prepare() throws FileNotFoundException { - filePrinterModule = FilePrinterModule.getSingleton(); + + fileLoggerModule = FileLoggerModule.getSingleton(); + consoleLoggerModule = ConsoleLoggerModule.getSingleton(); - filePrinterModule.prepare(OUTPUT_FILE, ERROR_FILE); + /* Prepare modules */ + fileLoggerModule.prepare(); + consoleLoggerModule.prepare(); } public static void unprepare() { - filePrinterModule.unprepare(); + + /* Close all resources */ + fileLoggerModule.unprepare(); + consoleLoggerModule.unprepare(); } public static final void execute(final String... args) { - filePrinterModule.printString("Hello World"); + + /* Send logs on file system */ + fileLoggerModule.printString("Message"); + fileLoggerModule.printErrorString("Error"); + + /* Send logs on console */ + consoleLoggerModule.printString("Message"); + consoleLoggerModule.printErrorString("Error"); } /** diff --git a/module/src/main/java/com/iluwatar/module/ConsoleLoggerModule.java b/module/src/main/java/com/iluwatar/module/ConsoleLoggerModule.java new file mode 100644 index 000000000..097f85b0e --- /dev/null +++ b/module/src/main/java/com/iluwatar/module/ConsoleLoggerModule.java @@ -0,0 +1,106 @@ +/** + * The MIT License Copyright (c) 2016 Amit Dixit + * + * 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.module; + +import java.io.FileNotFoundException; +import java.io.PrintStream; + +import org.apache.log4j.Logger; + +/** + * The Module pattern can be considered a Creational pattern and a Structural + * pattern. It manages the creation and organization of other elements, and + * groups them as the structural pattern does. An object that applies this + * pattern can provide the equivalent of a namespace, providing the + * initialization and finalization process of a static class or a class with + * static members with cleaner, more concise syntax and semantics. + *

+ * The below example demonstrates a Console logger module, which can print + * simple and error messages in two designated formats + */ +public class ConsoleLoggerModule { + + private static final Logger logger = Logger + .getLogger(ConsoleLoggerModule.class); + + private static ConsoleLoggerModule singleton = null; + + public PrintStream output = null; + public PrintStream error = null; + + private ConsoleLoggerModule() { + } + + public static final ConsoleLoggerModule getSingleton() { + + if (ConsoleLoggerModule.singleton == null) { + ConsoleLoggerModule.singleton = new ConsoleLoggerModule(); + } + + return ConsoleLoggerModule.singleton; + } + + /** + * + * @throws FileNotFoundException + */ + public final void prepare() { + + logger.debug("ConsoleLoggerModule::prepare();"); + + this.output = new PrintStream(System.out); + this.error = new PrintStream(System.err); + } + + /** + * + */ + public final void unprepare() { + + if (this.output != null) { + + this.output.flush(); + this.output.close(); + } + + if (this.error != null) { + + this.error.flush(); + this.error.close(); + } + + logger.debug("ConsoleLoggerModule::unprepare();"); + } + + /** + * + * @param value + */ + public final void printString(final String value) { + this.output.println(value); + } + + /** + * + * @param value + */ + public final void printErrorString(final String value) { + this.error.println(value); + } +} diff --git a/module/src/main/java/com/iluwatar/module/FilePrinterModule.java b/module/src/main/java/com/iluwatar/module/FileLoggerModule.java similarity index 57% rename from module/src/main/java/com/iluwatar/module/FilePrinterModule.java rename to module/src/main/java/com/iluwatar/module/FileLoggerModule.java index 879492248..d1df062de 100644 --- a/module/src/main/java/com/iluwatar/module/FilePrinterModule.java +++ b/module/src/main/java/com/iluwatar/module/FileLoggerModule.java @@ -1,11 +1,3 @@ -package com.iluwatar.module; - -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.PrintStream; - -import org.apache.log4j.Logger; - /** * The MIT License Copyright (c) 2016 Amit Dixit * @@ -27,39 +19,60 @@ import org.apache.log4j.Logger; * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -public final class FilePrinterModule { +package com.iluwatar.module; + +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.PrintStream; + +import org.apache.log4j.Logger; + +/** + * The Module pattern can be considered a Creational pattern and a Structural + * pattern. It manages the creation and organization of other elements, and + * groups them as the structural pattern does. An object that applies this + * pattern can provide the equivalent of a namespace, providing the + * initialization and finalization process of a static class or a class with + * static members with cleaner, more concise syntax and semantics. + *

+ * The below example demonstrates a File logger module, which can print simple + * and error messages in two designated files + */ +public final class FileLoggerModule { private static final Logger logger = Logger - .getLogger(FilePrinterModule.class); + .getLogger(FileLoggerModule.class); - private static FilePrinterModule singleton = null; + private static FileLoggerModule singleton = null; + + private static final String OUTPUT_FILE = "output.txt"; + private static final String ERROR_FILE = "error.txt"; public PrintStream output = null; public PrintStream error = null; - private FilePrinterModule() { + private FileLoggerModule() { } - public static final FilePrinterModule getSingleton() { + public static final FileLoggerModule getSingleton() { - if (FilePrinterModule.singleton == null) { - FilePrinterModule.singleton = new FilePrinterModule(); + if (FileLoggerModule.singleton == null) { + FileLoggerModule.singleton = new FileLoggerModule(); } - return FilePrinterModule.singleton; + return FileLoggerModule.singleton; } /** * * @throws FileNotFoundException */ - public final void prepare(final String outputFile, final String errorFile) - throws FileNotFoundException { + public final void prepare() throws FileNotFoundException { - logger.debug("MainModule::prepare();"); + logger.debug("FileLoggerModule::prepare();"); - this.output = new PrintStream(new FileOutputStream(outputFile)); - this.error = new PrintStream(new FileOutputStream(errorFile)); + this.output = new PrintStream(new FileOutputStream(OUTPUT_FILE)); + this.error = new PrintStream(new FileOutputStream(ERROR_FILE)); } /** @@ -79,7 +92,7 @@ public final class FilePrinterModule { this.error.close(); } - logger.debug("MainModule::unprepare();"); + logger.debug("FileLoggerModule::unprepare();"); } /** @@ -87,7 +100,7 @@ public final class FilePrinterModule { * @param value */ public final void printString(final String value) { - this.output.print(value); + this.output.println(value); } /** @@ -95,6 +108,6 @@ public final class FilePrinterModule { * @param value */ public final void printErrorString(final String value) { - this.error.print(value); + this.error.println(value); } } diff --git a/module/src/test/java/com/iluwatar/module/ModuleTest.java b/module/src/test/java/com/iluwatar/module/ModuleTest.java index 797e7f26a..cf3435850 100644 --- a/module/src/test/java/com/iluwatar/module/ModuleTest.java +++ b/module/src/test/java/com/iluwatar/module/ModuleTest.java @@ -24,19 +24,21 @@ import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; +import java.io.InputStreamReader; import org.apache.log4j.Logger; import org.junit.Test; /** - * The Data Mapper (DM) is a layer of software that separates the in-memory - * objects from the database. Its responsibility is to transfer data between the - * two and also to isolate them from each other. With Data Mapper the in-memory - * objects needn't know even that there's a database present; they need no SQL - * interface code, and certainly no knowledge of the database schema. (The - * database schema is always ignorant of the objects that use it.) Since it's a - * form of Mapper , Data Mapper itself is even unknown to the domain layer. + * The Module pattern can be considered a Creational pattern and a Structural + * pattern. It manages the creation and organization of other elements, and + * groups them as the structural pattern does. An object that applies this + * pattern can provide the equivalent of a namespace, providing the + * initialization and finalization process of a static class or a class with + * static members with cleaner, more concise syntax and semantics. *

+ * The below example demonstrates a JUnit test for testing two different + * modules: File Logger and Console Logger */ public class ModuleTest { @@ -54,23 +56,23 @@ public class ModuleTest { * @throws IOException */ @Test - public void testPositiveMessage() throws IOException { + public void positiveTestConsoleMessage() throws IOException { /* Prepare the essential sub modules, to perform the sequence of jobs */ - final FilePrinterModule filePrinterModule = FilePrinterModule + final FileLoggerModule fileLoggerModule = FileLoggerModule .getSingleton(); /* Prepare the essential sub modules, to perform the sequence of jobs */ - filePrinterModule.prepare(OUTPUT_FILE, ERROR_FILE); + fileLoggerModule.prepare(); /* Print 'Message' in file */ - filePrinterModule.printString(MESSAGE); + fileLoggerModule.printString(MESSAGE); - /* Test if 'Message' is printed in file */ - assertEquals(readFirstLine(OUTPUT_FILE), MESSAGE); + /* Test if 'Message' is printed on console */ + assertEquals(readFirstLine(), MESSAGE); /* Unprepare to cleanup the modules */ - filePrinterModule.unprepare(); + fileLoggerModule.unprepare(); } /** @@ -79,20 +81,20 @@ public class ModuleTest { * @throws IOException */ @Test - public void testNegativeMessage() throws IOException { + public void negativeTestConsoleMessage() throws IOException { /* Prepare the essential sub modules, to perform the sequence of jobs */ - final FilePrinterModule filePrinterModule = FilePrinterModule + final ConsoleLoggerModule consoleLoggerModule = ConsoleLoggerModule .getSingleton(); /* Prepare the essential sub modules, to perform the sequence of jobs */ - filePrinterModule.prepare(OUTPUT_FILE, ERROR_FILE); + consoleLoggerModule.prepare(); - /* Test if nothing is printed in file */ - assertEquals(readFirstLine(OUTPUT_FILE), null); + /* Test if nothing is printed on console */ + assertEquals(readFirstLine(), null); /* Unprepare to cleanup the modules */ - filePrinterModule.unprepare(); + consoleLoggerModule.unprepare(); } /** @@ -101,23 +103,23 @@ public class ModuleTest { * @throws FileNotFoundException */ @Test - public void testPositiveErrorMessage() throws FileNotFoundException { + public void positiveTestConsoleErrorMessage() { /* Prepare the essential sub modules, to perform the sequence of jobs */ - final FilePrinterModule filePrinterModule = FilePrinterModule + final ConsoleLoggerModule consoleLoggerModule = ConsoleLoggerModule .getSingleton(); /* Prepare the essential sub modules, to perform the sequence of jobs */ - filePrinterModule.prepare(OUTPUT_FILE, ERROR_FILE); + consoleLoggerModule.prepare(); /* Print 'Error' in file */ - filePrinterModule.printErrorString(ERROR); + consoleLoggerModule.printErrorString(ERROR); - /* Test if 'Message' is printed in file */ - assertEquals(readFirstLine(ERROR_FILE), ERROR); + /* Test if 'Message' is printed on console */ + assertEquals(readFirstLine(), ERROR); /* Unprepare to cleanup the modules */ - filePrinterModule.unprepare(); + consoleLoggerModule.unprepare(); } /** @@ -126,20 +128,152 @@ public class ModuleTest { * @throws FileNotFoundException */ @Test - public void testNegativeErrorMessage() throws FileNotFoundException { + public void negativeTestConsoleErrorMessage() { /* Prepare the essential sub modules, to perform the sequence of jobs */ - final FilePrinterModule filePrinterModule = FilePrinterModule + final ConsoleLoggerModule consoleLoggerModule = ConsoleLoggerModule .getSingleton(); /* Prepare the essential sub modules, to perform the sequence of jobs */ - filePrinterModule.prepare(OUTPUT_FILE, ERROR_FILE); + consoleLoggerModule.prepare(); + + /* Test if nothing is printed on console */ + assertEquals(readFirstLine(), null); + + /* Unprepare to cleanup the modules */ + consoleLoggerModule.unprepare(); + } + + /** + * This test verify that 'MESSAGE' is perfectly printed in output file + * + * @throws IOException + */ + @Test + public void positiveTestFileMessage() throws IOException { + + /* Prepare the essential sub modules, to perform the sequence of jobs */ + final FileLoggerModule fileLoggerModule = FileLoggerModule + .getSingleton(); + + /* Prepare the essential sub modules, to perform the sequence of jobs */ + fileLoggerModule.prepare(); + + /* Print 'Message' in file */ + fileLoggerModule.printString(MESSAGE); + + /* Test if 'Message' is printed in file */ + assertEquals(readFirstLine(OUTPUT_FILE), MESSAGE); + + /* Unprepare to cleanup the modules */ + fileLoggerModule.unprepare(); + } + + /** + * This test verify that nothing is printed in output file + * + * @throws IOException + */ + @Test + public void negativeTestFileMessage() throws IOException { + + /* Prepare the essential sub modules, to perform the sequence of jobs */ + final FileLoggerModule fileLoggerModule = FileLoggerModule + .getSingleton(); + + /* Prepare the essential sub modules, to perform the sequence of jobs */ + fileLoggerModule.prepare(); + + /* Test if nothing is printed in file */ + assertEquals(readFirstLine(OUTPUT_FILE), null); + + /* Unprepare to cleanup the modules */ + fileLoggerModule.unprepare(); + } + + /** + * This test verify that 'ERROR' is perfectly printed in error file + * + * @throws FileNotFoundException + */ + @Test + public void positiveTestFileErrorMessage() throws FileNotFoundException { + + /* Prepare the essential sub modules, to perform the sequence of jobs */ + final FileLoggerModule fileLoggerModule = FileLoggerModule + .getSingleton(); + + /* Prepare the essential sub modules, to perform the sequence of jobs */ + fileLoggerModule.prepare(); + + /* Print 'Error' in file */ + fileLoggerModule.printErrorString(ERROR); + + /* Test if 'Message' is printed in file */ + assertEquals(readFirstLine(ERROR_FILE), ERROR); + + /* Unprepare to cleanup the modules */ + fileLoggerModule.unprepare(); + } + + /** + * This test verify that nothing is printed in error file + * + * @throws FileNotFoundException + */ + @Test + public void negativeTestFileErrorMessage() throws FileNotFoundException { + + /* Prepare the essential sub modules, to perform the sequence of jobs */ + final FileLoggerModule fileLoggerModule = FileLoggerModule + .getSingleton(); + + /* Prepare the essential sub modules, to perform the sequence of jobs */ + fileLoggerModule.prepare(); /* Test if nothing is printed in file */ assertEquals(readFirstLine(ERROR_FILE), null); /* Unprepare to cleanup the modules */ - filePrinterModule.unprepare(); + fileLoggerModule.unprepare(); + } + + /** + * Utility method to read first line of a file + * + * @param file + * @return + */ + private static final String readFirstLine() { + + String firstLine = null; + BufferedReader bufferedReader = null; + try { + + /* Create a buffered reader */ + bufferedReader = new BufferedReader( + new InputStreamReader(System.in)); + + /* Read the line */ + firstLine = bufferedReader.readLine(); + + logger.info("ModuleTest::readFirstLineFromConsole() : firstLine : " + + firstLine); + + } catch (final IOException e) { + logger.error("ModuleTest::readFirstLineFromConsole()", e); + } finally { + + if (bufferedReader != null) { + try { + bufferedReader.close(); + } catch (final IOException e) { + logger.error("ModuleTest::readFirstLineFromConsole()", e); + } + } + } + + return firstLine; } /** @@ -160,17 +294,18 @@ public class ModuleTest { /* Read the line */ firstLine = bufferedReader.readLine(); - logger.info("ModuleTest::readFile() : firstLine : " + firstLine); + logger.info("ModuleTest::readFirstLine() : firstLine : " + + firstLine); } catch (final IOException e) { - logger.error("ModuleTest::readFile()", e); + logger.error("ModuleTest::readFirstLine()", e); } finally { if (bufferedReader != null) { try { bufferedReader.close(); } catch (final IOException e) { - logger.error("ModuleTest::readFile()", e); + logger.error("ModuleTest::readFirstLine()", e); } } } From 1ace4c05d6c8141964285032edb17e136e0ba69f Mon Sep 17 00:00:00 2001 From: Amit Dixit Date: Thu, 27 Oct 2016 15:59:51 +0530 Subject: [PATCH 10/37] App++ App++ --- .../main/java/com/iluwatar/module/App.java | 19 +++++++++---------- .../java/com/iluwatar/module/AppTest.java | 1 - 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/module/src/main/java/com/iluwatar/module/App.java b/module/src/main/java/com/iluwatar/module/App.java index 0ca43d5c2..a3ecdb31c 100644 --- a/module/src/main/java/com/iluwatar/module/App.java +++ b/module/src/main/java/com/iluwatar/module/App.java @@ -21,16 +21,15 @@ package com.iluwatar.module; import java.io.FileNotFoundException; /** - * The Data Mapper (DM) is a layer of software that separates the in-memory - * objects from the database. Its responsibility is to transfer data between the - * two and also to isolate them from each other. With Data Mapper the in-memory - * objects needn't know even that there's a database present; they need no SQL - * interface code, and certainly no knowledge of the database schema. (The - * database schema is always ignorant of the objects that use it.) Since it's a - * form of Mapper , Data Mapper itself is even unknown to the domain layer. + * The Module pattern can be considered a Creational pattern and a Structural + * pattern. It manages the creation and organization of other elements, and + * groups them as the structural pattern does. An object that applies this + * pattern can provide the equivalent of a namespace, providing the + * initialization and finalization process of a static class or a class with + * static members with cleaner, more concise syntax and semantics. *

- * The below example demonstrates basic CRUD operations: Create, Read, Update, - * and Delete. + * The below example demonstrates a use case for testing two different modules: + * File Logger and Console Logger * */ public final class App { @@ -39,7 +38,7 @@ public final class App { public static ConsoleLoggerModule consoleLoggerModule = null; public static void prepare() throws FileNotFoundException { - + fileLoggerModule = FileLoggerModule.getSingleton(); consoleLoggerModule = ConsoleLoggerModule.getSingleton(); diff --git a/module/src/test/java/com/iluwatar/module/AppTest.java b/module/src/test/java/com/iluwatar/module/AppTest.java index 46c12ef38..eb348d758 100644 --- a/module/src/test/java/com/iluwatar/module/AppTest.java +++ b/module/src/test/java/com/iluwatar/module/AppTest.java @@ -25,7 +25,6 @@ import com.iluwatar.module.App; import org.junit.Test; /** - * Tests that Data-Mapper example runs without errors. */ public final class AppTest { From 7ba6cb43fdc38b534db583f7ec01e816b437f05d Mon Sep 17 00:00:00 2001 From: Amit Dixit Date: Thu, 27 Oct 2016 16:00:01 +0530 Subject: [PATCH 11/37] App App --- module/src/test/java/com/iluwatar/module/AppTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/module/src/test/java/com/iluwatar/module/AppTest.java b/module/src/test/java/com/iluwatar/module/AppTest.java index eb348d758..0f20b4959 100644 --- a/module/src/test/java/com/iluwatar/module/AppTest.java +++ b/module/src/test/java/com/iluwatar/module/AppTest.java @@ -25,6 +25,7 @@ import com.iluwatar.module.App; import org.junit.Test; /** + * Tests that Module example runs without errors. */ public final class AppTest { From ea7752c5e183d2981c29ce45bb4d989ef2eefab6 Mon Sep 17 00:00:00 2001 From: Amit Dixit Date: Thu, 27 Oct 2016 18:30:07 +0530 Subject: [PATCH 12/37] checkstyle errors removed checkstyle errors removed --- module/etc/module.urm.puml | 43 +++ .../main/java/com/iluwatar/module/App.java | 101 +++--- .../iluwatar/module/ConsoleLoggerModule.java | 122 +++---- .../com/iluwatar/module/FileLoggerModule.java | 151 +++++---- .../java/com/iluwatar/module/AppTest.java | 10 +- .../iluwatar/module/FileLoggerModuleTest.java | 182 ++++++++++ .../java/com/iluwatar/module/ModuleTest.java | 315 ------------------ 7 files changed, 425 insertions(+), 499 deletions(-) create mode 100644 module/etc/module.urm.puml create mode 100644 module/src/test/java/com/iluwatar/module/FileLoggerModuleTest.java delete mode 100644 module/src/test/java/com/iluwatar/module/ModuleTest.java diff --git a/module/etc/module.urm.puml b/module/etc/module.urm.puml new file mode 100644 index 000000000..d78f12da8 --- /dev/null +++ b/module/etc/module.urm.puml @@ -0,0 +1,43 @@ +@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() + + 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() + + 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/src/main/java/com/iluwatar/module/App.java b/module/src/main/java/com/iluwatar/module/App.java index a3ecdb31c..cfa50975f 100644 --- a/module/src/main/java/com/iluwatar/module/App.java +++ b/module/src/main/java/com/iluwatar/module/App.java @@ -21,64 +21,75 @@ package com.iluwatar.module; import java.io.FileNotFoundException; /** - * The Module pattern can be considered a Creational pattern and a Structural - * pattern. It manages the creation and organization of other elements, and - * groups them as the structural pattern does. An object that applies this - * pattern can provide the equivalent of a namespace, providing the - * initialization and finalization process of a static class or a class with - * static members with cleaner, more concise syntax and semantics. + * The Module pattern can be considered a Creational pattern and a Structural pattern. It manages + * the creation and organization of other elements, and groups them as the structural pattern does. + * An object that applies this pattern can provide the equivalent of a namespace, providing the + * initialization and finalization process of a static class or a class with static members with + * cleaner, more concise syntax and semantics. *

- * The below example demonstrates a use case for testing two different modules: - * File Logger and Console Logger + * The below example demonstrates a use case for testing two different modules: File Logger and + * Console Logger * */ public final class App { - public static FileLoggerModule fileLoggerModule = null; - public static ConsoleLoggerModule consoleLoggerModule = null; + public static FileLoggerModule fileLoggerModule = null; + public static ConsoleLoggerModule consoleLoggerModule = null; - public static void prepare() throws FileNotFoundException { + /** + * Following method performs the initialization + * + * @throws FileNotFoundException if program is not able to find log files (output.txt and + * error.txt) + */ + public static void prepare() throws FileNotFoundException { - fileLoggerModule = FileLoggerModule.getSingleton(); - consoleLoggerModule = ConsoleLoggerModule.getSingleton(); + fileLoggerModule = FileLoggerModule.getSingleton(); + consoleLoggerModule = ConsoleLoggerModule.getSingleton(); - /* Prepare modules */ - fileLoggerModule.prepare(); - consoleLoggerModule.prepare(); - } + /* Prepare modules */ + fileLoggerModule.prepare(); + consoleLoggerModule.prepare(); + } - public static void unprepare() { + /** + * Following method performs the finalization + */ + public static void unprepare() { - /* Close all resources */ - fileLoggerModule.unprepare(); - consoleLoggerModule.unprepare(); - } + /* Close all resources */ + fileLoggerModule.unprepare(); + consoleLoggerModule.unprepare(); + } - public static final void execute(final String... args) { + /** + * Following method is main executor + * + * @param args for providing default program arguments + */ + public static void execute(final String... args) { - /* Send logs on file system */ - fileLoggerModule.printString("Message"); - fileLoggerModule.printErrorString("Error"); + /* Send logs on file system */ + fileLoggerModule.printString("Message"); + fileLoggerModule.printErrorString("Error"); - /* Send logs on console */ - consoleLoggerModule.printString("Message"); - consoleLoggerModule.printErrorString("Error"); - } + /* Send logs on console */ + consoleLoggerModule.printString("Message"); + consoleLoggerModule.printErrorString("Error"); + } - /** - * Program entry point. - * - * @param args - * command line args. - * @throws FileNotFoundException - */ - public static final void main(final String... args) - throws FileNotFoundException { - prepare(); - execute(args); - unprepare(); - } + /** + * Program entry point. + * + * @param args command line args. + * @throws FileNotFoundException if program is not able to find log files (output.txt and + * error.txt) + */ + public static void main(final String... args) throws FileNotFoundException { + prepare(); + execute(args); + unprepare(); + } - private App() { - } + private App() {} } diff --git a/module/src/main/java/com/iluwatar/module/ConsoleLoggerModule.java b/module/src/main/java/com/iluwatar/module/ConsoleLoggerModule.java index 097f85b0e..8f5941951 100644 --- a/module/src/main/java/com/iluwatar/module/ConsoleLoggerModule.java +++ b/module/src/main/java/com/iluwatar/module/ConsoleLoggerModule.java @@ -18,89 +18,91 @@ */ package com.iluwatar.module; -import java.io.FileNotFoundException; import java.io.PrintStream; import org.apache.log4j.Logger; /** - * The Module pattern can be considered a Creational pattern and a Structural - * pattern. It manages the creation and organization of other elements, and - * groups them as the structural pattern does. An object that applies this - * pattern can provide the equivalent of a namespace, providing the - * initialization and finalization process of a static class or a class with - * static members with cleaner, more concise syntax and semantics. + * The Module pattern can be considered a Creational pattern and a Structural pattern. It manages + * the creation and organization of other elements, and groups them as the structural pattern does. + * An object that applies this pattern can provide the equivalent of a namespace, providing the + * initialization and finalization process of a static class or a class with static members with + * cleaner, more concise syntax and semantics. *

- * The below example demonstrates a Console logger module, which can print - * simple and error messages in two designated formats + * The below example demonstrates a Console logger module, which can print simple and error messages + * in two designated formats */ -public class ConsoleLoggerModule { +public final class ConsoleLoggerModule { - private static final Logger logger = Logger - .getLogger(ConsoleLoggerModule.class); + private static final Logger LOGGER = Logger.getLogger(ConsoleLoggerModule.class); - private static ConsoleLoggerModule singleton = null; + private static ConsoleLoggerModule singleton = null; - public PrintStream output = null; - public PrintStream error = null; + public PrintStream output = null; + public PrintStream error = null; - private ConsoleLoggerModule() { - } + private ConsoleLoggerModule() {} - public static final ConsoleLoggerModule getSingleton() { + /** + * Static method to get single instance of class + * + * @return singleton instance of ConsoleLoggerModule + */ + public static ConsoleLoggerModule getSingleton() { - if (ConsoleLoggerModule.singleton == null) { - ConsoleLoggerModule.singleton = new ConsoleLoggerModule(); - } + if (ConsoleLoggerModule.singleton == null) { + ConsoleLoggerModule.singleton = new ConsoleLoggerModule(); + } - return ConsoleLoggerModule.singleton; - } + return ConsoleLoggerModule.singleton; + } - /** - * - * @throws FileNotFoundException - */ - public final void prepare() { + /** + * Following method performs the initialization + */ + public void prepare() { - logger.debug("ConsoleLoggerModule::prepare();"); + LOGGER.debug("ConsoleLoggerModule::prepare();"); - this.output = new PrintStream(System.out); - this.error = new PrintStream(System.err); - } + this.output = new PrintStream(System.out); + this.error = new PrintStream(System.err); + } - /** - * - */ - public final void unprepare() { + /** + * Following method performs the finalization + */ + public void unprepare() { - if (this.output != null) { + if (this.output != null) { - this.output.flush(); - this.output.close(); - } + this.output.flush(); + this.output.close(); + } - if (this.error != null) { + if (this.error != null) { - this.error.flush(); - this.error.close(); - } + this.error.flush(); + this.error.close(); + } - logger.debug("ConsoleLoggerModule::unprepare();"); - } + LOGGER.debug("ConsoleLoggerModule::unprepare();"); + } - /** - * - * @param value - */ - public final void printString(final String value) { - this.output.println(value); - } + /** + * Used to print a message + * + * @param value will be printed on console + */ + public void printString(final String value) { + this.output.println(value); + } - /** - * - * @param value - */ - public final void printErrorString(final String value) { - this.error.println(value); - } + /** + * Used to print a error message + * + * @param value will be printed on error console + */ + public void printErrorString(final String value) { + this.error.println(value); + } } diff --git a/module/src/main/java/com/iluwatar/module/FileLoggerModule.java b/module/src/main/java/com/iluwatar/module/FileLoggerModule.java index d1df062de..fae66191b 100644 --- a/module/src/main/java/com/iluwatar/module/FileLoggerModule.java +++ b/module/src/main/java/com/iluwatar/module/FileLoggerModule.java @@ -1,23 +1,20 @@ /** * The MIT License Copyright (c) 2016 Amit Dixit * - * 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 + * 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 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. + * 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.module; @@ -28,86 +25,92 @@ import java.io.PrintStream; import org.apache.log4j.Logger; /** - * The Module pattern can be considered a Creational pattern and a Structural - * pattern. It manages the creation and organization of other elements, and - * groups them as the structural pattern does. An object that applies this - * pattern can provide the equivalent of a namespace, providing the - * initialization and finalization process of a static class or a class with - * static members with cleaner, more concise syntax and semantics. + * The Module pattern can be considered a Creational pattern and a Structural pattern. It manages + * the creation and organization of other elements, and groups them as the structural pattern does. + * An object that applies this pattern can provide the equivalent of a namespace, providing the + * initialization and finalization process of a static class or a class with static members with + * cleaner, more concise syntax and semantics. *

- * The below example demonstrates a File logger module, which can print simple - * and error messages in two designated files + * The below example demonstrates a File logger module, which can print simple and error messages in + * two designated files */ public final class FileLoggerModule { - private static final Logger logger = Logger - .getLogger(FileLoggerModule.class); + private static final Logger LOGGER = Logger.getLogger(FileLoggerModule.class); - private static FileLoggerModule singleton = null; + private static FileLoggerModule singleton = null; - private static final String OUTPUT_FILE = "output.txt"; - private static final String ERROR_FILE = "error.txt"; + private static final String OUTPUT_FILE = "output.txt"; + private static final String ERROR_FILE = "error.txt"; - public PrintStream output = null; - public PrintStream error = null; + public PrintStream output = null; + public PrintStream error = null; - private FileLoggerModule() { - } + private FileLoggerModule() {} - public static final FileLoggerModule getSingleton() { + /** + * Static method to get single instance of class + * + * @return singleton instance of FileLoggerModule + */ + public static FileLoggerModule getSingleton() { - if (FileLoggerModule.singleton == null) { - FileLoggerModule.singleton = new FileLoggerModule(); - } + if (FileLoggerModule.singleton == null) { + FileLoggerModule.singleton = new FileLoggerModule(); + } - return FileLoggerModule.singleton; - } + return FileLoggerModule.singleton; + } - /** - * - * @throws FileNotFoundException - */ - public final void prepare() throws FileNotFoundException { + /** + * Following method performs the initialization + * + * @throws FileNotFoundException if program is not able to find log files (output.txt and + * error.txt) + */ + public void prepare() throws FileNotFoundException { - logger.debug("FileLoggerModule::prepare();"); + LOGGER.debug("FileLoggerModule::prepare();"); - this.output = new PrintStream(new FileOutputStream(OUTPUT_FILE)); - this.error = new PrintStream(new FileOutputStream(ERROR_FILE)); - } + this.output = new PrintStream(new FileOutputStream(OUTPUT_FILE)); + this.error = new PrintStream(new FileOutputStream(ERROR_FILE)); + } - /** - * - */ - public final void unprepare() { + /** + * Following method performs the finalization + */ + public void unprepare() { - if (this.output != null) { + if (this.output != null) { - this.output.flush(); - this.output.close(); - } + this.output.flush(); + this.output.close(); + } - if (this.error != null) { + if (this.error != null) { - this.error.flush(); - this.error.close(); - } + this.error.flush(); + this.error.close(); + } - logger.debug("FileLoggerModule::unprepare();"); - } + LOGGER.debug("FileLoggerModule::unprepare();"); + } - /** - * - * @param value - */ - public final void printString(final String value) { - this.output.println(value); - } + /** + * Used to print a message + * + * @param value will be printed in file + */ + public void printString(final String value) { + this.output.println(value); + } - /** - * - * @param value - */ - public final void printErrorString(final String value) { - this.error.println(value); - } + /** + * Used to print a error message + * + * @param value will be printed on error file + */ + public void printErrorString(final String value) { + this.error.println(value); + } } diff --git a/module/src/test/java/com/iluwatar/module/AppTest.java b/module/src/test/java/com/iluwatar/module/AppTest.java index 0f20b4959..21b32407d 100644 --- a/module/src/test/java/com/iluwatar/module/AppTest.java +++ b/module/src/test/java/com/iluwatar/module/AppTest.java @@ -29,9 +29,9 @@ import org.junit.Test; */ public final class AppTest { - @Test - public void test() throws FileNotFoundException { - final String[] args = {}; - App.main(args); - } + @Test + public void test() throws FileNotFoundException { + final String[] args = {}; + App.main(args); + } } diff --git a/module/src/test/java/com/iluwatar/module/FileLoggerModuleTest.java b/module/src/test/java/com/iluwatar/module/FileLoggerModuleTest.java new file mode 100644 index 000000000..ecefb307a --- /dev/null +++ b/module/src/test/java/com/iluwatar/module/FileLoggerModuleTest.java @@ -0,0 +1,182 @@ +/** + * The MIT License Copyright (c) 2016 Amit Dixit + * + * 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.module; + +import static org.junit.Assert.assertEquals; + +import java.io.BufferedReader; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; + +import org.apache.log4j.Logger; +import org.junit.Test; + +/** + * The Module pattern can be considered a Creational pattern and a Structural pattern. It manages + * the creation and organization of other elements, and groups them as the structural pattern does. + * An object that applies this pattern can provide the equivalent of a namespace, providing the + * initialization and finalization process of a static class or a class with static members with + * cleaner, more concise syntax and semantics. + *

+ * The below example demonstrates a JUnit test for testing two different modules: File Logger and + * Console Logger + */ +public final class FileLoggerModuleTest { + + private static final Logger LOGGER = Logger.getLogger(FileLoggerModuleTest.class); + + private static final String OUTPUT_FILE = "output.txt"; + private static final String ERROR_FILE = "error.txt"; + + private static final String MESSAGE = "MESSAGE"; + private static final String ERROR = "ERROR"; + + + /** + * This test verify that 'MESSAGE' is perfectly printed in output file + * + * @throws IOException if program is not able to find log files (output.txt and error.txt) + */ + @Test + public void positiveTestFileMessage() throws IOException { + + /* Get singletong instance of File Logger Module */ + final FileLoggerModule fileLoggerModule = FileLoggerModule.getSingleton(); + + /* Prepare the essential sub modules, to perform the sequence of jobs */ + fileLoggerModule.prepare(); + + /* Print 'Message' in file */ + fileLoggerModule.printString(MESSAGE); + + /* Test if 'Message' is printed in file */ + assertEquals(readFirstLine(OUTPUT_FILE), MESSAGE); + + /* Unprepare to cleanup the modules */ + fileLoggerModule.unprepare(); + } + + /** + * This test verify that nothing is printed in output file + * + * @throws IOException if program is not able to find log files (output.txt and error.txt) + */ + @Test + public void negativeTestFileMessage() throws IOException { + + /* Get singletong instance of File Logger Module */ + final FileLoggerModule fileLoggerModule = FileLoggerModule.getSingleton(); + + /* Prepare the essential sub modules, to perform the sequence of jobs */ + fileLoggerModule.prepare(); + + /* Test if nothing is printed in file */ + assertEquals(readFirstLine(OUTPUT_FILE), null); + + /* Unprepare to cleanup the modules */ + fileLoggerModule.unprepare(); + } + + /** + * This test verify that 'ERROR' is perfectly printed in error file + * + * @throws FileNotFoundException if program is not able to find log files (output.txt and + * error.txt) + */ + @Test + public void positiveTestFileErrorMessage() throws FileNotFoundException { + + /* Get singletong instance of File Logger Module */ + final FileLoggerModule fileLoggerModule = FileLoggerModule.getSingleton(); + + /* Prepare the essential sub modules, to perform the sequence of jobs */ + fileLoggerModule.prepare(); + + /* Print 'Error' in file */ + fileLoggerModule.printErrorString(ERROR); + + /* Test if 'Message' is printed in file */ + assertEquals(readFirstLine(ERROR_FILE), ERROR); + + /* Unprepare to cleanup the modules */ + fileLoggerModule.unprepare(); + } + + /** + * This test verify that nothing is printed in error file + * + * @throws FileNotFoundException if program is not able to find log files (output.txt and + * error.txt) + */ + @Test + public void negativeTestFileErrorMessage() throws FileNotFoundException { + + /* Get singletong instance of File Logger Module */ + final FileLoggerModule fileLoggerModule = FileLoggerModule.getSingleton(); + + /* Prepare the essential sub modules, to perform the sequence of jobs */ + fileLoggerModule.prepare(); + + /* Test if nothing is printed in file */ + assertEquals(readFirstLine(ERROR_FILE), null); + + /* Unprepare to cleanup the modules */ + fileLoggerModule.unprepare(); + } + + /** + * Utility method to read first line of a file + * + * @param file as file name to be read + * @return a string value as first line in file + */ + private static final String readFirstLine(final String file) { + + String firstLine = null; + BufferedReader bufferedReader = null; + try { + + /* Create a buffered reader */ + bufferedReader = new BufferedReader(new FileReader(file)); + + while (bufferedReader.ready()) { + + /* Read the line */ + firstLine = bufferedReader.readLine(); + } + + LOGGER.info("ModuleTest::readFirstLine() : firstLine : " + firstLine); + + } catch (final IOException e) { + LOGGER.error("ModuleTest::readFirstLine()", e); + } finally { + + if (bufferedReader != null) { + try { + bufferedReader.close(); + } catch (final IOException e) { + LOGGER.error("ModuleTest::readFirstLine()", e); + } + } + } + + return firstLine; + } +} diff --git a/module/src/test/java/com/iluwatar/module/ModuleTest.java b/module/src/test/java/com/iluwatar/module/ModuleTest.java deleted file mode 100644 index cf3435850..000000000 --- a/module/src/test/java/com/iluwatar/module/ModuleTest.java +++ /dev/null @@ -1,315 +0,0 @@ -/** - * The MIT License Copyright (c) 2016 Amit Dixit - * - * 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.module; - -import static org.junit.Assert.assertEquals; - -import java.io.BufferedReader; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; -import java.io.InputStreamReader; - -import org.apache.log4j.Logger; -import org.junit.Test; - -/** - * The Module pattern can be considered a Creational pattern and a Structural - * pattern. It manages the creation and organization of other elements, and - * groups them as the structural pattern does. An object that applies this - * pattern can provide the equivalent of a namespace, providing the - * initialization and finalization process of a static class or a class with - * static members with cleaner, more concise syntax and semantics. - *

- * The below example demonstrates a JUnit test for testing two different - * modules: File Logger and Console Logger - */ -public class ModuleTest { - - private static final Logger logger = Logger.getLogger(ModuleTest.class); - - private static final String OUTPUT_FILE = "output.txt"; - private static final String ERROR_FILE = "error.txt"; - - private static final String MESSAGE = "MESSAGE"; - private static final String ERROR = "ERROR"; - - /** - * This test verify that 'MESSAGE' is perfectly printed in output file - * - * @throws IOException - */ - @Test - public void positiveTestConsoleMessage() throws IOException { - - /* Prepare the essential sub modules, to perform the sequence of jobs */ - final FileLoggerModule fileLoggerModule = FileLoggerModule - .getSingleton(); - - /* Prepare the essential sub modules, to perform the sequence of jobs */ - fileLoggerModule.prepare(); - - /* Print 'Message' in file */ - fileLoggerModule.printString(MESSAGE); - - /* Test if 'Message' is printed on console */ - assertEquals(readFirstLine(), MESSAGE); - - /* Unprepare to cleanup the modules */ - fileLoggerModule.unprepare(); - } - - /** - * This test verify that nothing is printed in output file - * - * @throws IOException - */ - @Test - public void negativeTestConsoleMessage() throws IOException { - - /* Prepare the essential sub modules, to perform the sequence of jobs */ - final ConsoleLoggerModule consoleLoggerModule = ConsoleLoggerModule - .getSingleton(); - - /* Prepare the essential sub modules, to perform the sequence of jobs */ - consoleLoggerModule.prepare(); - - /* Test if nothing is printed on console */ - assertEquals(readFirstLine(), null); - - /* Unprepare to cleanup the modules */ - consoleLoggerModule.unprepare(); - } - - /** - * This test verify that 'ERROR' is perfectly printed in error file - * - * @throws FileNotFoundException - */ - @Test - public void positiveTestConsoleErrorMessage() { - - /* Prepare the essential sub modules, to perform the sequence of jobs */ - final ConsoleLoggerModule consoleLoggerModule = ConsoleLoggerModule - .getSingleton(); - - /* Prepare the essential sub modules, to perform the sequence of jobs */ - consoleLoggerModule.prepare(); - - /* Print 'Error' in file */ - consoleLoggerModule.printErrorString(ERROR); - - /* Test if 'Message' is printed on console */ - assertEquals(readFirstLine(), ERROR); - - /* Unprepare to cleanup the modules */ - consoleLoggerModule.unprepare(); - } - - /** - * This test verify that nothing is printed in error file - * - * @throws FileNotFoundException - */ - @Test - public void negativeTestConsoleErrorMessage() { - - /* Prepare the essential sub modules, to perform the sequence of jobs */ - final ConsoleLoggerModule consoleLoggerModule = ConsoleLoggerModule - .getSingleton(); - - /* Prepare the essential sub modules, to perform the sequence of jobs */ - consoleLoggerModule.prepare(); - - /* Test if nothing is printed on console */ - assertEquals(readFirstLine(), null); - - /* Unprepare to cleanup the modules */ - consoleLoggerModule.unprepare(); - } - - /** - * This test verify that 'MESSAGE' is perfectly printed in output file - * - * @throws IOException - */ - @Test - public void positiveTestFileMessage() throws IOException { - - /* Prepare the essential sub modules, to perform the sequence of jobs */ - final FileLoggerModule fileLoggerModule = FileLoggerModule - .getSingleton(); - - /* Prepare the essential sub modules, to perform the sequence of jobs */ - fileLoggerModule.prepare(); - - /* Print 'Message' in file */ - fileLoggerModule.printString(MESSAGE); - - /* Test if 'Message' is printed in file */ - assertEquals(readFirstLine(OUTPUT_FILE), MESSAGE); - - /* Unprepare to cleanup the modules */ - fileLoggerModule.unprepare(); - } - - /** - * This test verify that nothing is printed in output file - * - * @throws IOException - */ - @Test - public void negativeTestFileMessage() throws IOException { - - /* Prepare the essential sub modules, to perform the sequence of jobs */ - final FileLoggerModule fileLoggerModule = FileLoggerModule - .getSingleton(); - - /* Prepare the essential sub modules, to perform the sequence of jobs */ - fileLoggerModule.prepare(); - - /* Test if nothing is printed in file */ - assertEquals(readFirstLine(OUTPUT_FILE), null); - - /* Unprepare to cleanup the modules */ - fileLoggerModule.unprepare(); - } - - /** - * This test verify that 'ERROR' is perfectly printed in error file - * - * @throws FileNotFoundException - */ - @Test - public void positiveTestFileErrorMessage() throws FileNotFoundException { - - /* Prepare the essential sub modules, to perform the sequence of jobs */ - final FileLoggerModule fileLoggerModule = FileLoggerModule - .getSingleton(); - - /* Prepare the essential sub modules, to perform the sequence of jobs */ - fileLoggerModule.prepare(); - - /* Print 'Error' in file */ - fileLoggerModule.printErrorString(ERROR); - - /* Test if 'Message' is printed in file */ - assertEquals(readFirstLine(ERROR_FILE), ERROR); - - /* Unprepare to cleanup the modules */ - fileLoggerModule.unprepare(); - } - - /** - * This test verify that nothing is printed in error file - * - * @throws FileNotFoundException - */ - @Test - public void negativeTestFileErrorMessage() throws FileNotFoundException { - - /* Prepare the essential sub modules, to perform the sequence of jobs */ - final FileLoggerModule fileLoggerModule = FileLoggerModule - .getSingleton(); - - /* Prepare the essential sub modules, to perform the sequence of jobs */ - fileLoggerModule.prepare(); - - /* Test if nothing is printed in file */ - assertEquals(readFirstLine(ERROR_FILE), null); - - /* Unprepare to cleanup the modules */ - fileLoggerModule.unprepare(); - } - - /** - * Utility method to read first line of a file - * - * @param file - * @return - */ - private static final String readFirstLine() { - - String firstLine = null; - BufferedReader bufferedReader = null; - try { - - /* Create a buffered reader */ - bufferedReader = new BufferedReader( - new InputStreamReader(System.in)); - - /* Read the line */ - firstLine = bufferedReader.readLine(); - - logger.info("ModuleTest::readFirstLineFromConsole() : firstLine : " - + firstLine); - - } catch (final IOException e) { - logger.error("ModuleTest::readFirstLineFromConsole()", e); - } finally { - - if (bufferedReader != null) { - try { - bufferedReader.close(); - } catch (final IOException e) { - logger.error("ModuleTest::readFirstLineFromConsole()", e); - } - } - } - - return firstLine; - } - - /** - * Utility method to read first line of a file - * - * @param file - * @return - */ - private static final String readFirstLine(final String file) { - - String firstLine = null; - BufferedReader bufferedReader = null; - try { - - /* Create a buffered reader */ - bufferedReader = new BufferedReader(new FileReader(file)); - - /* Read the line */ - firstLine = bufferedReader.readLine(); - - logger.info("ModuleTest::readFirstLine() : firstLine : " - + firstLine); - - } catch (final IOException e) { - logger.error("ModuleTest::readFirstLine()", e); - } finally { - - if (bufferedReader != null) { - try { - bufferedReader.close(); - } catch (final IOException e) { - logger.error("ModuleTest::readFirstLine()", e); - } - } - } - - return firstLine; - } -} From 27d6d500bcc5cf31f59f2f6efe26271c30462b3a Mon Sep 17 00:00:00 2001 From: daniel-bryla Date: Fri, 28 Oct 2016 09:35:59 +0200 Subject: [PATCH 13/37] #502 Reverted changes in composite example, due to nature of this example using logger isn't good idea --- .../src/main/java/com/iluwatar/composite/Letter.java | 9 ++------- .../src/main/java/com/iluwatar/composite/Sentence.java | 9 ++------- composite/src/main/java/com/iluwatar/composite/Word.java | 9 ++------- 3 files changed, 6 insertions(+), 21 deletions(-) diff --git a/composite/src/main/java/com/iluwatar/composite/Letter.java b/composite/src/main/java/com/iluwatar/composite/Letter.java index c8a6ccfce..088cdd44c 100644 --- a/composite/src/main/java/com/iluwatar/composite/Letter.java +++ b/composite/src/main/java/com/iluwatar/composite/Letter.java @@ -22,18 +22,13 @@ */ package com.iluwatar.composite; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - /** - * + * * Letter * */ public class Letter extends LetterComposite { - private static final Logger LOGGER = LoggerFactory.getLogger(Letter.class); - private char c; public Letter(char c) { @@ -42,7 +37,7 @@ public class Letter extends LetterComposite { @Override protected void printThisBefore() { - LOGGER.info(String.valueOf(c)); + System.out.print(c); } @Override diff --git a/composite/src/main/java/com/iluwatar/composite/Sentence.java b/composite/src/main/java/com/iluwatar/composite/Sentence.java index ca8698f4f..bccf6c751 100644 --- a/composite/src/main/java/com/iluwatar/composite/Sentence.java +++ b/composite/src/main/java/com/iluwatar/composite/Sentence.java @@ -22,20 +22,15 @@ */ package com.iluwatar.composite; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.util.List; /** - * + * * Sentence * */ public class Sentence extends LetterComposite { - private static final Logger LOGGER = LoggerFactory.getLogger(Sentence.class); - /** * Constructor */ @@ -52,6 +47,6 @@ public class Sentence extends LetterComposite { @Override protected void printThisAfter() { - LOGGER.info("."); + System.out.print("."); } } diff --git a/composite/src/main/java/com/iluwatar/composite/Word.java b/composite/src/main/java/com/iluwatar/composite/Word.java index 4e5cfb31d..0174dc88a 100644 --- a/composite/src/main/java/com/iluwatar/composite/Word.java +++ b/composite/src/main/java/com/iluwatar/composite/Word.java @@ -22,20 +22,15 @@ */ package com.iluwatar.composite; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.util.List; /** - * + * * Word * */ public class Word extends LetterComposite { - private static final Logger LOGGER = LoggerFactory.getLogger(Word.class); - /** * Constructor */ @@ -47,7 +42,7 @@ public class Word extends LetterComposite { @Override protected void printThisBefore() { - LOGGER.info(" "); + System.out.print(" "); } @Override From e138163c4f1688678dc8bc43e9683b142d534fe7 Mon Sep 17 00:00:00 2001 From: daniel-bryla Date: Fri, 4 Nov 2016 11:47:06 +0100 Subject: [PATCH 14/37] #502 Adjusted tests for logger introduction --- .../com/iluwatar/decorator/TrollTest.java | 61 ++++++----- .../delegation/simple/DelegateTest.java | 55 ++++++++-- .../injection/AdvancedWizardTest.java | 30 ++++-- .../dependency/injection/GuiceWizardTest.java | 38 ++++--- .../injection/SimpleWizardTest.java | 25 ++++- .../dependency/injection/StdOutTest.java | 75 ------------- .../injection/utils/InMemoryAppender.java | 54 ++++++++++ .../doublechecked/locking/InventoryTest.java | 71 ++++++------ .../doubledispatch/CollisionTest.java | 54 +--------- .../event/aggregator/KingJoffreyTest.java | 67 +++++++----- .../facade/DwarvenGoldmineFacadeTest.java | 98 +++++++++-------- .../front/controller/CommandTest.java | 27 +++-- .../front/controller/FrontControllerTest.java | 27 +++-- .../iluwatar/front/controller/StdOutTest.java | 76 ------------- .../iluwatar/front/controller/ViewTest.java | 29 +++-- .../controller/utils/InMemoryAppender.java | 54 ++++++++++ .../hexagonal/service/ConsoleLottery.java | 1 - .../com/iluwatar/layers/CakeViewImplTest.java | 49 ++++++++- .../java/com/iluwatar/layers/StdOutTest.java | 78 -------------- .../iluwatar/mediator/PartyMemberTest.java | 84 ++++++++------- .../model/view/controller/GiantViewTest.java | 60 ++++++----- .../com/iluwatar/nullobject/NullNodeTest.java | 11 +- .../com/iluwatar/nullobject/StdOutTest.java | 76 ------------- .../com/iluwatar/nullobject/TreeTest.java | 68 +++++++++--- .../com/iluwatar/observer/StdOutTest.java | 76 ------------- .../observer/WeatherObserverTest.java | 29 +++-- .../com/iluwatar/observer/WeatherTest.java | 29 +++-- .../observer/generic/GWeatherTest.java | 37 ++++--- .../observer/generic/ObserverTest.java | 31 ++++-- .../observer/utils/InMemoryAppender.java | 58 ++++++++++ .../iluwatar/poison/pill/ConsumerTest.java | 54 ++++++++-- .../com/iluwatar/poison/pill/StdOutTest.java | 75 ------------- .../privateclassdata/ImmutableStewTest.java | 39 ++++--- .../iluwatar/privateclassdata/StdOutTest.java | 75 ------------- .../iluwatar/privateclassdata/StewTest.java | 27 +++-- .../utils/InMemoryAppender.java | 53 +++++++++ .../producer/consumer/ConsumerTest.java | 12 +-- .../producer/consumer/StdOutTest.java | 75 ------------- .../java/com/iluwatar/proxy/StdOutTest.java | 75 ------------- .../iluwatar/proxy/WizardTowerProxyTest.java | 35 ++++-- .../com/iluwatar/proxy/WizardTowerTest.java | 35 ++++-- .../proxy/utils/InMemoryAppender.java | 58 ++++++++++ .../writer/lock/ReaderAndWriterTest.java | 44 +++++--- .../reader/writer/lock/ReaderTest.java | 38 ++++--- .../reader/writer/lock/StdOutTest.java | 76 ------------- .../reader/writer/lock/WriterTest.java | 37 ++++--- .../writer/lock/utils/InMemoryAppender.java | 54 ++++++++++ .../is/initialization/ClosableTest.java | 56 ++++++++-- .../is/initialization/StdOutTest.java | 75 ------------- .../java/com/iluwatar/state/MammothTest.java | 76 +++++++------ .../strategy/DragonSlayingStrategyTest.java | 76 +++++++------ .../templatemethod/StealingMethodTest.java | 102 ++++++++++-------- .../java/com/iluwatar/twin/BallItemTest.java | 66 ++++++++++-- .../java/com/iluwatar/twin/StdOutTest.java | 75 ------------- .../java/com/iluwatar/visitor/StdOutTest.java | 75 ------------- .../com/iluwatar/visitor/VisitorTest.java | 58 ++++++++-- 56 files changed, 1447 insertions(+), 1602 deletions(-) delete mode 100644 dependency-injection/src/test/java/com/iluwatar/dependency/injection/StdOutTest.java create mode 100644 dependency-injection/src/test/java/com/iluwatar/dependency/injection/utils/InMemoryAppender.java delete mode 100644 front-controller/src/test/java/com/iluwatar/front/controller/StdOutTest.java create mode 100644 front-controller/src/test/java/com/iluwatar/front/controller/utils/InMemoryAppender.java delete mode 100644 layers/src/test/java/com/iluwatar/layers/StdOutTest.java delete mode 100644 null-object/src/test/java/com/iluwatar/nullobject/StdOutTest.java delete mode 100644 observer/src/test/java/com/iluwatar/observer/StdOutTest.java create mode 100644 observer/src/test/java/com/iluwatar/observer/utils/InMemoryAppender.java delete mode 100644 poison-pill/src/test/java/com/iluwatar/poison/pill/StdOutTest.java delete mode 100644 private-class-data/src/test/java/com/iluwatar/privateclassdata/StdOutTest.java create mode 100644 private-class-data/src/test/java/com/iluwatar/privateclassdata/utils/InMemoryAppender.java delete mode 100644 producer-consumer/src/test/java/com/iluwatar/producer/consumer/StdOutTest.java delete mode 100644 proxy/src/test/java/com/iluwatar/proxy/StdOutTest.java create mode 100644 proxy/src/test/java/com/iluwatar/proxy/utils/InMemoryAppender.java delete mode 100644 reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/StdOutTest.java create mode 100644 reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/utils/InMemoryAppender.java delete mode 100644 resource-acquisition-is-initialization/src/test/java/com/iluwatar/resource/acquisition/is/initialization/StdOutTest.java delete mode 100644 twin/src/test/java/com/iluwatar/twin/StdOutTest.java delete mode 100644 visitor/src/test/java/com/iluwatar/visitor/StdOutTest.java diff --git a/decorator/src/test/java/com/iluwatar/decorator/TrollTest.java b/decorator/src/test/java/com/iluwatar/decorator/TrollTest.java index 84b0f6d20..652c1fcdc 100644 --- a/decorator/src/test/java/com/iluwatar/decorator/TrollTest.java +++ b/decorator/src/test/java/com/iluwatar/decorator/TrollTest.java @@ -22,16 +22,18 @@ */ package com.iluwatar.decorator; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.AppenderBase; import org.junit.After; import org.junit.Before; import org.junit.Test; +import org.slf4j.LoggerFactory; -import java.io.PrintStream; +import java.util.LinkedList; +import java.util.List; import static org.junit.Assert.assertEquals; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.*; -import static org.mockito.internal.verification.VerificationModeFactory.times; /** * Date: 12/7/15 - 7:26 PM @@ -40,31 +42,16 @@ import static org.mockito.internal.verification.VerificationModeFactory.times; */ public class TrollTest { - /** - * The mocked standard out stream, required since the actions don't have any influence on other - * objects, except for writing to the std-out using {@link System#out} - */ - private final PrintStream stdOutMock = mock(PrintStream.class); + private InMemoryAppender appender; - /** - * Keep the original std-out so it can be restored after the test - */ - private final PrintStream stdOutOrig = System.out; - - /** - * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test - */ @Before public void setUp() { - System.setOut(this.stdOutMock); + appender = new InMemoryAppender(Troll.class); } - /** - * Removed the mocked std-out {@link PrintStream} again from the {@link System} class - */ @After public void tearDown() { - System.setOut(this.stdOutOrig); + appender.stop(); } @Test @@ -73,12 +60,34 @@ public class TrollTest { assertEquals(10, troll.getAttackPower()); troll.attack(); - verify(this.stdOutMock, times(1)).println(eq("The troll swings at you with a club!")); + assertEquals("The troll swings at you with a club!", appender.getLastMessage()); troll.fleeBattle(); - verify(this.stdOutMock, times(1)).println(eq("The troll shrieks in horror and runs away!")); + assertEquals("The troll shrieks in horror and runs away!", appender.getLastMessage()); - verifyNoMoreInteractions(this.stdOutMock); + assertEquals(2, appender.getLogSize()); } -} \ No newline at end of file + private class InMemoryAppender extends AppenderBase { + + private List log = new LinkedList<>(); + + public InMemoryAppender(Class clazz) { + ((Logger) LoggerFactory.getLogger(clazz)).addAppender(this); + start(); + } + + @Override + protected void append(ILoggingEvent eventObject) { + log.add(eventObject); + } + + public String getLastMessage() { + return log.get(log.size() - 1).getMessage(); + } + + public int getLogSize() { + return log.size(); + } + } +} diff --git a/delegation/src/test/java/com/iluwatar/delegation/simple/DelegateTest.java b/delegation/src/test/java/com/iluwatar/delegation/simple/DelegateTest.java index 6a19c9a1a..c1f32a8e0 100644 --- a/delegation/src/test/java/com/iluwatar/delegation/simple/DelegateTest.java +++ b/delegation/src/test/java/com/iluwatar/delegation/simple/DelegateTest.java @@ -22,28 +22,44 @@ */ package com.iluwatar.delegation.simple; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.AppenderBase; import com.iluwatar.delegation.simple.printers.CanonPrinter; import com.iluwatar.delegation.simple.printers.EpsonPrinter; import com.iluwatar.delegation.simple.printers.HpPrinter; -import org.junit.Rule; +import org.junit.After; +import org.junit.Before; import org.junit.Test; -import org.junit.contrib.java.lang.system.SystemOutRule; +import org.slf4j.LoggerFactory; + +import java.util.LinkedList; +import java.util.List; import static org.junit.Assert.assertEquals; public class DelegateTest { - private static final String MESSAGE = "Test Message Printed"; + private InMemoryAppender appender; - @Rule - public final SystemOutRule systemOutRule = new SystemOutRule().enableLog(); + @Before + public void setUp() { + appender = new InMemoryAppender(); + } + + @After + public void tearDown() { + appender.stop(); + } + + private static final String MESSAGE = "Test Message Printed"; @Test public void testCanonPrinter() throws Exception { PrinterController printerController = new PrinterController(new CanonPrinter()); printerController.print(MESSAGE); - assertEquals("Canon Printer : Test Message Printed", systemOutRule.getLog()); + assertEquals("Canon Printer : Test Message Printed", appender.getLastMessage()); } @Test @@ -51,7 +67,7 @@ public class DelegateTest { PrinterController printerController = new PrinterController(new HpPrinter()); printerController.print(MESSAGE); - assertEquals("HP Printer : Test Message Printed", systemOutRule.getLog()); + assertEquals("HP Printer : Test Message Printed", appender.getLastMessage()); } @Test @@ -59,7 +75,30 @@ public class DelegateTest { PrinterController printerController = new PrinterController(new EpsonPrinter()); printerController.print(MESSAGE); - assertEquals("Epson Printer : Test Message Printed", systemOutRule.getLog()); + assertEquals("Epson Printer : Test Message Printed", appender.getLastMessage()); + } + + private class InMemoryAppender extends AppenderBase { + + private List log = new LinkedList<>(); + + public InMemoryAppender() { + ((Logger) LoggerFactory.getLogger("root")).addAppender(this); + start(); + } + + @Override + protected void append(ILoggingEvent eventObject) { + log.add(eventObject); + } + + public String getLastMessage() { + return log.get(log.size() - 1).getFormattedMessage(); + } + + public int getLogSize() { + return log.size(); + } } } diff --git a/dependency-injection/src/test/java/com/iluwatar/dependency/injection/AdvancedWizardTest.java b/dependency-injection/src/test/java/com/iluwatar/dependency/injection/AdvancedWizardTest.java index d1f5e574c..a0578626f 100644 --- a/dependency-injection/src/test/java/com/iluwatar/dependency/injection/AdvancedWizardTest.java +++ b/dependency-injection/src/test/java/com/iluwatar/dependency/injection/AdvancedWizardTest.java @@ -22,18 +22,31 @@ */ package com.iluwatar.dependency.injection; +import com.iluwatar.dependency.injection.utils.InMemoryAppender; +import org.junit.After; +import org.junit.Before; import org.junit.Test; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.junit.Assert.assertEquals; /** * Date: 12/10/15 - 8:40 PM * * @author Jeroen Meulemeester */ -public class AdvancedWizardTest extends StdOutTest { +public class AdvancedWizardTest { + + private InMemoryAppender appender; + + @Before + public void setUp() { + appender = new InMemoryAppender(Tobacco.class); + } + + @After + public void tearDown() { + appender.stop(); + } /** * Test if the {@link AdvancedWizard} smokes whatever instance of {@link Tobacco} is passed to him @@ -51,12 +64,13 @@ public class AdvancedWizardTest extends StdOutTest { advancedWizard.smoke(); // Verify if the wizard is smoking the correct tobacco ... - verify(getStdOutMock(), times(1)).println("AdvancedWizard smoking " + tobacco.getClass().getSimpleName()); + assertEquals("AdvancedWizard smoking " + tobacco.getClass().getSimpleName(), appender.getLastMessage()); - // ... and nothing else is happening. - verifyNoMoreInteractions(getStdOutMock()); } + // ... and nothing else is happening. + assertEquals(tobaccos.length, appender.getLogSize()); + } -} \ No newline at end of file +} diff --git a/dependency-injection/src/test/java/com/iluwatar/dependency/injection/GuiceWizardTest.java b/dependency-injection/src/test/java/com/iluwatar/dependency/injection/GuiceWizardTest.java index 1d3d679df..811773678 100644 --- a/dependency-injection/src/test/java/com/iluwatar/dependency/injection/GuiceWizardTest.java +++ b/dependency-injection/src/test/java/com/iluwatar/dependency/injection/GuiceWizardTest.java @@ -25,19 +25,31 @@ package com.iluwatar.dependency.injection; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; - +import com.iluwatar.dependency.injection.utils.InMemoryAppender; +import org.junit.After; +import org.junit.Before; import org.junit.Test; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.junit.Assert.assertEquals; /** * Date: 12/10/15 - 8:57 PM * * @author Jeroen Meulemeester */ -public class GuiceWizardTest extends StdOutTest { +public class GuiceWizardTest { + + private InMemoryAppender appender; + + @Before + public void setUp() { + appender = new InMemoryAppender(Tobacco.class); + } + + @After + public void tearDown() { + appender.stop(); + } /** * Test if the {@link GuiceWizard} smokes whatever instance of {@link Tobacco} is passed to him @@ -55,12 +67,11 @@ public class GuiceWizardTest extends StdOutTest { guiceWizard.smoke(); // Verify if the wizard is smoking the correct tobacco ... - verify(getStdOutMock(), times(1)).println("GuiceWizard smoking " + tobacco.getClass().getSimpleName()); - - // ... and nothing else is happening. - verifyNoMoreInteractions(getStdOutMock()); + assertEquals("GuiceWizard smoking " + tobacco.getClass().getSimpleName(), appender.getLastMessage()); } + // ... and nothing else is happening. + assertEquals(tobaccos.length, appender.getLogSize()); } /** @@ -89,12 +100,11 @@ public class GuiceWizardTest extends StdOutTest { guiceWizard.smoke(); // Verify if the wizard is smoking the correct tobacco ... - verify(getStdOutMock(), times(1)).println("GuiceWizard smoking " + tobaccoClass.getSimpleName()); - - // ... and nothing else is happening. - verifyNoMoreInteractions(getStdOutMock()); + assertEquals("GuiceWizard smoking " + tobaccoClass.getSimpleName(), appender.getLastMessage()); } + // ... and nothing else is happening. + assertEquals(tobaccos.length, appender.getLogSize()); } -} \ No newline at end of file +} diff --git a/dependency-injection/src/test/java/com/iluwatar/dependency/injection/SimpleWizardTest.java b/dependency-injection/src/test/java/com/iluwatar/dependency/injection/SimpleWizardTest.java index e5a856e8d..cda3eac47 100644 --- a/dependency-injection/src/test/java/com/iluwatar/dependency/injection/SimpleWizardTest.java +++ b/dependency-injection/src/test/java/com/iluwatar/dependency/injection/SimpleWizardTest.java @@ -22,16 +22,31 @@ */ package com.iluwatar.dependency.injection; +import com.iluwatar.dependency.injection.utils.InMemoryAppender; +import org.junit.After; +import org.junit.Before; import org.junit.Test; -import static org.mockito.Mockito.*; +import static org.junit.Assert.assertEquals; /** * Date: 12/10/15 - 8:26 PM * * @author Jeroen Meulemeester */ -public class SimpleWizardTest extends StdOutTest { +public class SimpleWizardTest { + + private InMemoryAppender appender; + + @Before + public void setUp() { + appender = new InMemoryAppender(Tobacco.class); + } + + @After + public void tearDown() { + appender.stop(); + } /** * Test if the {@link SimpleWizard} does the only thing it can do: Smoke it's {@link @@ -41,8 +56,8 @@ public class SimpleWizardTest extends StdOutTest { public void testSmoke() { final SimpleWizard simpleWizard = new SimpleWizard(); simpleWizard.smoke(); - verify(getStdOutMock(), times(1)).println("SimpleWizard smoking OldTobyTobacco"); - verifyNoMoreInteractions(getStdOutMock()); + assertEquals("SimpleWizard smoking OldTobyTobacco", appender.getLastMessage()); + assertEquals(1, appender.getLogSize()); } -} \ No newline at end of file +} diff --git a/dependency-injection/src/test/java/com/iluwatar/dependency/injection/StdOutTest.java b/dependency-injection/src/test/java/com/iluwatar/dependency/injection/StdOutTest.java deleted file mode 100644 index 57272c511..000000000 --- a/dependency-injection/src/test/java/com/iluwatar/dependency/injection/StdOutTest.java +++ /dev/null @@ -1,75 +0,0 @@ -/** - * 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.dependency.injection; - -import org.junit.After; -import org.junit.Before; - -import java.io.PrintStream; - -import static org.mockito.Mockito.mock; - -/** - * Date: 12/10/15 - 8:37 PM - * - * @author Jeroen Meulemeester - */ -public abstract class StdOutTest { - - /** - * The mocked standard out {@link PrintStream}, required since the actions of the wizard don't - * have any influence on any other accessible objects, except for writing to std-out using {@link - * System#out} - */ - private final PrintStream stdOutMock = mock(PrintStream.class); - - /** - * Keep the original std-out so it can be restored after the test - */ - private final PrintStream stdOutOrig = System.out; - - /** - * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test - */ - @Before - public void setUp() { - System.setOut(this.stdOutMock); - } - - /** - * Removed the mocked std-out {@link PrintStream} again from the {@link System} class - */ - @After - public void tearDown() { - System.setOut(this.stdOutOrig); - } - - /** - * Get the mocked stdOut {@link PrintStream} - * - * @return The stdOut print stream mock, renewed before each test - */ - final PrintStream getStdOutMock() { - return this.stdOutMock; - } -} diff --git a/dependency-injection/src/test/java/com/iluwatar/dependency/injection/utils/InMemoryAppender.java b/dependency-injection/src/test/java/com/iluwatar/dependency/injection/utils/InMemoryAppender.java new file mode 100644 index 000000000..b4c60b8aa --- /dev/null +++ b/dependency-injection/src/test/java/com/iluwatar/dependency/injection/utils/InMemoryAppender.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.dependency.injection.utils; + +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.AppenderBase; +import org.slf4j.LoggerFactory; + +import java.util.LinkedList; +import java.util.List; + +public class InMemoryAppender extends AppenderBase { + + private List log = new LinkedList<>(); + + public InMemoryAppender(Class clazz) { + ((Logger) LoggerFactory.getLogger(clazz)).addAppender(this); + start(); + } + + @Override + protected void append(ILoggingEvent eventObject) { + log.add(eventObject); + } + + public String getLastMessage() { + return log.get(log.size() - 1).getFormattedMessage(); + } + + public int getLogSize() { + return log.size(); + } +} diff --git a/double-checked-locking/src/test/java/com/iluwatar/doublechecked/locking/InventoryTest.java b/double-checked-locking/src/test/java/com/iluwatar/doublechecked/locking/InventoryTest.java index 485c9573e..9f5f608b0 100644 --- a/double-checked-locking/src/test/java/com/iluwatar/doublechecked/locking/InventoryTest.java +++ b/double-checked-locking/src/test/java/com/iluwatar/doublechecked/locking/InventoryTest.java @@ -22,24 +22,23 @@ */ package com.iluwatar.doublechecked.locking; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.AppenderBase; import org.junit.After; import org.junit.Before; import org.junit.Test; -import org.mockito.ArgumentCaptor; +import org.slf4j.LoggerFactory; -import java.io.PrintStream; +import java.util.LinkedList; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; -import static junit.framework.Assert.assertTrue; import static junit.framework.TestCase.assertEquals; import static org.junit.Assert.assertNotNull; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.junit.Assert.assertTrue; /** * Date: 12/10/15 - 9:34 PM @@ -48,31 +47,16 @@ import static org.mockito.Mockito.verifyNoMoreInteractions; */ public class InventoryTest { - /** - * The mocked standard out {@link PrintStream}, used to verify a steady increasing size of the - * {@link Inventory} while adding items from multiple threads concurrently - */ - private final PrintStream stdOutMock = mock(PrintStream.class); + private InMemoryAppender appender; - /** - * Keep the original std-out so it can be restored after the test - */ - private final PrintStream stdOutOrig = System.out; - - /** - * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test - */ @Before public void setUp() { - System.setOut(this.stdOutMock); + appender = new InMemoryAppender(Inventory.class); } - /** - * Removed the mocked std-out {@link PrintStream} again from the {@link System} class - */ @After public void tearDown() { - System.setOut(this.stdOutOrig); + appender.stop(); } /** @@ -112,21 +96,32 @@ public class InventoryTest { assertNotNull(items); assertEquals(INVENTORY_SIZE, items.size()); - // Capture all stdOut messages ... - final ArgumentCaptor stdOutCaptor = ArgumentCaptor.forClass(String.class); - verify(this.stdOutMock, times(INVENTORY_SIZE)).println(stdOutCaptor.capture()); - - // ... verify if we got all 1000 - final List values = stdOutCaptor.getAllValues(); - assertEquals(INVENTORY_SIZE, values.size()); + assertEquals(INVENTORY_SIZE, appender.getLogSize()); // ... and check if the inventory size is increasing continuously - for (int i = 0; i < values.size(); i++) { - assertNotNull(values.get(i)); - assertTrue(values.get(i).contains("items.size()=" + (i + 1))); + for (int i = 0; i < items.size(); i++) { + assertTrue(appender.log.get(i).getFormattedMessage().contains("items.size()=" + (i + 1))); } - - verifyNoMoreInteractions(this.stdOutMock); } -} \ No newline at end of file + + + private class InMemoryAppender extends AppenderBase { + private List log = new LinkedList<>(); + + public InMemoryAppender(Class clazz) { + ((Logger) LoggerFactory.getLogger(clazz)).addAppender(this); + start(); + } + + @Override + protected void append(ILoggingEvent eventObject) { + log.add(eventObject); + } + + public int getLogSize() { + return log.size(); + } + } + +} diff --git a/double-dispatch/src/test/java/com/iluwatar/doubledispatch/CollisionTest.java b/double-dispatch/src/test/java/com/iluwatar/doubledispatch/CollisionTest.java index dbc8fc55e..6576d6d2f 100644 --- a/double-dispatch/src/test/java/com/iluwatar/doubledispatch/CollisionTest.java +++ b/double-dispatch/src/test/java/com/iluwatar/doubledispatch/CollisionTest.java @@ -22,17 +22,9 @@ */ package com.iluwatar.doubledispatch; -import org.junit.After; -import org.junit.Before; - -import java.io.PrintStream; import java.util.Objects; import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; /** * Date: 12/10/15 - 8:37 PM @@ -41,43 +33,6 @@ import static org.mockito.Mockito.verifyNoMoreInteractions; */ public abstract class CollisionTest { - /** - * The mocked standard out {@link PrintStream}, required if some of the actions on the tested - * object don't have a direct influence on any other accessible objects, except for writing to - * std-out using {@link System#out} - */ - private final PrintStream stdOutMock = mock(PrintStream.class); - - /** - * Keep the original std-out so it can be restored after the test - */ - private final PrintStream stdOutOrig = System.out; - - /** - * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test - */ - @Before - public void setUp() { - System.setOut(this.stdOutMock); - } - - /** - * Removed the mocked std-out {@link PrintStream} again from the {@link System} class - */ - @After - public void tearDown() { - System.setOut(this.stdOutOrig); - } - - /** - * Get the mocked stdOut {@link PrintStream} - * - * @return The stdOut print stream mock, renewed before each test - */ - final PrintStream getStdOutMock() { - return this.stdOutMock; - } - /** * Get the tested object * @@ -106,9 +61,6 @@ public abstract class CollisionTest { tested.collision(other); - verify(getStdOutMock(), times(1)).println(description); - verifyNoMoreInteractions(getStdOutMock()); - testOnFire(other, tested, otherOnFire); testDamaged(other, tested, otherDamaged); @@ -129,8 +81,8 @@ public abstract class CollisionTest { final String targetName = target.getClass().getSimpleName(); final String otherName = other.getClass().getSimpleName(); - final String errorMessage = expectTargetOnFire - ? "Expected [" + targetName + "] to be on fire after colliding with [" + otherName + "] but it was not!" + final String errorMessage = expectTargetOnFire + ? "Expected [" + targetName + "] to be on fire after colliding with [" + otherName + "] but it was not!" : "Expected [" + targetName + "] not to be on fire after colliding with [" + otherName + "] but it was!"; assertEquals(errorMessage, expectTargetOnFire, target.isOnFire()); @@ -149,7 +101,7 @@ public abstract class CollisionTest { final String otherName = other.getClass().getSimpleName(); final String errorMessage = expectedDamage - ? "Expected [" + targetName + "] to be damaged after colliding with [" + otherName + "] but it was not!" + ? "Expected [" + targetName + "] to be damaged after colliding with [" + otherName + "] but it was not!" : "Expected [" + targetName + "] not to be damaged after colliding with [" + otherName + "] but it was!"; assertEquals(errorMessage, expectedDamage, target.isDamaged()); diff --git a/event-aggregator/src/test/java/com/iluwatar/event/aggregator/KingJoffreyTest.java b/event-aggregator/src/test/java/com/iluwatar/event/aggregator/KingJoffreyTest.java index 3e0028ac4..e06d10b6a 100644 --- a/event-aggregator/src/test/java/com/iluwatar/event/aggregator/KingJoffreyTest.java +++ b/event-aggregator/src/test/java/com/iluwatar/event/aggregator/KingJoffreyTest.java @@ -22,17 +22,18 @@ */ package com.iluwatar.event.aggregator; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.AppenderBase; import org.junit.After; import org.junit.Before; import org.junit.Test; +import org.slf4j.LoggerFactory; -import java.io.PrintStream; +import java.util.LinkedList; +import java.util.List; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyZeroInteractions; -import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.junit.Assert.assertEquals; /** * Date: 12/12/15 - 3:04 PM @@ -41,31 +42,16 @@ import static org.mockito.Mockito.verifyNoMoreInteractions; */ public class KingJoffreyTest { - /** - * The mocked standard out {@link PrintStream}, required since {@link KingJoffrey} does nothing - * except for writing to std-out using {@link System#out} - */ - private final PrintStream stdOutMock = mock(PrintStream.class); + private InMemoryAppender appender; - /** - * Keep the original std-out so it can be restored after the test - */ - private final PrintStream stdOutOrig = System.out; - - /** - * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test - */ @Before public void setUp() { - System.setOut(this.stdOutMock); + appender = new InMemoryAppender(KingJoffrey.class); } - /** - * Removed the mocked std-out {@link PrintStream} again from the {@link System} class - */ @After public void tearDown() { - System.setOut(this.stdOutOrig); + appender.stop(); } /** @@ -75,15 +61,38 @@ public class KingJoffreyTest { public void testOnEvent() { final KingJoffrey kingJoffrey = new KingJoffrey(); - for (final Event event : Event.values()) { - verifyZeroInteractions(this.stdOutMock); + for (int i = 0; i < Event.values().length; ++i) { + assertEquals(i, appender.getLogSize()); + Event event = Event.values()[i]; kingJoffrey.onEvent(event); final String expectedMessage = "Received event from the King's Hand: " + event.toString(); - verify(this.stdOutMock, times(1)).println(expectedMessage); - verifyNoMoreInteractions(this.stdOutMock); + assertEquals(expectedMessage, appender.getLastMessage()); + assertEquals(i + 1, appender.getLogSize()); } } -} \ No newline at end of file + private class InMemoryAppender extends AppenderBase { + private List log = new LinkedList<>(); + + public InMemoryAppender(Class clazz) { + ((Logger) LoggerFactory.getLogger(clazz)).addAppender(this); + start(); + } + + @Override + protected void append(ILoggingEvent eventObject) { + log.add(eventObject); + } + + public String getLastMessage() { + return log.get(log.size() - 1).getFormattedMessage(); + } + + public int getLogSize() { + return log.size(); + } + } + +} diff --git a/facade/src/test/java/com/iluwatar/facade/DwarvenGoldmineFacadeTest.java b/facade/src/test/java/com/iluwatar/facade/DwarvenGoldmineFacadeTest.java index 4a3b218e2..7718f7d41 100644 --- a/facade/src/test/java/com/iluwatar/facade/DwarvenGoldmineFacadeTest.java +++ b/facade/src/test/java/com/iluwatar/facade/DwarvenGoldmineFacadeTest.java @@ -22,17 +22,19 @@ */ package com.iluwatar.facade; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.AppenderBase; import org.junit.After; import org.junit.Before; import org.junit.Test; +import org.slf4j.LoggerFactory; -import java.io.PrintStream; +import java.util.LinkedList; +import java.util.List; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.internal.verification.VerificationModeFactory.times; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; /** * Date: 12/9/15 - 9:40 PM @@ -41,35 +43,19 @@ import static org.mockito.internal.verification.VerificationModeFactory.times; */ public class DwarvenGoldmineFacadeTest { - /** - * The mocked standard out {@link PrintStream}, required since the actions on the gold mine facade - * don't have any influence on any other accessible objects, except for writing to std-out using - * {@link System#out} - */ - private final PrintStream stdOutMock = mock(PrintStream.class); + private InMemoryAppender appender; - /** - * Keep the original std-out so it can be restored after the test - */ - private final PrintStream stdOutOrig = System.out; - - /** - * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test - */ @Before public void setUp() { - System.setOut(this.stdOutMock); + appender = new InMemoryAppender(); } - /** - * Removed the mocked std-out {@link PrintStream} again from the {@link System} class - */ @After public void tearDown() { - System.setOut(this.stdOutOrig); + appender.stop(); } - /** + /** * Test a complete day cycle in the gold mine by executing all three different steps: {@link * DwarvenGoldmineFacade#startNewDay()}, {@link DwarvenGoldmineFacade#digOutGold()} and {@link * DwarvenGoldmineFacade#endDay()}. @@ -82,44 +68,68 @@ public class DwarvenGoldmineFacadeTest { goldMine.startNewDay(); // On the start of a day, all workers should wake up ... - verify(this.stdOutMock, times(1)).println(eq("Dwarf gold digger wakes up.")); - verify(this.stdOutMock, times(1)).println(eq("Dwarf cart operator wakes up.")); - verify(this.stdOutMock, times(1)).println(eq("Dwarven tunnel digger wakes up.")); + assertTrue(appender.logContains("Dwarf gold digger wakes up.")); + assertTrue(appender.logContains("Dwarf cart operator wakes up.")); + assertTrue(appender.logContains("Dwarven tunnel digger wakes up.")); // ... and go to the mine - verify(this.stdOutMock, times(1)).println(eq("Dwarf gold digger goes to the mine.")); - verify(this.stdOutMock, times(1)).println(eq("Dwarf cart operator goes to the mine.")); - verify(this.stdOutMock, times(1)).println(eq("Dwarven tunnel digger goes to the mine.")); + assertTrue(appender.logContains("Dwarf gold digger goes to the mine.")); + assertTrue(appender.logContains("Dwarf cart operator goes to the mine.")); + assertTrue(appender.logContains("Dwarven tunnel digger goes to the mine.")); // No other actions were invoked, so the workers shouldn't have done (printed) anything else - verifyNoMoreInteractions(this.stdOutMock); + assertEquals(6, appender.getLogSize()); // Now do some actual work, start digging gold! goldMine.digOutGold(); // Since we gave the dig command, every worker should be doing it's job ... - verify(this.stdOutMock, times(1)).println(eq("Dwarf gold digger digs for gold.")); - verify(this.stdOutMock, times(1)).println(eq("Dwarf cart operator moves gold chunks out of the mine.")); - verify(this.stdOutMock, times(1)).println(eq("Dwarven tunnel digger creates another promising tunnel.")); + assertTrue(appender.logContains("Dwarf gold digger digs for gold.")); + assertTrue(appender.logContains("Dwarf cart operator moves gold chunks out of the mine.")); + assertTrue(appender.logContains("Dwarven tunnel digger creates another promising tunnel.")); // Again, they shouldn't be doing anything else. - verifyNoMoreInteractions(this.stdOutMock); + assertEquals(9, appender.getLogSize()); // Enough gold, lets end the day. goldMine.endDay(); // Check if the workers go home ... - verify(this.stdOutMock, times(1)).println(eq("Dwarf gold digger goes home.")); - verify(this.stdOutMock, times(1)).println(eq("Dwarf cart operator goes home.")); - verify(this.stdOutMock, times(1)).println(eq("Dwarven tunnel digger goes home.")); + assertTrue(appender.logContains("Dwarf gold digger goes home.")); + assertTrue(appender.logContains("Dwarf cart operator goes home.")); + assertTrue(appender.logContains("Dwarven tunnel digger goes home.")); // ... and go to sleep. We need well rested workers the next day :) - verify(this.stdOutMock, times(1)).println(eq("Dwarf gold digger goes to sleep.")); - verify(this.stdOutMock, times(1)).println(eq("Dwarf cart operator goes to sleep.")); - verify(this.stdOutMock, times(1)).println(eq("Dwarven tunnel digger goes to sleep.")); + assertTrue(appender.logContains("Dwarf gold digger goes to sleep.")); + assertTrue(appender.logContains("Dwarf cart operator goes to sleep.")); + assertTrue(appender.logContains("Dwarven tunnel digger goes to sleep.")); // Every worker should be sleeping now, no other actions allowed - verifyNoMoreInteractions(this.stdOutMock); + assertEquals(15, appender.getLogSize()); } + private class InMemoryAppender extends AppenderBase { + + private List log = new LinkedList<>(); + + public InMemoryAppender() { + ((Logger) LoggerFactory.getLogger("root")).addAppender(this); + start(); + } + + @Override + protected void append(ILoggingEvent eventObject) { + log.add(eventObject); + } + + public int getLogSize() { + return log.size(); + } + + public boolean logContains(String message) { + return log.stream().anyMatch(event -> event.getFormattedMessage().equals(message)); + } + } + + } diff --git a/front-controller/src/test/java/com/iluwatar/front/controller/CommandTest.java b/front-controller/src/test/java/com/iluwatar/front/controller/CommandTest.java index c4d9ae625..0b5c9f593 100644 --- a/front-controller/src/test/java/com/iluwatar/front/controller/CommandTest.java +++ b/front-controller/src/test/java/com/iluwatar/front/controller/CommandTest.java @@ -22,6 +22,9 @@ */ package com.iluwatar.front.controller; +import com.iluwatar.front.controller.utils.InMemoryAppender; +import org.junit.After; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @@ -30,9 +33,7 @@ import org.junit.runners.Parameterized.Parameters; import java.util.ArrayList; import java.util.List; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.verifyZeroInteractions; +import static org.junit.Assert.assertEquals; /** * Date: 12/13/15 - 1:39 PM @@ -40,7 +41,19 @@ import static org.mockito.Mockito.verifyZeroInteractions; * @author Jeroen Meulemeester */ @RunWith(Parameterized.class) -public class CommandTest extends StdOutTest { +public class CommandTest { + + private InMemoryAppender appender; + + @Before + public void setUp() { + appender = new InMemoryAppender(); + } + + @After + public void tearDown() { + appender.stop(); + } @Parameters public static List data() { @@ -75,10 +88,10 @@ public class CommandTest extends StdOutTest { @Test public void testDisplay() { final FrontController frontController = new FrontController(); - verifyZeroInteractions(getStdOutMock()); + assertEquals(0, appender.getLogSize()); frontController.handleRequest(request); - verify(getStdOutMock()).println(displayMessage); - verifyNoMoreInteractions(getStdOutMock()); + assertEquals(displayMessage, appender.getLastMessage()); + assertEquals(1, appender.getLogSize()); } } diff --git a/front-controller/src/test/java/com/iluwatar/front/controller/FrontControllerTest.java b/front-controller/src/test/java/com/iluwatar/front/controller/FrontControllerTest.java index 0822ffcd0..46a26e6fb 100644 --- a/front-controller/src/test/java/com/iluwatar/front/controller/FrontControllerTest.java +++ b/front-controller/src/test/java/com/iluwatar/front/controller/FrontControllerTest.java @@ -22,6 +22,9 @@ */ package com.iluwatar.front.controller; +import com.iluwatar.front.controller.utils.InMemoryAppender; +import org.junit.After; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @@ -30,9 +33,7 @@ import org.junit.runners.Parameterized.Parameters; import java.util.ArrayList; import java.util.List; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.verifyZeroInteractions; +import static org.junit.Assert.assertEquals; /** * Date: 12/13/15 - 1:39 PM @@ -40,7 +41,19 @@ import static org.mockito.Mockito.verifyZeroInteractions; * @author Jeroen Meulemeester */ @RunWith(Parameterized.class) -public class FrontControllerTest extends StdOutTest { +public class FrontControllerTest { + + private InMemoryAppender appender; + + @Before + public void setUp() { + appender = new InMemoryAppender(); + } + + @After + public void tearDown() { + appender.stop(); + } @Parameters public static List data() { @@ -74,10 +87,10 @@ public class FrontControllerTest extends StdOutTest { @Test public void testDisplay() { - verifyZeroInteractions(getStdOutMock()); + assertEquals(0, appender.getLogSize()); this.command.process(); - verify(getStdOutMock()).println(displayMessage); - verifyNoMoreInteractions(getStdOutMock()); + assertEquals(displayMessage, appender.getLastMessage()); + assertEquals(1, appender.getLogSize()); } } diff --git a/front-controller/src/test/java/com/iluwatar/front/controller/StdOutTest.java b/front-controller/src/test/java/com/iluwatar/front/controller/StdOutTest.java deleted file mode 100644 index bc32a1b3c..000000000 --- a/front-controller/src/test/java/com/iluwatar/front/controller/StdOutTest.java +++ /dev/null @@ -1,76 +0,0 @@ -/** - * 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.front.controller; - -import org.junit.After; -import org.junit.Before; - -import java.io.PrintStream; - -import static org.mockito.Mockito.mock; - -/** - * Date: 12/10/15 - 8:37 PM - * - * @author Jeroen Meulemeester - */ -public abstract class StdOutTest { - - /** - * The mocked standard out {@link PrintStream}, required since the actions of the views don't have - * any influence on any other accessible objects, except for writing to std-out using {@link - * System#out} - */ - private final PrintStream stdOutMock = mock(PrintStream.class); - - /** - * Keep the original std-out so it can be restored after the test - */ - private final PrintStream stdOutOrig = System.out; - - /** - * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test - */ - @Before - public void setUp() { - System.setOut(this.stdOutMock); - } - - /** - * Removed the mocked std-out {@link PrintStream} again from the {@link System} class - */ - @After - public void tearDown() { - System.setOut(this.stdOutOrig); - } - - /** - * Get the mocked stdOut {@link PrintStream} - * - * @return The stdOut print stream mock, renewed before each test - */ - final PrintStream getStdOutMock() { - return this.stdOutMock; - } - -} diff --git a/front-controller/src/test/java/com/iluwatar/front/controller/ViewTest.java b/front-controller/src/test/java/com/iluwatar/front/controller/ViewTest.java index cdabd66ef..bca070305 100644 --- a/front-controller/src/test/java/com/iluwatar/front/controller/ViewTest.java +++ b/front-controller/src/test/java/com/iluwatar/front/controller/ViewTest.java @@ -22,6 +22,9 @@ */ package com.iluwatar.front.controller; +import com.iluwatar.front.controller.utils.InMemoryAppender; +import org.junit.After; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @@ -30,9 +33,7 @@ import org.junit.runners.Parameterized.Parameters; import java.util.ArrayList; import java.util.List; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.verifyZeroInteractions; +import static org.junit.Assert.assertEquals; /** * Date: 12/13/15 - 1:39 PM @@ -40,7 +41,19 @@ import static org.mockito.Mockito.verifyZeroInteractions; * @author Jeroen Meulemeester */ @RunWith(Parameterized.class) -public class ViewTest extends StdOutTest { +public class ViewTest { + + private InMemoryAppender appender; + + @Before + public void setUp() { + appender = new InMemoryAppender(); + } + + @After + public void tearDown() { + appender.stop(); + } @Parameters public static List data() { @@ -74,10 +87,10 @@ public class ViewTest extends StdOutTest { @Test public void testDisplay() { - verifyZeroInteractions(getStdOutMock()); + assertEquals(0, appender.getLogSize()); this.view.display(); - verify(getStdOutMock()).println(displayMessage); - verifyNoMoreInteractions(getStdOutMock()); + assertEquals(displayMessage, appender.getLastMessage()); + assertEquals(1, appender.getLogSize()); } -} \ No newline at end of file +} diff --git a/front-controller/src/test/java/com/iluwatar/front/controller/utils/InMemoryAppender.java b/front-controller/src/test/java/com/iluwatar/front/controller/utils/InMemoryAppender.java new file mode 100644 index 000000000..1747deac5 --- /dev/null +++ b/front-controller/src/test/java/com/iluwatar/front/controller/utils/InMemoryAppender.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.front.controller.utils; + +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.AppenderBase; +import org.slf4j.LoggerFactory; + +import java.util.LinkedList; +import java.util.List; + +public class InMemoryAppender extends AppenderBase { + + private List log = new LinkedList<>(); + + public InMemoryAppender() { + ((Logger) LoggerFactory.getLogger("root")).addAppender(this); + start(); + } + + @Override + protected void append(ILoggingEvent eventObject) { + log.add(eventObject); + } + + public String getLastMessage() { + return log.get(log.size() - 1).getFormattedMessage(); + } + + public int getLogSize() { + return log.size(); + } +} diff --git a/hexagonal/src/main/java/com/iluwatar/hexagonal/service/ConsoleLottery.java b/hexagonal/src/main/java/com/iluwatar/hexagonal/service/ConsoleLottery.java index 00d61b668..077b0f235 100644 --- a/hexagonal/src/main/java/com/iluwatar/hexagonal/service/ConsoleLottery.java +++ b/hexagonal/src/main/java/com/iluwatar/hexagonal/service/ConsoleLottery.java @@ -24,7 +24,6 @@ package com.iluwatar.hexagonal.service; import com.google.inject.Guice; import com.google.inject.Injector; -import com.iluwatar.hexagonal.administration.ConsoleAdministration; import com.iluwatar.hexagonal.banking.WireTransfers; import com.iluwatar.hexagonal.domain.LotteryNumbers; import com.iluwatar.hexagonal.domain.LotteryService; diff --git a/layers/src/test/java/com/iluwatar/layers/CakeViewImplTest.java b/layers/src/test/java/com/iluwatar/layers/CakeViewImplTest.java index a69aa23bb..3a9214ae1 100644 --- a/layers/src/test/java/com/iluwatar/layers/CakeViewImplTest.java +++ b/layers/src/test/java/com/iluwatar/layers/CakeViewImplTest.java @@ -22,11 +22,19 @@ */ package com.iluwatar.layers; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.AppenderBase; +import org.junit.After; +import org.junit.Before; import org.junit.Test; +import org.slf4j.LoggerFactory; import java.util.ArrayList; +import java.util.LinkedList; import java.util.List; +import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.*; /** @@ -34,7 +42,19 @@ import static org.mockito.Mockito.*; * * @author Jeroen Meulemeester */ -public class CakeViewImplTest extends StdOutTest { +public class CakeViewImplTest { + + private InMemoryAppender appender; + + @Before + public void setUp() { + appender = new InMemoryAppender(CakeViewImpl.class); + } + + @After + public void tearDown() { + appender.stop(); + } /** * Verify if the cake view renders the expected result @@ -56,11 +76,34 @@ public class CakeViewImplTest extends StdOutTest { final CakeViewImpl cakeView = new CakeViewImpl(bakingService); - verifyZeroInteractions(getStdOutMock()); + assertEquals(0, appender.getLogSize()); cakeView.render(); - verify(getStdOutMock(), times(1)).println(cake); + assertEquals(cake.toString(), appender.getLastMessage()); } + private class InMemoryAppender extends AppenderBase { + + private List log = new LinkedList<>(); + + public InMemoryAppender(Class clazz) { + ((Logger) LoggerFactory.getLogger(clazz)).addAppender(this); + start(); + } + + @Override + protected void append(ILoggingEvent eventObject) { + log.add(eventObject); + } + + public String getLastMessage() { + return log.get(log.size() - 1).getFormattedMessage(); + } + + public int getLogSize() { + return log.size(); + } + } + } diff --git a/layers/src/test/java/com/iluwatar/layers/StdOutTest.java b/layers/src/test/java/com/iluwatar/layers/StdOutTest.java deleted file mode 100644 index 67a554873..000000000 --- a/layers/src/test/java/com/iluwatar/layers/StdOutTest.java +++ /dev/null @@ -1,78 +0,0 @@ -/** - * 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.layers; - -import org.junit.After; -import org.junit.Before; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.PrintStream; - -import static org.mockito.Mockito.mock; - -/** - * Date: 12/10/15 - 8:37 PM - * - * @author Jeroen Meulemeester - */ -public abstract class StdOutTest { - - /** - * The mocked standard out {@link PrintStream}, required since the actions of the views don't have - * any influence on any other accessible objects, except for writing to std-out using {@link - * System#out} - */ - private final PrintStream stdOutMock = mock(PrintStream.class); - - /** - * Keep the original std-out so it can be restored after the test - */ - private final PrintStream stdOutOrig = System.out; - - /** - * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test - */ - @Before - public void setUp() { - System.setOut(this.stdOutMock); - } - - /** - * Removed the mocked std-out {@link PrintStream} again from the {@link System} class - */ - @After - public void tearDown() { - System.setOut(this.stdOutOrig); - } - - /** - * Get the mocked stdOut {@link PrintStream} - * - * @return The stdOut print stream mock, renewed before each test - */ - final PrintStream getStdOutMock() { - return this.stdOutMock; - } - -} diff --git a/mediator/src/test/java/com/iluwatar/mediator/PartyMemberTest.java b/mediator/src/test/java/com/iluwatar/mediator/PartyMemberTest.java index 0bf43f9cd..e5f7e2719 100644 --- a/mediator/src/test/java/com/iluwatar/mediator/PartyMemberTest.java +++ b/mediator/src/test/java/com/iluwatar/mediator/PartyMemberTest.java @@ -22,22 +22,25 @@ */ package com.iluwatar.mediator; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.AppenderBase; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; +import org.slf4j.LoggerFactory; -import java.io.PrintStream; import java.util.Arrays; import java.util.Collection; +import java.util.LinkedList; +import java.util.List; import java.util.function.Supplier; import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.verifyZeroInteractions; /** * Date: 12/19/15 - 10:13 PM @@ -57,34 +60,6 @@ public class PartyMemberTest { ); } - /** - * The mocked standard out {@link PrintStream}, required since some actions on a {@link - * PartyMember} have any influence on any other accessible objects, except for writing to std-out - * using {@link System#out} - */ - private final PrintStream stdOutMock = mock(PrintStream.class); - - /** - * Keep the original std-out so it can be restored after the test - */ - private final PrintStream stdOutOrig = System.out; - - /** - * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test - */ - @Before - public void setUp() { - System.setOut(this.stdOutMock); - } - - /** - * Removed the mocked std-out {@link PrintStream} again from the {@link System} class - */ - @After - public void tearDown() { - System.setOut(this.stdOutOrig); - } - /** * The factory, used to create a new instance of the tested party member */ @@ -99,6 +74,18 @@ public class PartyMemberTest { this.memberSupplier = memberSupplier; } + private InMemoryAppender appender; + + @Before + public void setUp() { + appender = new InMemoryAppender(PartyMemberBase.class); + } + + @After + public void tearDown() { + appender.stop(); + } + /** * Verify if a party action triggers the correct output to the std-Out */ @@ -108,10 +95,10 @@ public class PartyMemberTest { for (final Action action : Action.values()) { member.partyAction(action); - verify(this.stdOutMock).println(member.toString() + " " + action.getDescription()); + assertEquals(member.toString() + " " + action.getDescription(), appender.getLastMessage()); } - verifyNoMoreInteractions(this.stdOutMock); + assertEquals(Action.values().length, appender.getLogSize()); } /** @@ -122,19 +109,19 @@ public class PartyMemberTest { final PartyMember member = this.memberSupplier.get(); member.act(Action.GOLD); - verifyZeroInteractions(this.stdOutMock); + assertEquals(0, appender.getLogSize()); final Party party = mock(Party.class); member.joinedParty(party); - verify(this.stdOutMock).println(member.toString() + " joins the party"); + assertEquals(member.toString() + " joins the party", appender.getLastMessage()); for (final Action action : Action.values()) { member.act(action); - verify(this.stdOutMock).println(member.toString() + " " + action.toString()); + assertEquals(member.toString() + " " + action.toString(), appender.getLastMessage()); verify(party).act(member, action); } - verifyNoMoreInteractions(party, this.stdOutMock); + assertEquals(Action.values().length + 1, appender.getLogSize()); } /** @@ -147,4 +134,27 @@ public class PartyMemberTest { assertEquals(memberClass.getSimpleName(), member.toString()); } + private class InMemoryAppender extends AppenderBase { + private List log = new LinkedList<>(); + + public InMemoryAppender(Class clazz) { + ((Logger) LoggerFactory.getLogger(clazz)).addAppender(this); + start(); + } + + @Override + protected void append(ILoggingEvent eventObject) { + log.add(eventObject); + } + + public int getLogSize() { + return log.size(); + } + + public String getLastMessage() { + return log.get(log.size() - 1).getFormattedMessage(); + } + } + + } diff --git a/model-view-controller/src/test/java/com/iluwatar/model/view/controller/GiantViewTest.java b/model-view-controller/src/test/java/com/iluwatar/model/view/controller/GiantViewTest.java index 89d503d4e..9ea0ae96e 100644 --- a/model-view-controller/src/test/java/com/iluwatar/model/view/controller/GiantViewTest.java +++ b/model-view-controller/src/test/java/com/iluwatar/model/view/controller/GiantViewTest.java @@ -22,15 +22,19 @@ */ package com.iluwatar.model.view.controller; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.AppenderBase; import org.junit.After; import org.junit.Before; import org.junit.Test; +import org.slf4j.LoggerFactory; -import java.io.PrintStream; +import java.util.LinkedList; +import java.util.List; +import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; /** * Date: 12/20/15 - 2:04 PM @@ -39,32 +43,16 @@ import static org.mockito.Mockito.verifyNoMoreInteractions; */ public class GiantViewTest { - /** - * The mocked standard out {@link PrintStream}, required since the actions of the views don't have - * any influence on any other accessible objects, except for writing to std-out using {@link - * System#out} - */ - private final PrintStream stdOutMock = mock(PrintStream.class); + private InMemoryAppender appender; - /** - * Keep the original std-out so it can be restored after the test - */ - private final PrintStream stdOutOrig = System.out; - - /** - * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test - */ @Before public void setUp() { - System.setOut(this.stdOutMock); + appender = new InMemoryAppender(GiantView.class); } - /** - * Removed the mocked std-out {@link PrintStream} again from the {@link System} class - */ @After public void tearDown() { - System.setOut(this.stdOutOrig); + appender.stop(); } /** @@ -78,9 +66,29 @@ public class GiantViewTest { final GiantModel model = mock(GiantModel.class); view.displayGiant(model); - verify(this.stdOutMock).println(model); - verifyNoMoreInteractions(model, this.stdOutMock); - + assertEquals(model.toString(), appender.getLastMessage()); + assertEquals(1, appender.getLogSize()); } -} \ No newline at end of file + public class InMemoryAppender extends AppenderBase { + private List log = new LinkedList<>(); + + public InMemoryAppender(Class clazz) { + ((Logger) LoggerFactory.getLogger(clazz)).addAppender(this); + start(); + } + + @Override + protected void append(ILoggingEvent eventObject) { + log.add(eventObject); + } + + public String getLastMessage() { + return log.get(log.size() - 1).getMessage(); + } + + public int getLogSize() { + return log.size(); + } + } +} diff --git a/null-object/src/test/java/com/iluwatar/nullobject/NullNodeTest.java b/null-object/src/test/java/com/iluwatar/nullobject/NullNodeTest.java index 1375b8949..98168fc0a 100644 --- a/null-object/src/test/java/com/iluwatar/nullobject/NullNodeTest.java +++ b/null-object/src/test/java/com/iluwatar/nullobject/NullNodeTest.java @@ -23,19 +23,15 @@ package com.iluwatar.nullobject; import org.junit.Test; -import org.mockito.Mockito; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; +import static org.junit.Assert.*; /** * Date: 12/26/15 - 11:47 PM * * @author Jeroen Meulemeester */ -public class NullNodeTest extends StdOutTest { +public class NullNodeTest { /** * Verify if {@link NullNode#getInstance()} actually returns the same object instance @@ -59,7 +55,6 @@ public class NullNodeTest extends StdOutTest { @Test public void testWalk() throws Exception { NullNode.getInstance().walk(); - Mockito.verifyZeroInteractions(getStdOutMock()); } -} \ No newline at end of file +} diff --git a/null-object/src/test/java/com/iluwatar/nullobject/StdOutTest.java b/null-object/src/test/java/com/iluwatar/nullobject/StdOutTest.java deleted file mode 100644 index 0c0122132..000000000 --- a/null-object/src/test/java/com/iluwatar/nullobject/StdOutTest.java +++ /dev/null @@ -1,76 +0,0 @@ -/** - * 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.nullobject; - -import org.junit.After; -import org.junit.Before; - -import java.io.PrintStream; - -import static org.mockito.Mockito.mock; - -/** - * Date: 12/10/15 - 8:37 PM - * - * @author Jeroen Meulemeester - */ -public abstract class StdOutTest { - - /** - * The mocked standard out {@link PrintStream}, required since walking through the tree has no - * influence on any other accessible object, except for writing to std-out using {@link - * System#out} - */ - private final PrintStream stdOutMock = mock(PrintStream.class); - - /** - * Keep the original std-out so it can be restored after the test - */ - private final PrintStream stdOutOrig = System.out; - - /** - * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test - */ - @Before - public void setUp() { - System.setOut(this.stdOutMock); - } - - /** - * Removed the mocked std-out {@link PrintStream} again from the {@link System} class - */ - @After - public void tearDown() { - System.setOut(this.stdOutOrig); - } - - /** - * Get the mocked stdOut {@link PrintStream} - * - * @return The stdOut print stream mock, renewed before each test - */ - final PrintStream getStdOutMock() { - return this.stdOutMock; - } - -} diff --git a/null-object/src/test/java/com/iluwatar/nullobject/TreeTest.java b/null-object/src/test/java/com/iluwatar/nullobject/TreeTest.java index 6c77cd236..2712b0356 100644 --- a/null-object/src/test/java/com/iluwatar/nullobject/TreeTest.java +++ b/null-object/src/test/java/com/iluwatar/nullobject/TreeTest.java @@ -22,20 +22,37 @@ */ package com.iluwatar.nullobject; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.AppenderBase; +import org.junit.After; +import org.junit.Before; import org.junit.Test; -import org.mockito.InOrder; -import org.mockito.Mockito; +import org.slf4j.LoggerFactory; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertSame; +import java.util.LinkedList; +import java.util.List; + +import static org.junit.Assert.*; /** * Date: 12/26/15 - 11:44 PM * * @author Jeroen Meulemeester */ -public class TreeTest extends StdOutTest { +public class TreeTest { + + private InMemoryAppender appender; + + @Before + public void setUp() { + appender = new InMemoryAppender(); + } + + @After + public void tearDown() { + appender.stop(); + } /** * During the tests, the same tree structure will be used, shown below. End points will be @@ -79,15 +96,14 @@ public class TreeTest extends StdOutTest { public void testWalk() { TREE_ROOT.walk(); - final InOrder inOrder = Mockito.inOrder(getStdOutMock()); - inOrder.verify(getStdOutMock()).println("root"); - inOrder.verify(getStdOutMock()).println("level1_a"); - inOrder.verify(getStdOutMock()).println("level2_a"); - inOrder.verify(getStdOutMock()).println("level3_a"); - inOrder.verify(getStdOutMock()).println("level3_b"); - inOrder.verify(getStdOutMock()).println("level2_b"); - inOrder.verify(getStdOutMock()).println("level1_b"); - inOrder.verifyNoMoreInteractions(); + assertTrue(appender.logContains("root")); + assertTrue(appender.logContains("level1_a")); + assertTrue(appender.logContains("level2_a")); + assertTrue(appender.logContains("level3_a")); + assertTrue(appender.logContains("level3_b")); + assertTrue(appender.logContains("level2_b")); + assertTrue(appender.logContains("level1_b")); + assertEquals(7, appender.getLogSize()); } @Test @@ -120,4 +136,26 @@ public class TreeTest extends StdOutTest { assertSame(NullNode.getInstance(), level1.getLeft()); } + private class InMemoryAppender extends AppenderBase { + private List log = new LinkedList<>(); + + public InMemoryAppender() { + ((Logger) LoggerFactory.getLogger("root")).addAppender(this); + start(); + } + + @Override + protected void append(ILoggingEvent eventObject) { + log.add(eventObject); + } + + public boolean logContains(String message) { + return log.stream().anyMatch(event -> event.getMessage().equals(message)); + } + + public int getLogSize() { + return log.size(); + } + } + } diff --git a/observer/src/test/java/com/iluwatar/observer/StdOutTest.java b/observer/src/test/java/com/iluwatar/observer/StdOutTest.java deleted file mode 100644 index afd870ae4..000000000 --- a/observer/src/test/java/com/iluwatar/observer/StdOutTest.java +++ /dev/null @@ -1,76 +0,0 @@ -/** - * 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.observer; - -import org.junit.After; -import org.junit.Before; - -import java.io.PrintStream; - -import static org.mockito.Mockito.mock; - -/** - * Date: 12/27/15 - 12:16 PM - * - * @author Jeroen Meulemeester - */ -public abstract class StdOutTest { - - /** - * The mocked standard out {@link PrintStream}, required since changes in the weather doesn't has - * any influence on any other accessible objects, except for writing to std-out using {@link - * System#out} - */ - private final PrintStream stdOutMock = mock(PrintStream.class); - - /** - * Keep the original std-out so it can be restored after the test - */ - private final PrintStream stdOutOrig = System.out; - - /** - * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test - */ - @Before - public void setUp() { - System.setOut(this.stdOutMock); - } - - /** - * Removed the mocked std-out {@link PrintStream} again from the {@link System} class - */ - @After - public void tearDown() { - System.setOut(this.stdOutOrig); - } - - /** - * Get the mocked stdOut {@link PrintStream} - * - * @return The stdOut print stream mock, renewed before each test - */ - protected final PrintStream getStdOutMock() { - return this.stdOutMock; - } - -} diff --git a/observer/src/test/java/com/iluwatar/observer/WeatherObserverTest.java b/observer/src/test/java/com/iluwatar/observer/WeatherObserverTest.java index a06c19952..1ccf4bf12 100644 --- a/observer/src/test/java/com/iluwatar/observer/WeatherObserverTest.java +++ b/observer/src/test/java/com/iluwatar/observer/WeatherObserverTest.java @@ -22,20 +22,33 @@ */ package com.iluwatar.observer; +import com.iluwatar.observer.utils.InMemoryAppender; +import org.junit.After; +import org.junit.Before; import org.junit.Test; import java.util.function.Supplier; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.verifyZeroInteractions; +import static org.junit.Assert.assertEquals; /** * Date: 12/27/15 - 11:44 AM * * @author Jeroen Meulemeester */ -public abstract class WeatherObserverTest extends StdOutTest { +public abstract class WeatherObserverTest { + + private InMemoryAppender appender; + + @Before + public void setUp() { + appender = new InMemoryAppender(); + } + + @After + public void tearDown() { + appender.stop(); + } /** * The observer instance factory @@ -71,11 +84,11 @@ public abstract class WeatherObserverTest extends Std @Test public void testObserver() { final O observer = this.factory.get(); - verifyZeroInteractions(getStdOutMock()); + assertEquals(0, appender.getLogSize()); observer.update(this.weather); - verify(getStdOutMock()).println(this.response); - verifyNoMoreInteractions(getStdOutMock()); + assertEquals(response, appender.getLastMessage()); + assertEquals(1, appender.getLogSize()); } -} \ No newline at end of file +} diff --git a/observer/src/test/java/com/iluwatar/observer/WeatherTest.java b/observer/src/test/java/com/iluwatar/observer/WeatherTest.java index 7a38e7137..9d53b2e23 100644 --- a/observer/src/test/java/com/iluwatar/observer/WeatherTest.java +++ b/observer/src/test/java/com/iluwatar/observer/WeatherTest.java @@ -22,9 +22,13 @@ */ package com.iluwatar.observer; +import com.iluwatar.observer.utils.InMemoryAppender; +import org.junit.After; +import org.junit.Before; import org.junit.Test; import org.mockito.InOrder; +import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -36,7 +40,19 @@ import static org.mockito.Mockito.verifyZeroInteractions; * * @author Jeroen Meulemeester */ -public class WeatherTest extends StdOutTest { +public class WeatherTest { + + private InMemoryAppender appender; + + @Before + public void setUp() { + appender = new InMemoryAppender(Weather.class); + } + + @After + public void tearDown() { + appender.stop(); + } /** * Add a {@link WeatherObserver}, verify if it gets notified of a weather change, remove the @@ -51,14 +67,15 @@ public class WeatherTest extends StdOutTest { verifyZeroInteractions(observer); weather.timePasses(); - verify(getStdOutMock()).println("The weather changed to rainy."); + assertEquals("The weather changed to rainy.", appender.getLastMessage()); verify(observer).update(WeatherType.RAINY); weather.removeObserver(observer); weather.timePasses(); - verify(getStdOutMock()).println("The weather changed to windy."); + assertEquals("The weather changed to windy.", appender.getLastMessage()); - verifyNoMoreInteractions(observer, getStdOutMock()); + verifyNoMoreInteractions(observer); + assertEquals(2, appender.getLogSize()); } /** @@ -70,7 +87,7 @@ public class WeatherTest extends StdOutTest { final Weather weather = new Weather(); weather.addObserver(observer); - final InOrder inOrder = inOrder(observer, getStdOutMock()); + final InOrder inOrder = inOrder(observer); final WeatherType[] weatherTypes = WeatherType.values(); for (int i = 1; i < 20; i++) { weather.timePasses(); @@ -80,4 +97,4 @@ public class WeatherTest extends StdOutTest { verifyNoMoreInteractions(observer); } -} \ No newline at end of file +} diff --git a/observer/src/test/java/com/iluwatar/observer/generic/GWeatherTest.java b/observer/src/test/java/com/iluwatar/observer/generic/GWeatherTest.java index 758dbca8c..61d619a60 100644 --- a/observer/src/test/java/com/iluwatar/observer/generic/GWeatherTest.java +++ b/observer/src/test/java/com/iluwatar/observer/generic/GWeatherTest.java @@ -22,25 +22,35 @@ */ package com.iluwatar.observer.generic; -import com.iluwatar.observer.StdOutTest; import com.iluwatar.observer.WeatherObserver; import com.iluwatar.observer.WeatherType; - +import com.iluwatar.observer.utils.InMemoryAppender; +import org.junit.After; +import org.junit.Before; import org.junit.Test; import org.mockito.InOrder; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.verifyZeroInteractions; +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.*; /** * Date: 12/27/15 - 11:08 AM * * @author Jeroen Meulemeester */ -public class GWeatherTest extends StdOutTest { +public class GWeatherTest { + + private InMemoryAppender appender; + + @Before + public void setUp() { + appender = new InMemoryAppender(GWeather.class); + } + + @After + public void tearDown() { + appender.stop(); + } /** * Add a {@link WeatherObserver}, verify if it gets notified of a weather change, remove the @@ -55,14 +65,15 @@ public class GWeatherTest extends StdOutTest { verifyZeroInteractions(observer); weather.timePasses(); - verify(getStdOutMock()).println("The weather changed to rainy."); + assertEquals("The weather changed to rainy.", appender.getLastMessage()); verify(observer).update(weather, WeatherType.RAINY); weather.removeObserver(observer); weather.timePasses(); - verify(getStdOutMock()).println("The weather changed to windy."); + assertEquals("The weather changed to windy.", appender.getLastMessage()); - verifyNoMoreInteractions(observer, getStdOutMock()); + verifyNoMoreInteractions(observer); + assertEquals(2, appender.getLogSize()); } /** @@ -74,7 +85,7 @@ public class GWeatherTest extends StdOutTest { final GWeather weather = new GWeather(); weather.addObserver(observer); - final InOrder inOrder = inOrder(observer, getStdOutMock()); + final InOrder inOrder = inOrder(observer); final WeatherType[] weatherTypes = WeatherType.values(); for (int i = 1; i < 20; i++) { weather.timePasses(); @@ -84,4 +95,4 @@ public class GWeatherTest extends StdOutTest { verifyNoMoreInteractions(observer); } -} \ No newline at end of file +} diff --git a/observer/src/test/java/com/iluwatar/observer/generic/ObserverTest.java b/observer/src/test/java/com/iluwatar/observer/generic/ObserverTest.java index 33d8daaf5..d01d30992 100644 --- a/observer/src/test/java/com/iluwatar/observer/generic/ObserverTest.java +++ b/observer/src/test/java/com/iluwatar/observer/generic/ObserverTest.java @@ -22,23 +22,34 @@ */ package com.iluwatar.observer.generic; -import com.iluwatar.observer.StdOutTest; import com.iluwatar.observer.WeatherType; - +import com.iluwatar.observer.utils.InMemoryAppender; +import org.junit.After; +import org.junit.Before; import org.junit.Test; import java.util.function.Supplier; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.verifyZeroInteractions; +import static org.junit.Assert.assertEquals; /** * Date: 12/27/15 - 11:44 AM * * @author Jeroen Meulemeester */ -public abstract class ObserverTest extends StdOutTest { +public abstract class ObserverTest { + + private InMemoryAppender appender; + + @Before + public void setUp() { + appender = new InMemoryAppender(); + } + + @After + public void tearDown() { + appender.stop(); + } /** * The observer instance factory @@ -74,11 +85,11 @@ public abstract class ObserverTest extends StdOutTest { @Test public void testObserver() { final O observer = this.factory.get(); - verifyZeroInteractions(getStdOutMock()); + assertEquals(0, appender.getLogSize()); observer.update(null, this.weather); - verify(getStdOutMock()).println(this.response); - verifyNoMoreInteractions(getStdOutMock()); + assertEquals(this.response, appender.getLastMessage()); + assertEquals(1, appender.getLogSize()); } -} \ No newline at end of file +} diff --git a/observer/src/test/java/com/iluwatar/observer/utils/InMemoryAppender.java b/observer/src/test/java/com/iluwatar/observer/utils/InMemoryAppender.java new file mode 100644 index 000000000..4e6e49768 --- /dev/null +++ b/observer/src/test/java/com/iluwatar/observer/utils/InMemoryAppender.java @@ -0,0 +1,58 @@ +/** + * 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.observer.utils; + +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.AppenderBase; +import org.slf4j.LoggerFactory; + +import java.util.LinkedList; +import java.util.List; + +public class InMemoryAppender extends AppenderBase { + private List log = new LinkedList<>(); + + public InMemoryAppender(Class clazz) { + ((Logger) LoggerFactory.getLogger(clazz)).addAppender(this); + start(); + } + + public InMemoryAppender() { + ((Logger) LoggerFactory.getLogger("root")).addAppender(this); + start(); + } + + @Override + protected void append(ILoggingEvent eventObject) { + log.add(eventObject); + } + + public int getLogSize() { + return log.size(); + } + + public String getLastMessage() { + return log.get(log.size() - 1).getFormattedMessage(); + } +} diff --git a/poison-pill/src/test/java/com/iluwatar/poison/pill/ConsumerTest.java b/poison-pill/src/test/java/com/iluwatar/poison/pill/ConsumerTest.java index 01a5dfaa6..983287c3c 100644 --- a/poison-pill/src/test/java/com/iluwatar/poison/pill/ConsumerTest.java +++ b/poison-pill/src/test/java/com/iluwatar/poison/pill/ConsumerTest.java @@ -22,19 +22,38 @@ */ package com.iluwatar.poison.pill; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.AppenderBase; +import org.junit.After; +import org.junit.Before; import org.junit.Test; -import org.mockito.InOrder; +import org.slf4j.LoggerFactory; import java.time.LocalDateTime; +import java.util.LinkedList; +import java.util.List; -import static org.mockito.Mockito.inOrder; +import static org.junit.Assert.assertTrue; /** * Date: 12/27/15 - 9:45 PM * * @author Jeroen Meulemeester */ -public class ConsumerTest extends StdOutTest { +public class ConsumerTest { + + private InMemoryAppender appender; + + @Before + public void setUp() { + appender = new InMemoryAppender(Consumer.class); + } + + @After + public void tearDown() { + appender.stop(); + } @Test public void testConsume() throws Exception { @@ -52,12 +71,9 @@ public class ConsumerTest extends StdOutTest { new Consumer("NSA", queue).consume(); - final InOrder inOrder = inOrder(getStdOutMock()); - inOrder.verify(getStdOutMock()).println("Message [Hello!] from [you] received by [NSA]"); - inOrder.verify(getStdOutMock()).println("Message [Hi!] from [me] received by [NSA]"); - inOrder.verify(getStdOutMock()).println("Consumer NSA receive request to terminate."); - inOrder.verifyNoMoreInteractions(); - + assertTrue(appender.logContains("Message [Hello!] from [you] received by [NSA]")); + assertTrue(appender.logContains("Message [Hi!] from [me] received by [NSA]")); + assertTrue(appender.logContains("Consumer NSA receive request to terminate.")); } /** @@ -75,4 +91,22 @@ public class ConsumerTest extends StdOutTest { return msg; } -} \ No newline at end of file + private class InMemoryAppender extends AppenderBase { + private List log = new LinkedList<>(); + + public InMemoryAppender(Class clazz) { + ((Logger) LoggerFactory.getLogger(clazz)).addAppender(this); + start(); + } + + @Override + protected void append(ILoggingEvent eventObject) { + log.add(eventObject); + } + + public boolean logContains(String message) { + return log.stream().anyMatch(event -> event.getFormattedMessage().equals(message)); + } + } + +} diff --git a/poison-pill/src/test/java/com/iluwatar/poison/pill/StdOutTest.java b/poison-pill/src/test/java/com/iluwatar/poison/pill/StdOutTest.java deleted file mode 100644 index f1b3c4840..000000000 --- a/poison-pill/src/test/java/com/iluwatar/poison/pill/StdOutTest.java +++ /dev/null @@ -1,75 +0,0 @@ -/** - * 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.poison.pill; - -import org.junit.After; -import org.junit.Before; - -import java.io.PrintStream; - -import static org.mockito.Mockito.mock; - -/** - * Date: 12/10/15 - 8:37 PM - * - * @author Jeroen Meulemeester - */ -public abstract class StdOutTest { - - /** - * The mocked standard out {@link PrintStream}, required since some actions don't have any - * influence on accessible objects, except for writing to std-out using {@link System#out} - */ - private final PrintStream stdOutMock = mock(PrintStream.class); - - /** - * Keep the original std-out so it can be restored after the test - */ - private final PrintStream stdOutOrig = System.out; - - /** - * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test - */ - @Before - public void setUp() { - System.setOut(this.stdOutMock); - } - - /** - * Removed the mocked std-out {@link PrintStream} again from the {@link System} class - */ - @After - public void tearDown() { - System.setOut(this.stdOutOrig); - } - - /** - * Get the mocked stdOut {@link PrintStream} - * - * @return The stdOut print stream mock, renewed before each test - */ - final PrintStream getStdOutMock() { - return this.stdOutMock; - } - -} diff --git a/private-class-data/src/test/java/com/iluwatar/privateclassdata/ImmutableStewTest.java b/private-class-data/src/test/java/com/iluwatar/privateclassdata/ImmutableStewTest.java index 58867d303..431375ef7 100644 --- a/private-class-data/src/test/java/com/iluwatar/privateclassdata/ImmutableStewTest.java +++ b/private-class-data/src/test/java/com/iluwatar/privateclassdata/ImmutableStewTest.java @@ -22,18 +22,31 @@ */ package com.iluwatar.privateclassdata; +import com.iluwatar.privateclassdata.utils.InMemoryAppender; +import org.junit.After; +import org.junit.Before; import org.junit.Test; -import org.mockito.InOrder; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.verify; +import static org.junit.Assert.assertEquals; /** * Date: 12/27/15 - 10:46 PM * * @author Jeroen Meulemeester */ -public class ImmutableStewTest extends StdOutTest { +public class ImmutableStewTest { + + private InMemoryAppender appender; + + @Before + public void setUp() { + appender = new InMemoryAppender(); + } + + @After + public void tearDown() { + appender.stop(); + } /** * Verify if mixing the stew doesn't change the internal state @@ -41,15 +54,14 @@ public class ImmutableStewTest extends StdOutTest { @Test public void testMix() { final Stew stew = new Stew(1, 2, 3, 4); - final String message = "Mixing the stew we find: 1 potatoes, 2 carrots, 3 meat and 4 peppers"; + final String expectedMessage = "Mixing the stew we find: 1 potatoes, 2 carrots, 3 meat and 4 peppers"; - final InOrder inOrder = inOrder(getStdOutMock()); for (int i = 0; i < 20; i++) { stew.mix(); - inOrder.verify(getStdOutMock()).println(message); + assertEquals(expectedMessage, appender.getLastMessage()); } - inOrder.verifyNoMoreInteractions(); + assertEquals(20, appender.getLogSize()); } /** @@ -60,15 +72,12 @@ public class ImmutableStewTest extends StdOutTest { final Stew stew = new Stew(1, 2, 3, 4); stew.mix(); - verify(getStdOutMock()) - .println("Mixing the stew we find: 1 potatoes, 2 carrots, 3 meat and 4 peppers"); + assertEquals("Mixing the stew we find: 1 potatoes, 2 carrots, 3 meat and 4 peppers", appender.getLastMessage()); stew.taste(); - verify(getStdOutMock()).println("Tasting the stew"); + assertEquals("Tasting the stew", appender.getLastMessage()); stew.mix(); - verify(getStdOutMock()) - .println("Mixing the stew we find: 0 potatoes, 1 carrots, 2 meat and 3 peppers"); - + assertEquals("Mixing the stew we find: 0 potatoes, 1 carrots, 2 meat and 3 peppers", appender.getLastMessage()); } -} \ No newline at end of file +} diff --git a/private-class-data/src/test/java/com/iluwatar/privateclassdata/StdOutTest.java b/private-class-data/src/test/java/com/iluwatar/privateclassdata/StdOutTest.java deleted file mode 100644 index f90551020..000000000 --- a/private-class-data/src/test/java/com/iluwatar/privateclassdata/StdOutTest.java +++ /dev/null @@ -1,75 +0,0 @@ -/** - * 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.privateclassdata; - -import org.junit.After; -import org.junit.Before; - -import java.io.PrintStream; - -import static org.mockito.Mockito.mock; - -/** - * Date: 12/10/15 - 8:37 PM - * - * @author Jeroen Meulemeester - */ -public abstract class StdOutTest { - - /** - * The mocked standard out {@link PrintStream}, required since some actions don't have any - * influence on accessible objects, except for writing to std-out using {@link System#out} - */ - private final PrintStream stdOutMock = mock(PrintStream.class); - - /** - * Keep the original std-out so it can be restored after the test - */ - private final PrintStream stdOutOrig = System.out; - - /** - * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test - */ - @Before - public void setUp() { - System.setOut(this.stdOutMock); - } - - /** - * Removed the mocked std-out {@link PrintStream} again from the {@link System} class - */ - @After - public void tearDown() { - System.setOut(this.stdOutOrig); - } - - /** - * Get the mocked stdOut {@link PrintStream} - * - * @return The stdOut print stream mock, renewed before each test - */ - final PrintStream getStdOutMock() { - return this.stdOutMock; - } - -} diff --git a/private-class-data/src/test/java/com/iluwatar/privateclassdata/StewTest.java b/private-class-data/src/test/java/com/iluwatar/privateclassdata/StewTest.java index a894e4ae0..f2e3c5fad 100644 --- a/private-class-data/src/test/java/com/iluwatar/privateclassdata/StewTest.java +++ b/private-class-data/src/test/java/com/iluwatar/privateclassdata/StewTest.java @@ -22,17 +22,31 @@ */ package com.iluwatar.privateclassdata; +import com.iluwatar.privateclassdata.utils.InMemoryAppender; +import org.junit.After; +import org.junit.Before; import org.junit.Test; -import org.mockito.InOrder; -import static org.mockito.Mockito.inOrder; +import static org.junit.Assert.assertEquals; /** * Date: 12/27/15 - 10:46 PM * * @author Jeroen Meulemeester */ -public class StewTest extends StdOutTest { +public class StewTest { + + private InMemoryAppender appender; + + @Before + public void setUp() { + appender = new InMemoryAppender(); + } + + @After + public void tearDown() { + appender.stop(); + } /** * Verify if mixing the stew doesn't change the internal state @@ -43,13 +57,12 @@ public class StewTest extends StdOutTest { final String expectedMessage = "Mixing the immutable stew we find: 1 potatoes, " + "2 carrots, 3 meat and 4 peppers"; - final InOrder inOrder = inOrder(getStdOutMock()); for (int i = 0; i < 20; i++) { stew.mix(); - inOrder.verify(getStdOutMock()).println(expectedMessage); + assertEquals(expectedMessage, appender.getLastMessage()); } - inOrder.verifyNoMoreInteractions(); + assertEquals(20, appender.getLogSize()); } -} \ No newline at end of file +} diff --git a/private-class-data/src/test/java/com/iluwatar/privateclassdata/utils/InMemoryAppender.java b/private-class-data/src/test/java/com/iluwatar/privateclassdata/utils/InMemoryAppender.java new file mode 100644 index 000000000..4b2def101 --- /dev/null +++ b/private-class-data/src/test/java/com/iluwatar/privateclassdata/utils/InMemoryAppender.java @@ -0,0 +1,53 @@ +/** + * 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.privateclassdata.utils; + +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.AppenderBase; +import org.slf4j.LoggerFactory; + +import java.util.LinkedList; +import java.util.List; + +public class InMemoryAppender extends AppenderBase { + private List log = new LinkedList<>(); + + public InMemoryAppender() { + ((Logger) LoggerFactory.getLogger("root")).addAppender(this); + start(); + } + + @Override + protected void append(ILoggingEvent eventObject) { + log.add(eventObject); + } + + public int getLogSize() { + return log.size(); + } + + public String getLastMessage() { + return log.get(log.size() - 1).getFormattedMessage(); + } +} diff --git a/producer-consumer/src/test/java/com/iluwatar/producer/consumer/ConsumerTest.java b/producer-consumer/src/test/java/com/iluwatar/producer/consumer/ConsumerTest.java index 2ca547a0b..dd725df75 100644 --- a/producer-consumer/src/test/java/com/iluwatar/producer/consumer/ConsumerTest.java +++ b/producer-consumer/src/test/java/com/iluwatar/producer/consumer/ConsumerTest.java @@ -23,18 +23,15 @@ package com.iluwatar.producer.consumer; import org.junit.Test; -import org.mockito.InOrder; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.*; /** * Date: 12/27/15 - 11:01 PM * * @author Jeroen Meulemeester */ -public class ConsumerTest extends StdOutTest { +public class ConsumerTest { private static final int ITEM_COUNT = 5; @@ -48,14 +45,11 @@ public class ConsumerTest extends StdOutTest { reset(queue); // Don't count the preparation above as interactions with the queue final Consumer consumer = new Consumer("consumer", queue); - final InOrder inOrder = inOrder(getStdOutMock()); for (int id = 0; id < ITEM_COUNT; id++) { consumer.consume(); - inOrder.verify(getStdOutMock()) - .println("Consumer [consumer] consume item [" + id + "] produced by [producer]"); } - inOrder.verifyNoMoreInteractions(); + verify(queue, times(ITEM_COUNT)).take(); } } diff --git a/producer-consumer/src/test/java/com/iluwatar/producer/consumer/StdOutTest.java b/producer-consumer/src/test/java/com/iluwatar/producer/consumer/StdOutTest.java deleted file mode 100644 index 1e1c41f75..000000000 --- a/producer-consumer/src/test/java/com/iluwatar/producer/consumer/StdOutTest.java +++ /dev/null @@ -1,75 +0,0 @@ -/** - * 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.producer.consumer; - -import org.junit.After; -import org.junit.Before; - -import java.io.PrintStream; - -import static org.mockito.Mockito.mock; - -/** - * Date: 12/10/15 - 8:37 PM - * - * @author Jeroen Meulemeester - */ -public abstract class StdOutTest { - - /** - * The mocked standard out {@link PrintStream}, required since some actions don't have any - * influence on accessible objects, except for writing to std-out using {@link System#out} - */ - private final PrintStream stdOutMock = mock(PrintStream.class); - - /** - * Keep the original std-out so it can be restored after the test - */ - private final PrintStream stdOutOrig = System.out; - - /** - * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test - */ - @Before - public void setUp() { - System.setOut(this.stdOutMock); - } - - /** - * Removed the mocked std-out {@link PrintStream} again from the {@link System} class - */ - @After - public void tearDown() { - System.setOut(this.stdOutOrig); - } - - /** - * Get the mocked stdOut {@link PrintStream} - * - * @return The stdOut print stream mock, renewed before each test - */ - final PrintStream getStdOutMock() { - return this.stdOutMock; - } - -} diff --git a/proxy/src/test/java/com/iluwatar/proxy/StdOutTest.java b/proxy/src/test/java/com/iluwatar/proxy/StdOutTest.java deleted file mode 100644 index 48831444a..000000000 --- a/proxy/src/test/java/com/iluwatar/proxy/StdOutTest.java +++ /dev/null @@ -1,75 +0,0 @@ -/** - * 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.proxy; - -import org.junit.After; -import org.junit.Before; - -import java.io.PrintStream; - -import static org.mockito.Mockito.mock; - -/** - * Date: 12/10/15 - 8:37 PM - * - * @author Jeroen Meulemeester - */ -public abstract class StdOutTest { - - /** - * The mocked standard out {@link PrintStream}, required since some actions don't have any - * influence on accessible objects, except for writing to std-out using {@link System#out} - */ - private final PrintStream stdOutMock = mock(PrintStream.class); - - /** - * Keep the original std-out so it can be restored after the test - */ - private final PrintStream stdOutOrig = System.out; - - /** - * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test - */ - @Before - public void setUp() { - System.setOut(this.stdOutMock); - } - - /** - * Removed the mocked std-out {@link PrintStream} again from the {@link System} class - */ - @After - public void tearDown() { - System.setOut(this.stdOutOrig); - } - - /** - * Get the mocked stdOut {@link PrintStream} - * - * @return The stdOut print stream mock, renewed before each test - */ - final PrintStream getStdOutMock() { - return this.stdOutMock; - } - -} diff --git a/proxy/src/test/java/com/iluwatar/proxy/WizardTowerProxyTest.java b/proxy/src/test/java/com/iluwatar/proxy/WizardTowerProxyTest.java index b87b7a0bc..921624f63 100644 --- a/proxy/src/test/java/com/iluwatar/proxy/WizardTowerProxyTest.java +++ b/proxy/src/test/java/com/iluwatar/proxy/WizardTowerProxyTest.java @@ -22,17 +22,32 @@ */ package com.iluwatar.proxy; +import com.iluwatar.proxy.utils.InMemoryAppender; +import org.junit.After; +import org.junit.Before; import org.junit.Test; -import org.mockito.InOrder; -import static org.mockito.Mockito.inOrder; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; /** * Date: 12/28/15 - 9:18 PM * * @author Jeroen Meulemeester */ -public class WizardTowerProxyTest extends StdOutTest { +public class WizardTowerProxyTest { + + private InMemoryAppender appender; + + @Before + public void setUp() { + appender = new InMemoryAppender(); + } + + @After + public void tearDown() { + appender.stop(); + } @Test public void testEnter() throws Exception { @@ -48,13 +63,11 @@ public class WizardTowerProxyTest extends StdOutTest { tower.enter(wizard); } - final InOrder inOrder = inOrder(getStdOutMock()); - inOrder.verify(getStdOutMock()).println("Gandalf enters the tower."); - inOrder.verify(getStdOutMock()).println("Dumbledore enters the tower."); - inOrder.verify(getStdOutMock()).println("Oz enters the tower."); - inOrder.verify(getStdOutMock()).println("Merlin is not allowed to enter!"); - inOrder.verifyNoMoreInteractions(); - + assertTrue(appender.logContains("Gandalf enters the tower.")); + assertTrue(appender.logContains("Dumbledore enters the tower.")); + assertTrue(appender.logContains("Oz enters the tower.")); + assertTrue(appender.logContains("Merlin is not allowed to enter!")); + assertEquals(4, appender.getLogSize()); } -} \ No newline at end of file +} diff --git a/proxy/src/test/java/com/iluwatar/proxy/WizardTowerTest.java b/proxy/src/test/java/com/iluwatar/proxy/WizardTowerTest.java index 9996434f5..ab56115ca 100644 --- a/proxy/src/test/java/com/iluwatar/proxy/WizardTowerTest.java +++ b/proxy/src/test/java/com/iluwatar/proxy/WizardTowerTest.java @@ -22,17 +22,32 @@ */ package com.iluwatar.proxy; +import com.iluwatar.proxy.utils.InMemoryAppender; +import org.junit.After; +import org.junit.Before; import org.junit.Test; -import org.mockito.InOrder; -import static org.mockito.Mockito.inOrder; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; /** * Date: 12/28/15 - 9:18 PM * * @author Jeroen Meulemeester */ -public class WizardTowerTest extends StdOutTest { +public class WizardTowerTest { + + private InMemoryAppender appender; + + @Before + public void setUp() { + appender = new InMemoryAppender(WizardTower.class); + } + + @After + public void tearDown() { + appender.stop(); + } @Test public void testEnter() throws Exception { @@ -48,13 +63,11 @@ public class WizardTowerTest extends StdOutTest { tower.enter(wizard); } - final InOrder inOrder = inOrder(getStdOutMock()); - inOrder.verify(getStdOutMock()).println("Gandalf enters the tower."); - inOrder.verify(getStdOutMock()).println("Dumbledore enters the tower."); - inOrder.verify(getStdOutMock()).println("Oz enters the tower."); - inOrder.verify(getStdOutMock()).println("Merlin enters the tower."); - inOrder.verifyNoMoreInteractions(); - + assertTrue(appender.logContains("Gandalf enters the tower.")); + assertTrue(appender.logContains("Dumbledore enters the tower.")); + assertTrue(appender.logContains("Oz enters the tower.")); + assertTrue(appender.logContains("Merlin enters the tower.")); + assertEquals(4, appender.getLogSize()); } -} \ No newline at end of file +} diff --git a/proxy/src/test/java/com/iluwatar/proxy/utils/InMemoryAppender.java b/proxy/src/test/java/com/iluwatar/proxy/utils/InMemoryAppender.java new file mode 100644 index 000000000..857d3e548 --- /dev/null +++ b/proxy/src/test/java/com/iluwatar/proxy/utils/InMemoryAppender.java @@ -0,0 +1,58 @@ +/** + * 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.proxy.utils; + +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.AppenderBase; +import org.slf4j.LoggerFactory; + +import java.util.LinkedList; +import java.util.List; + +public class InMemoryAppender extends AppenderBase { + private List log = new LinkedList<>(); + + public InMemoryAppender(Class clazz) { + ((Logger) LoggerFactory.getLogger(clazz)).addAppender(this); + start(); + } + + public InMemoryAppender() { + ((Logger) LoggerFactory.getLogger("root")).addAppender(this); + start(); + } + + @Override + protected void append(ILoggingEvent eventObject) { + log.add(eventObject); + } + + public boolean logContains(String message) { + return log.stream().anyMatch(event -> event.getFormattedMessage().equals(message)); + } + + public int getLogSize() { + return log.size(); + } +} diff --git a/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/ReaderAndWriterTest.java b/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/ReaderAndWriterTest.java index dc8feb04f..7d0ac70bf 100644 --- a/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/ReaderAndWriterTest.java +++ b/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/ReaderAndWriterTest.java @@ -23,21 +23,35 @@ package com.iluwatar.reader.writer.lock; -import static org.mockito.Mockito.inOrder; +import com.iluwatar.reader.writer.lock.utils.InMemoryAppender; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; -import org.junit.Test; -import org.mockito.InOrder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import static org.junit.Assert.assertTrue; /** * @author hongshuwei@gmail.com */ -public class ReaderAndWriterTest extends StdOutTest { +public class ReaderAndWriterTest { + + private InMemoryAppender appender; + + @Before + public void setUp() { + appender = new InMemoryAppender(); + } + + @After + public void tearDown() { + appender.stop(); + } private static final Logger LOGGER = LoggerFactory.getLogger(ReaderAndWriterTest.class); @@ -65,11 +79,10 @@ public class ReaderAndWriterTest extends StdOutTest { LOGGER.error("Error waiting for ExecutorService shutdown", e); } - final InOrder inOrder = inOrder(getStdOutMock()); - inOrder.verify(getStdOutMock()).println("Reader 1 begin"); - inOrder.verify(getStdOutMock()).println("Reader 1 finish"); - inOrder.verify(getStdOutMock()).println("Writer 1 begin"); - inOrder.verify(getStdOutMock()).println("Writer 1 finish"); + assertTrue(appender.logContains("Reader 1 begin")); + assertTrue(appender.logContains("Reader 1 finish")); + assertTrue(appender.logContains("Writer 1 begin")); + assertTrue(appender.logContains("Writer 1 finish")); } /** @@ -96,11 +109,10 @@ public class ReaderAndWriterTest extends StdOutTest { LOGGER.error("Error waiting for ExecutorService shutdown", e); } - final InOrder inOrder = inOrder(getStdOutMock()); - inOrder.verify(getStdOutMock()).println("Writer 1 begin"); - inOrder.verify(getStdOutMock()).println("Writer 1 finish"); - inOrder.verify(getStdOutMock()).println("Reader 1 begin"); - inOrder.verify(getStdOutMock()).println("Reader 1 finish"); + assertTrue(appender.logContains("Writer 1 begin")); + assertTrue(appender.logContains("Writer 1 finish")); + assertTrue(appender.logContains("Reader 1 begin")); + assertTrue(appender.logContains("Reader 1 finish")); } } diff --git a/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/ReaderTest.java b/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/ReaderTest.java index a51120bf8..9830eda67 100644 --- a/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/ReaderTest.java +++ b/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/ReaderTest.java @@ -22,22 +22,36 @@ */ package com.iluwatar.reader.writer.lock; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.spy; +import com.iluwatar.reader.writer.lock.utils.InMemoryAppender; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; -import org.junit.Test; -import org.mockito.InOrder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import static junit.framework.TestCase.assertTrue; +import static org.mockito.Mockito.spy; /** * @author hongshuwei@gmail.com */ -public class ReaderTest extends StdOutTest { +public class ReaderTest { + + private InMemoryAppender appender; + + @Before + public void setUp() { + appender = new InMemoryAppender(Reader.class); + } + + @After + public void tearDown() { + appender.stop(); + } private static final Logger LOGGER = LoggerFactory.getLogger(ReaderTest.class); @@ -66,11 +80,9 @@ public class ReaderTest extends StdOutTest { // Read operation will hold the read lock 250 milliseconds, so here we prove that multiple reads // can be performed in the same time. - final InOrder inOrder = inOrder(getStdOutMock()); - inOrder.verify(getStdOutMock()).println("Reader 1 begin"); - inOrder.verify(getStdOutMock()).println("Reader 2 begin"); - inOrder.verify(getStdOutMock()).println("Reader 1 finish"); - inOrder.verify(getStdOutMock()).println("Reader 2 finish"); - + assertTrue(appender.logContains("Reader 1 begin")); + assertTrue(appender.logContains("Reader 2 begin")); + assertTrue(appender.logContains("Reader 1 finish")); + assertTrue(appender.logContains("Reader 2 finish")); } } diff --git a/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/StdOutTest.java b/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/StdOutTest.java deleted file mode 100644 index 7a1af09c0..000000000 --- a/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/StdOutTest.java +++ /dev/null @@ -1,76 +0,0 @@ -/** - * 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.reader.writer.lock; - -import org.junit.After; -import org.junit.Before; - -import java.io.PrintStream; - -import static org.mockito.Mockito.mock; - -/** - * Date: 12/10/15 - 8:37 PM - * - * @author Jeroen Meulemeester - */ -public abstract class StdOutTest { - - /** - * The mocked standard out {@link PrintStream}, required since some actions don't have any - * influence on accessible objects, except for writing to std-out using {@link System#out} - */ - private final PrintStream stdOutMock = mock(PrintStream.class); - - /** - * Keep the original std-out so it can be restored after the test - */ - private final PrintStream stdOutOrig = System.out; - - /** - * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test - */ - @Before - public void setUp() { - System.setOut(this.stdOutMock); - } - - /** - * Removed the mocked std-out {@link PrintStream} again from the {@link System} class - */ - @After - public void tearDown() { - System.setOut(this.stdOutOrig); - } - - /** - * Get the mocked stdOut {@link PrintStream} - * - * @return The stdOut print stream mock, renewed before each test - */ - final PrintStream getStdOutMock() { - return this.stdOutMock; - } - -} diff --git a/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/WriterTest.java b/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/WriterTest.java index 729b5eff3..4bf6d0747 100644 --- a/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/WriterTest.java +++ b/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/WriterTest.java @@ -22,22 +22,36 @@ */ package com.iluwatar.reader.writer.lock; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.spy; +import com.iluwatar.reader.writer.lock.utils.InMemoryAppender; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; -import org.junit.Test; -import org.mockito.InOrder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.spy; /** * @author hongshuwei@gmail.com */ -public class WriterTest extends StdOutTest { +public class WriterTest { + + private InMemoryAppender appender; + + @Before + public void setUp() { + appender = new InMemoryAppender(Writer.class); + } + + @After + public void tearDown() { + appender.stop(); + } private static final Logger LOGGER = LoggerFactory.getLogger(WriterTest.class); @@ -67,10 +81,9 @@ public class WriterTest extends StdOutTest { // Write operation will hold the write lock 250 milliseconds, so here we verify that when two // writer execute concurrently, the second writer can only writes only when the first one is // finished. - final InOrder inOrder = inOrder(getStdOutMock()); - inOrder.verify(getStdOutMock()).println("Writer 1 begin"); - inOrder.verify(getStdOutMock()).println("Writer 1 finish"); - inOrder.verify(getStdOutMock()).println("Writer 2 begin"); - inOrder.verify(getStdOutMock()).println("Writer 2 finish"); + assertTrue(appender.logContains("Writer 1 begin")); + assertTrue(appender.logContains("Writer 1 finish")); + assertTrue(appender.logContains("Writer 2 begin")); + assertTrue(appender.logContains("Writer 2 finish")); } } diff --git a/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/utils/InMemoryAppender.java b/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/utils/InMemoryAppender.java new file mode 100644 index 000000000..44fcb084b --- /dev/null +++ b/reader-writer-lock/src/test/java/com/iluwatar/reader/writer/lock/utils/InMemoryAppender.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.reader.writer.lock.utils; + +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.AppenderBase; +import org.slf4j.LoggerFactory; + +import java.util.LinkedList; +import java.util.List; + +public class InMemoryAppender extends AppenderBase { + private List log = new LinkedList<>(); + + public InMemoryAppender(Class clazz) { + ((Logger) LoggerFactory.getLogger(clazz)).addAppender(this); + start(); + } + + public InMemoryAppender() { + ((Logger) LoggerFactory.getLogger("root")).addAppender(this); + start(); + } + + @Override + protected void append(ILoggingEvent eventObject) { + log.add(eventObject); + } + + public boolean logContains(String message) { + return log.stream().anyMatch(event -> event.getFormattedMessage().equals(message)); + } +} diff --git a/resource-acquisition-is-initialization/src/test/java/com/iluwatar/resource/acquisition/is/initialization/ClosableTest.java b/resource-acquisition-is-initialization/src/test/java/com/iluwatar/resource/acquisition/is/initialization/ClosableTest.java index 55bdaf19c..638b06ecc 100644 --- a/resource-acquisition-is-initialization/src/test/java/com/iluwatar/resource/acquisition/is/initialization/ClosableTest.java +++ b/resource-acquisition-is-initialization/src/test/java/com/iluwatar/resource/acquisition/is/initialization/ClosableTest.java @@ -22,28 +22,64 @@ */ package com.iluwatar.resource.acquisition.is.initialization; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.AppenderBase; +import org.junit.After; +import org.junit.Before; import org.junit.Test; -import org.mockito.InOrder; +import org.slf4j.LoggerFactory; -import static org.mockito.Mockito.inOrder; +import java.util.LinkedList; +import java.util.List; + +import static org.junit.Assert.assertTrue; /** * Date: 12/28/15 - 9:31 PM * * @author Jeroen Meulemeester */ -public class ClosableTest extends StdOutTest { +public class ClosableTest { + + private InMemoryAppender appender; + + @Before + public void setUp() { + appender = new InMemoryAppender(); + } + + @After + public void tearDown() { + appender.stop(); + } @Test public void testOpenClose() throws Exception { - final InOrder inOrder = inOrder(getStdOutMock()); try (final SlidingDoor door = new SlidingDoor(); final TreasureChest chest = new TreasureChest()) { - inOrder.verify(getStdOutMock()).println("Sliding door opens."); - inOrder.verify(getStdOutMock()).println("Treasure chest opens."); + assertTrue(appender.logContains("Sliding door opens.")); + assertTrue(appender.logContains("Treasure chest opens.")); } - inOrder.verify(getStdOutMock()).println("Treasure chest closes."); - inOrder.verify(getStdOutMock()).println("Sliding door closes."); - inOrder.verifyNoMoreInteractions(); + assertTrue(appender.logContains("Treasure chest closes.")); + assertTrue(appender.logContains("Sliding door closes.")); } -} \ No newline at end of file + public class InMemoryAppender extends AppenderBase { + private List log = new LinkedList<>(); + + public InMemoryAppender() { + ((Logger) LoggerFactory.getLogger("root")).addAppender(this); + start(); + } + + @Override + protected void append(ILoggingEvent eventObject) { + log.add(eventObject); + } + + public boolean logContains(String message) { + return log.stream().anyMatch(event -> event.getMessage().equals(message)); + } + } + +} diff --git a/resource-acquisition-is-initialization/src/test/java/com/iluwatar/resource/acquisition/is/initialization/StdOutTest.java b/resource-acquisition-is-initialization/src/test/java/com/iluwatar/resource/acquisition/is/initialization/StdOutTest.java deleted file mode 100644 index 42cb42e6b..000000000 --- a/resource-acquisition-is-initialization/src/test/java/com/iluwatar/resource/acquisition/is/initialization/StdOutTest.java +++ /dev/null @@ -1,75 +0,0 @@ -/** - * 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.resource.acquisition.is.initialization; - -import org.junit.After; -import org.junit.Before; - -import java.io.PrintStream; - -import static org.mockito.Mockito.mock; - -/** - * Date: 12/10/15 - 8:37 PM - * - * @author Jeroen Meulemeester - */ -public abstract class StdOutTest { - - /** - * The mocked standard out {@link PrintStream}, required since some actions don't have any - * influence on accessible objects, except for writing to std-out using {@link System#out} - */ - private final PrintStream stdOutMock = mock(PrintStream.class); - - /** - * Keep the original std-out so it can be restored after the test - */ - private final PrintStream stdOutOrig = System.out; - - /** - * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test - */ - @Before - public void setUp() { - System.setOut(this.stdOutMock); - } - - /** - * Removed the mocked std-out {@link PrintStream} again from the {@link System} class - */ - @After - public void tearDown() { - System.setOut(this.stdOutOrig); - } - - /** - * Get the mocked stdOut {@link PrintStream} - * - * @return The stdOut print stream mock, renewed before each test - */ - final PrintStream getStdOutMock() { - return this.stdOutMock; - } - -} diff --git a/state/src/test/java/com/iluwatar/state/MammothTest.java b/state/src/test/java/com/iluwatar/state/MammothTest.java index 4fe37bfd1..be4c0d892 100644 --- a/state/src/test/java/com/iluwatar/state/MammothTest.java +++ b/state/src/test/java/com/iluwatar/state/MammothTest.java @@ -22,17 +22,19 @@ */ package com.iluwatar.state; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.AppenderBase; import org.junit.After; import org.junit.Before; import org.junit.Test; -import org.mockito.InOrder; -import org.mockito.Mockito; +import org.slf4j.LoggerFactory; -import java.io.PrintStream; +import java.util.LinkedList; +import java.util.List; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; -import static org.mockito.Mockito.mock; /** * Date: 12/29/15 - 8:27 PM @@ -41,31 +43,16 @@ import static org.mockito.Mockito.mock; */ public class MammothTest { - /** - * The mocked standard out {@link PrintStream}, required since some actions don't have any - * influence on accessible objects, except for writing to std-out using {@link System#out} - */ - private final PrintStream stdOutMock = mock(PrintStream.class); + private InMemoryAppender appender; - /** - * Keep the original std-out so it can be restored after the test - */ - private final PrintStream stdOutOrig = System.out; - - /** - * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test - */ @Before public void setUp() { - System.setOut(this.stdOutMock); + appender = new InMemoryAppender(); } - /** - * Removed the mocked std-out {@link PrintStream} again from the {@link System} class - */ @After public void tearDown() { - System.setOut(this.stdOutOrig); + appender.stop(); } /** @@ -74,28 +61,27 @@ public class MammothTest { */ @Test public void testTimePasses() { - final InOrder inOrder = Mockito.inOrder(this.stdOutMock); final Mammoth mammoth = new Mammoth(); mammoth.observe(); - inOrder.verify(this.stdOutMock).println("The mammoth is calm and peaceful."); - inOrder.verifyNoMoreInteractions(); + assertEquals("The mammoth is calm and peaceful.", appender.getLastMessage()); + assertEquals(1 , appender.getLogSize()); mammoth.timePasses(); - inOrder.verify(this.stdOutMock).println("The mammoth gets angry!"); - inOrder.verifyNoMoreInteractions(); + assertEquals("The mammoth gets angry!", appender.getLastMessage()); + assertEquals(2 , appender.getLogSize()); mammoth.observe(); - inOrder.verify(this.stdOutMock).println("The mammoth is furious!"); - inOrder.verifyNoMoreInteractions(); + assertEquals("The mammoth is furious!", appender.getLastMessage()); + assertEquals(3 , appender.getLogSize()); mammoth.timePasses(); - inOrder.verify(this.stdOutMock).println("The mammoth calms down."); - inOrder.verifyNoMoreInteractions(); + assertEquals("The mammoth calms down.", appender.getLastMessage()); + assertEquals(4 , appender.getLogSize()); mammoth.observe(); - inOrder.verify(this.stdOutMock).println("The mammoth is calm and peaceful."); - inOrder.verifyNoMoreInteractions(); + assertEquals("The mammoth is calm and peaceful.", appender.getLastMessage()); + assertEquals(5 , appender.getLogSize()); } @@ -109,4 +95,26 @@ public class MammothTest { assertEquals("The mammoth", toString); } -} \ No newline at end of file + private class InMemoryAppender extends AppenderBase { + private List log = new LinkedList<>(); + + public InMemoryAppender() { + ((Logger) LoggerFactory.getLogger("root")).addAppender(this); + start(); + } + + @Override + protected void append(ILoggingEvent eventObject) { + log.add(eventObject); + } + + public int getLogSize() { + return log.size(); + } + + public String getLastMessage() { + return log.get(log.size() - 1).getFormattedMessage(); + } + } + +} diff --git a/strategy/src/test/java/com/iluwatar/strategy/DragonSlayingStrategyTest.java b/strategy/src/test/java/com/iluwatar/strategy/DragonSlayingStrategyTest.java index 35f4c1a82..d04e0f5c1 100644 --- a/strategy/src/test/java/com/iluwatar/strategy/DragonSlayingStrategyTest.java +++ b/strategy/src/test/java/com/iluwatar/strategy/DragonSlayingStrategyTest.java @@ -22,19 +22,22 @@ */ package com.iluwatar.strategy; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.AppenderBase; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; +import org.slf4j.LoggerFactory; -import java.io.PrintStream; import java.util.Arrays; import java.util.Collection; +import java.util.LinkedList; +import java.util.List; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.junit.Assert.assertEquals; /** * Date: 12/29/15 - 10:58 PM @@ -71,20 +74,22 @@ public class DragonSlayingStrategyTest { private final DragonSlayingStrategy strategy; /** - * The expected action on the std-out + * The expected action in the log */ private final String expectedResult; - /** - * The mocked standard out {@link PrintStream}, required since some actions don't have any - * influence on accessible objects, except for writing to std-out using {@link System#out} - */ - private final PrintStream stdOutMock = mock(PrintStream.class); + private InMemoryAppender appender; + + @Before + public void setUp() { + appender = new InMemoryAppender(); + } + + @After + public void tearDown() { + appender.stop(); + } - /** - * Keep the original std-out so it can be restored after the test - */ - private final PrintStream stdOutOrig = System.out; /** * Create a new test instance for the given strategy @@ -97,30 +102,35 @@ public class DragonSlayingStrategyTest { this.expectedResult = expectedResult; } - /** - * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test - */ - @Before - public void setUp() { - System.setOut(this.stdOutMock); - } - - /** - * Removed the mocked std-out {@link PrintStream} again from the {@link System} class - */ - @After - public void tearDown() { - System.setOut(this.stdOutOrig); - } - /** * Test if executing the strategy gives the correct response */ @Test public void testExecute() { this.strategy.execute(); - verify(this.stdOutMock).println(this.expectedResult); - verifyNoMoreInteractions(this.stdOutMock); + assertEquals(this.expectedResult, appender.getLastMessage()); + assertEquals(1, appender.getLogSize()); } -} \ No newline at end of file + private class InMemoryAppender extends AppenderBase { + private List log = new LinkedList<>(); + + public InMemoryAppender() { + ((Logger) LoggerFactory.getLogger("root")).addAppender(this); + start(); + } + + @Override + protected void append(ILoggingEvent eventObject) { + log.add(eventObject); + } + + public int getLogSize() { + return log.size(); + } + + public String getLastMessage() { + return log.get(log.size() - 1).getFormattedMessage(); + } + } +} diff --git a/template-method/src/test/java/com/iluwatar/templatemethod/StealingMethodTest.java b/template-method/src/test/java/com/iluwatar/templatemethod/StealingMethodTest.java index e0cb90d42..0ea337f93 100644 --- a/template-method/src/test/java/com/iluwatar/templatemethod/StealingMethodTest.java +++ b/template-method/src/test/java/com/iluwatar/templatemethod/StealingMethodTest.java @@ -22,19 +22,19 @@ */ package com.iluwatar.templatemethod; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.AppenderBase; import org.junit.After; import org.junit.Before; import org.junit.Test; -import org.mockito.InOrder; +import org.slf4j.LoggerFactory; -import java.io.PrintStream; +import java.util.LinkedList; +import java.util.List; import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.verifyZeroInteractions; +import static org.junit.Assert.assertTrue; /** * Date: 12/30/15 - 18:12 PM @@ -43,6 +43,18 @@ import static org.mockito.Mockito.verifyZeroInteractions; */ public abstract class StealingMethodTest { + private InMemoryAppender appender; + + @Before + public void setUp() { + appender = new InMemoryAppender(); + } + + @After + public void tearDown() { + appender.stop(); + } + /** * The tested stealing method */ @@ -68,17 +80,6 @@ public abstract class StealingMethodTest { */ private final String expectedStealMethod; - /** - * The mocked standard out {@link PrintStream}, required since some actions don't have any - * influence on accessible objects, except for writing to std-out using {@link System#out} - */ - private final PrintStream stdOutMock = mock(PrintStream.class); - - /** - * Keep the original std-out so it can be restored after the test - */ - private final PrintStream stdOutOrig = System.out; - /** * Create a new test for the given stealing method, together with the expected results * @@ -98,22 +99,6 @@ public abstract class StealingMethodTest { this.expectedStealMethod = expectedStealMethod; } - /** - * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test - */ - @Before - public void setUp() { - System.setOut(this.stdOutMock); - } - - /** - * Removed the mocked std-out {@link PrintStream} again from the {@link System} class - */ - @After - public void tearDown() { - System.setOut(this.stdOutOrig); - } - /** * Verify if the thief picks the correct target */ @@ -127,11 +112,11 @@ public abstract class StealingMethodTest { */ @Test public void testConfuseTarget() { - verifyZeroInteractions(this.stdOutMock); + assertEquals(0, appender.getLogSize()); this.method.confuseTarget(this.expectedTarget); - verify(this.stdOutMock).println(this.expectedConfuseMethod); - verifyNoMoreInteractions(this.stdOutMock); + assertEquals(this.expectedConfuseMethod, appender.getLastMessage()); + assertEquals(1, appender.getLogSize()); } /** @@ -139,11 +124,11 @@ public abstract class StealingMethodTest { */ @Test public void testStealTheItem() { - verifyZeroInteractions(this.stdOutMock); + assertEquals(0, appender.getLogSize()); this.method.stealTheItem(this.expectedTarget); - verify(this.stdOutMock).println(this.expectedStealMethod); - verifyNoMoreInteractions(this.stdOutMock); + assertEquals(this.expectedStealMethod, appender.getLastMessage()); + assertEquals(1, appender.getLogSize()); } /** @@ -151,14 +136,37 @@ public abstract class StealingMethodTest { */ @Test public void testSteal() { - final InOrder inOrder = inOrder(this.stdOutMock); - this.method.steal(); - inOrder.verify(this.stdOutMock).println(this.expectedTargetResult); - inOrder.verify(this.stdOutMock).println(this.expectedConfuseMethod); - inOrder.verify(this.stdOutMock).println(this.expectedStealMethod); - inOrder.verifyNoMoreInteractions(); + assertTrue(appender.logContains(this.expectedTargetResult)); + assertTrue(appender.logContains(this.expectedConfuseMethod)); + assertTrue(appender.logContains(this.expectedStealMethod)); + assertEquals(3, appender.getLogSize()); } -} \ No newline at end of file + private class InMemoryAppender extends AppenderBase { + private List log = new LinkedList<>(); + + public InMemoryAppender() { + ((Logger) LoggerFactory.getLogger("root")).addAppender(this); + start(); + } + + @Override + protected void append(ILoggingEvent eventObject) { + log.add(eventObject); + } + + public int getLogSize() { + return log.size(); + } + + public String getLastMessage() { + return log.get(log.size() - 1).getFormattedMessage(); + } + + public boolean logContains(String message) { + return log.stream().anyMatch(event -> event.getFormattedMessage().equals(message)); + } + } +} diff --git a/twin/src/test/java/com/iluwatar/twin/BallItemTest.java b/twin/src/test/java/com/iluwatar/twin/BallItemTest.java index 4bb9a2111..439a64da1 100644 --- a/twin/src/test/java/com/iluwatar/twin/BallItemTest.java +++ b/twin/src/test/java/com/iluwatar/twin/BallItemTest.java @@ -22,20 +22,40 @@ */ package com.iluwatar.twin; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.AppenderBase; +import org.junit.After; +import org.junit.Before; import org.junit.Test; import org.mockito.InOrder; +import org.slf4j.LoggerFactory; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; +import java.util.LinkedList; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.*; /** * Date: 12/30/15 - 18:44 PM * * @author Jeroen Meulemeester */ -public class BallItemTest extends StdOutTest { +public class BallItemTest { + + private InMemoryAppender appender; + + @Before + public void setUp() { + appender = new InMemoryAppender(); + } + + @After + public void tearDown() { + appender.stop(); + } @Test public void testClick() { @@ -63,10 +83,11 @@ public class BallItemTest extends StdOutTest { ballItem.setTwin(ballThread); ballItem.draw(); - verify(getStdOutMock()).println("draw"); - verify(getStdOutMock()).println("doDraw"); + assertTrue(appender.logContains("draw")); + assertTrue(appender.logContains("doDraw")); - verifyNoMoreInteractions(ballThread, getStdOutMock()); + verifyNoMoreInteractions(ballThread); + assertEquals(2, appender.getLogSize()); } @Test @@ -76,9 +97,32 @@ public class BallItemTest extends StdOutTest { ballItem.setTwin(ballThread); ballItem.move(); - verify(getStdOutMock()).println("move"); + assertTrue(appender.logContains("move")); - verifyNoMoreInteractions(ballThread, getStdOutMock()); + verifyNoMoreInteractions(ballThread); + assertEquals(1, appender.getLogSize()); } -} \ No newline at end of file + public class InMemoryAppender extends AppenderBase { + private List log = new LinkedList<>(); + + public InMemoryAppender() { + ((Logger) LoggerFactory.getLogger("root")).addAppender(this); + start(); + } + + @Override + protected void append(ILoggingEvent eventObject) { + log.add(eventObject); + } + + public boolean logContains(String message) { + return log.stream().anyMatch(event -> event.getMessage().equals(message)); + } + + public int getLogSize() { + return log.size(); + } + } + +} diff --git a/twin/src/test/java/com/iluwatar/twin/StdOutTest.java b/twin/src/test/java/com/iluwatar/twin/StdOutTest.java deleted file mode 100644 index b3baf8abd..000000000 --- a/twin/src/test/java/com/iluwatar/twin/StdOutTest.java +++ /dev/null @@ -1,75 +0,0 @@ -/** - * 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.twin; - -import org.junit.After; -import org.junit.Before; - -import java.io.PrintStream; - -import static org.mockito.Mockito.mock; - -/** - * Date: 12/10/15 - 8:37 PM - * - * @author Jeroen Meulemeester - */ -public abstract class StdOutTest { - - /** - * The mocked standard out {@link PrintStream}, required since some actions don't have any - * influence on accessible objects, except for writing to std-out using {@link System#out} - */ - private final PrintStream stdOutMock = mock(PrintStream.class); - - /** - * Keep the original std-out so it can be restored after the test - */ - private final PrintStream stdOutOrig = System.out; - - /** - * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test - */ - @Before - public void setUp() { - System.setOut(this.stdOutMock); - } - - /** - * Removed the mocked std-out {@link PrintStream} again from the {@link System} class - */ - @After - public void tearDown() { - System.setOut(this.stdOutOrig); - } - - /** - * Get the mocked stdOut {@link PrintStream} - * - * @return The stdOut print stream mock, renewed before each test - */ - final PrintStream getStdOutMock() { - return this.stdOutMock; - } - -} diff --git a/visitor/src/test/java/com/iluwatar/visitor/StdOutTest.java b/visitor/src/test/java/com/iluwatar/visitor/StdOutTest.java deleted file mode 100644 index 075f235f5..000000000 --- a/visitor/src/test/java/com/iluwatar/visitor/StdOutTest.java +++ /dev/null @@ -1,75 +0,0 @@ -/** - * 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.visitor; - -import org.junit.After; -import org.junit.Before; - -import java.io.PrintStream; - -import static org.mockito.Mockito.mock; - -/** - * Date: 12/10/15 - 8:37 PM - * - * @author Jeroen Meulemeester - */ -public abstract class StdOutTest { - - /** - * The mocked standard out {@link PrintStream}, required since some actions don't have any - * influence on accessible objects, except for writing to std-out using {@link System#out} - */ - private final PrintStream stdOutMock = mock(PrintStream.class); - - /** - * Keep the original std-out so it can be restored after the test - */ - private final PrintStream stdOutOrig = System.out; - - /** - * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test - */ - @Before - public void setUp() { - System.setOut(this.stdOutMock); - } - - /** - * Removed the mocked std-out {@link PrintStream} again from the {@link System} class - */ - @After - public void tearDown() { - System.setOut(this.stdOutOrig); - } - - /** - * Get the mocked stdOut {@link PrintStream} - * - * @return The stdOut print stream mock, renewed before each test - */ - final PrintStream getStdOutMock() { - return this.stdOutMock; - } - -} diff --git a/visitor/src/test/java/com/iluwatar/visitor/VisitorTest.java b/visitor/src/test/java/com/iluwatar/visitor/VisitorTest.java index 4a131bbf2..a0c8b4eea 100644 --- a/visitor/src/test/java/com/iluwatar/visitor/VisitorTest.java +++ b/visitor/src/test/java/com/iluwatar/visitor/VisitorTest.java @@ -22,19 +22,38 @@ */ package com.iluwatar.visitor; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.AppenderBase; +import org.junit.After; +import org.junit.Before; import org.junit.Test; +import org.slf4j.LoggerFactory; +import java.util.LinkedList; +import java.util.List; import java.util.Optional; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.junit.Assert.assertEquals; /** * Date: 12/30/15 - 18:59 PM * * @author Jeroen Meulemeester */ -public abstract class VisitorTest extends StdOutTest { +public abstract class VisitorTest { + + private InMemoryAppender appender; + + @Before + public void setUp() { + appender = new InMemoryAppender(); + } + + @After + public void tearDown() { + appender.stop(); + } /** * The tested visitor instance @@ -76,27 +95,48 @@ public abstract class VisitorTest extends StdOutTest { public void testVisitCommander() { this.visitor.visitCommander(new Commander()); if (this.commanderResponse.isPresent()) { - verify(getStdOutMock()).println(this.commanderResponse.get()); + assertEquals(this.commanderResponse.get(), appender.getLastMessage()); + assertEquals(1, appender.getLogSize()); } - verifyNoMoreInteractions(getStdOutMock()); } @Test public void testVisitSergeant() { this.visitor.visitSergeant(new Sergeant()); if (this.sergeantResponse.isPresent()) { - verify(getStdOutMock()).println(this.sergeantResponse.get()); + assertEquals(this.sergeantResponse.get(), appender.getLastMessage()); + assertEquals(1, appender.getLogSize()); } - verifyNoMoreInteractions(getStdOutMock()); } @Test public void testVisitSoldier() { this.visitor.visitSoldier(new Soldier()); if (this.soldierResponse.isPresent()) { - verify(getStdOutMock()).println(this.soldierResponse.get()); + assertEquals(this.soldierResponse.get(), appender.getLastMessage()); + assertEquals(1, appender.getLogSize()); } - verifyNoMoreInteractions(getStdOutMock()); } + private class InMemoryAppender extends AppenderBase { + private List log = new LinkedList<>(); + + public InMemoryAppender() { + ((Logger) LoggerFactory.getLogger("root")).addAppender(this); + start(); + } + + @Override + protected void append(ILoggingEvent eventObject) { + log.add(eventObject); + } + + public int getLogSize() { + return log.size(); + } + + public String getLastMessage() { + return log.get(log.size() - 1).getFormattedMessage(); + } + } } From b37190a2140555d981161bc0e4ad210452cecde4 Mon Sep 17 00:00:00 2001 From: daniel-bryla Date: Fri, 4 Nov 2016 12:19:32 +0100 Subject: [PATCH 15/37] #502 Introduced logging in new example --- .../main/java/com/iluwatar/caching/App.java | 10 +-- .../com/iluwatar/event/asynchronous/App.java | 61 ++++++++++--------- .../iluwatar/event/asynchronous/Event.java | 13 ++-- .../event/asynchronous/EventManager.java | 12 ++-- .../asynchronous/EventAsynchronousTest.java | 18 +++--- 5 files changed, 64 insertions(+), 50 deletions(-) diff --git a/caching/src/main/java/com/iluwatar/caching/App.java b/caching/src/main/java/com/iluwatar/caching/App.java index 8a4ff0b8d..f30b20e05 100644 --- a/caching/src/main/java/com/iluwatar/caching/App.java +++ b/caching/src/main/java/com/iluwatar/caching/App.java @@ -149,9 +149,9 @@ public class App { * Cache-Aside */ public void useCacheAsideStategy() { - System.out.println("# CachingPolicy.ASIDE"); + LOGGER.info("# CachingPolicy.ASIDE"); AppManager.initCachingPolicy(CachingPolicy.ASIDE); - System.out.println(AppManager.printCacheContent()); + LOGGER.info(AppManager.printCacheContent()); UserAccount userAccount3 = new UserAccount("003", "Adam", "He likes food."); UserAccount userAccount4 = new UserAccount("004", "Rita", "She hates cats."); @@ -160,10 +160,10 @@ public class App { AppManager.save(userAccount4); AppManager.save(userAccount5); - System.out.println(AppManager.printCacheContent()); + LOGGER.info(AppManager.printCacheContent()); AppManager.find("003"); - System.out.println(AppManager.printCacheContent()); + LOGGER.info(AppManager.printCacheContent()); AppManager.find("004"); - System.out.println(AppManager.printCacheContent()); + LOGGER.info(AppManager.printCacheContent()); } } diff --git a/event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/App.java b/event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/App.java index 5a2565940..c7c543434 100644 --- a/event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/App.java +++ b/event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/App.java @@ -16,38 +16,43 @@ */ package com.iluwatar.event.asynchronous; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.io.IOException; import java.io.InputStream; import java.util.Properties; import java.util.Scanner; /** - * + * * This application demonstrates the Event-based Asynchronous pattern. Essentially, users (of the pattern) may * choose to run events in an Asynchronous or Synchronous mode. There can be multiple Asynchronous events running at * once but only one Synchronous event can run at a time. Asynchronous events are synonymous to multi-threads. The key * point here is that the threads run in the background and the user is free to carry on with other processes. Once an * event is complete, the appropriate listener/callback method will be called. The listener then proceeds to carry out * further processing depending on the needs of the user. - * + * * The {@link EventManager} manages the events/threads that the user creates. Currently, the supported event operations * are: start, stop, getStatus. For Synchronous events, the user is unable to * start another (Synchronous) event if one is already running at the time. The running event would have to either be * stopped or completed before a new event can be started. - * + * * The Event-based Asynchronous Pattern makes available the advantages of multithreaded applications while hiding many * of the complex issues inherent in multithreaded design. Using a class that supports this pattern can allow you to:- * (1) Perform time-consuming tasks, such as downloads and database operations, "in the background," without * interrupting your application. (2) Execute multiple operations simultaneously, receiving notifications when each * completes. (3) Wait for resources to become available without stopping ("hanging") your application. (4) Communicate * with pending asynchronous operations using the familiar events-and-delegates model. - * + * * @see EventManager * @see Event * */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + public static final String PROP_FILE_NAME = "config.properties"; boolean interactiveMode = false; @@ -77,7 +82,7 @@ public class App { try { prop.load(inputStream); } catch (IOException e) { - System.out.println(PROP_FILE_NAME + " was not found. Defaulting to non-interactive mode."); + LOGGER.error("{} was not found. Defaulting to non-interactive mode.", PROP_FILE_NAME, e); } String property = prop.getProperty("INTERACTIVE_MODE"); if (property.equalsIgnoreCase("YES")) { @@ -106,27 +111,27 @@ public class App { try { // Create an Asynchronous event. int aEventId = eventManager.createAsync(60); - System.out.println("Async Event [" + aEventId + "] has been created."); + LOGGER.info("Async Event [{}] has been created.", aEventId); eventManager.start(aEventId); - System.out.println("Async Event [" + aEventId + "] has been started."); + LOGGER.info("Async Event [{}] has been started.", aEventId); // Create a Synchronous event. int sEventId = eventManager.create(60); - System.out.println("Sync Event [" + sEventId + "] has been created."); + LOGGER.info("Sync Event [{}] has been created.", sEventId); eventManager.start(sEventId); - System.out.println("Sync Event [" + sEventId + "] has been started."); + LOGGER.info("Sync Event [{}] has been started.", sEventId); eventManager.status(aEventId); eventManager.status(sEventId); eventManager.cancel(aEventId); - System.out.println("Async Event [" + aEventId + "] has been stopped."); + LOGGER.info("Async Event [{}] has been stopped.", aEventId); eventManager.cancel(sEventId); - System.out.println("Sync Event [" + sEventId + "] has been stopped."); + LOGGER.info("Sync Event [{}] has been stopped.", sEventId); } catch (MaxNumOfEventsAllowedException | LongRunningEventException | EventDoesNotExistException | InvalidOperationException e) { - System.out.println(e.getMessage()); + LOGGER.error(e.getMessage()); } } @@ -139,58 +144,58 @@ public class App { Scanner s = new Scanner(System.in); int option = -1; while (option != 4) { - System.out.println("Hello. Would you like to boil some eggs?"); - System.out.println("(1) BOIL AN EGG \n(2) STOP BOILING THIS EGG \n(3) HOW ARE MY EGGS? \n(4) EXIT"); - System.out.print("Choose [1,2,3,4]: "); + LOGGER.info("Hello. Would you like to boil some eggs?"); + LOGGER.info("(1) BOIL AN EGG \n(2) STOP BOILING THIS EGG \n(3) HOW ARE MY EGGS? \n(4) EXIT"); + LOGGER.info("Choose [1,2,3,4]: "); option = s.nextInt(); if (option == 1) { s.nextLine(); - System.out.print("Boil multiple eggs at once (A) or boil them one-by-one (S)?: "); + LOGGER.info("Boil multiple eggs at once (A) or boil them one-by-one (S)?: "); String eventType = s.nextLine(); - System.out.print("How long should this egg be boiled for (in seconds)?: "); + LOGGER.info("How long should this egg be boiled for (in seconds)?: "); int eventTime = s.nextInt(); if (eventType.equalsIgnoreCase("A")) { try { int eventId = eventManager.createAsync(eventTime); eventManager.start(eventId); - System.out.println("Egg [" + eventId + "] is being boiled."); + LOGGER.info("Egg [{}] is being boiled.", eventId); } catch (MaxNumOfEventsAllowedException | LongRunningEventException | EventDoesNotExistException e) { - System.out.println(e.getMessage()); + LOGGER.error(e.getMessage()); } } else if (eventType.equalsIgnoreCase("S")) { try { int eventId = eventManager.create(eventTime); eventManager.start(eventId); - System.out.println("Egg [" + eventId + "] is being boiled."); + LOGGER.info("Egg [{}] is being boiled.", eventId); } catch (MaxNumOfEventsAllowedException | InvalidOperationException | LongRunningEventException | EventDoesNotExistException e) { - System.out.println(e.getMessage()); + LOGGER.error(e.getMessage()); } } else { - System.out.println("Unknown event type."); + LOGGER.info("Unknown event type."); } } else if (option == 2) { - System.out.print("Which egg?: "); + LOGGER.info("Which egg?: "); int eventId = s.nextInt(); try { eventManager.cancel(eventId); - System.out.println("Egg [" + eventId + "] is removed from boiler."); + LOGGER.info("Egg [{}] is removed from boiler.", eventId); } catch (EventDoesNotExistException e) { - System.out.println(e.getMessage()); + LOGGER.error(e.getMessage()); } } else if (option == 3) { s.nextLine(); - System.out.print("Just one egg (O) OR all of them (A) ?: "); + LOGGER.info("Just one egg (O) OR all of them (A) ?: "); String eggChoice = s.nextLine(); if (eggChoice.equalsIgnoreCase("O")) { - System.out.print("Which egg?: "); + LOGGER.info("Which egg?: "); int eventId = s.nextInt(); try { eventManager.status(eventId); } catch (EventDoesNotExistException e) { - System.out.println(e.getMessage()); + LOGGER.error(e.getMessage()); } } else if (eggChoice.equalsIgnoreCase("A")) { eventManager.statusOfAllEvents(); diff --git a/event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/Event.java b/event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/Event.java index 5e557fff2..bd4687dd5 100644 --- a/event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/Event.java +++ b/event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/Event.java @@ -16,13 +16,18 @@ */ package com.iluwatar.event.asynchronous; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** - * + * * Each Event runs as a separate/individual thread. * */ public class Event implements IEvent, Runnable { + private static final Logger LOGGER = LoggerFactory.getLogger(Event.class); + private int eventId; private int eventTime; private boolean isSynchronous; @@ -31,7 +36,7 @@ public class Event implements IEvent, Runnable { private ThreadCompleteListener eventListener; /** - * + * * @param eventId event ID * @param eventTime event time * @param isSynchronous is of synchronous type @@ -63,9 +68,9 @@ public class Event implements IEvent, Runnable { @Override public void status() { if (!isComplete) { - System.out.println("[" + eventId + "] is not done."); + LOGGER.info("[{}] is not done.", eventId); } else { - System.out.println("[" + eventId + "] is done."); + LOGGER.info("[{}] is done.", eventId); } } diff --git a/event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/EventManager.java b/event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/EventManager.java index dae995e38..e181e8704 100644 --- a/event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/EventManager.java +++ b/event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/EventManager.java @@ -22,7 +22,7 @@ import java.util.Random; import java.util.concurrent.ConcurrentHashMap; /** - * + * * EventManager handles and maintains a pool of event threads. {@link Event} threads are created upon user request. Thre * are two types of events; Asynchronous and Synchronous. There can be multiple Asynchronous events running at once but * only one Synchronous event running at a time. Currently supported event operations are: start, stop, and getStatus. @@ -52,7 +52,7 @@ public class EventManager implements ThreadCompleteListener { /** * Create a Synchronous event. - * + * * @param eventTime Time an event should run for. * @return eventId * @throws MaxNumOfEventsAllowedException When too many events are running at a time. @@ -74,7 +74,7 @@ public class EventManager implements ThreadCompleteListener { /** * Create an Asynchronous event. - * + * * @param eventTime Time an event should run for. * @return eventId * @throws MaxNumOfEventsAllowedException When too many events are running at a time. @@ -106,7 +106,7 @@ public class EventManager implements ThreadCompleteListener { /** * Starts event. - * + * * @param eventId The event that needs to be started. * @throws EventDoesNotExistException If event does not exist in our eventPool. */ @@ -120,7 +120,7 @@ public class EventManager implements ThreadCompleteListener { /** * Stops event. - * + * * @param eventId The event that needs to be stopped. * @throws EventDoesNotExistException If event does not exist in our eventPool. */ @@ -139,7 +139,7 @@ public class EventManager implements ThreadCompleteListener { /** * Get status of a running event. - * + * * @param eventId The event to inquire status of. * @throws EventDoesNotExistException If event does not exist in our eventPool. */ diff --git a/event-asynchronous/src/test/java/com/iluwatar/event/asynchronous/EventAsynchronousTest.java b/event-asynchronous/src/test/java/com/iluwatar/event/asynchronous/EventAsynchronousTest.java index 213439203..f032c8971 100644 --- a/event-asynchronous/src/test/java/com/iluwatar/event/asynchronous/EventAsynchronousTest.java +++ b/event-asynchronous/src/test/java/com/iluwatar/event/asynchronous/EventAsynchronousTest.java @@ -16,10 +16,12 @@ */ package com.iluwatar.event.asynchronous; -import static org.junit.Assert.assertTrue; - import org.junit.Before; import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static org.junit.Assert.assertTrue; /** * @@ -29,6 +31,8 @@ import org.junit.Test; public class EventAsynchronousTest { App app; + private static final Logger LOGGER = LoggerFactory.getLogger(EventAsynchronousTest.class); + @Before public void setUp() { app = new App(); @@ -46,7 +50,7 @@ public class EventAsynchronousTest { eventManager.cancel(aEventId); assertTrue(eventManager.getEventPool().size() == 0); } catch (MaxNumOfEventsAllowedException | LongRunningEventException | EventDoesNotExistException e) { - System.out.println(e.getMessage()); + LOGGER.error(e.getMessage()); } } @@ -63,7 +67,7 @@ public class EventAsynchronousTest { assertTrue(eventManager.getEventPool().size() == 0); } catch (MaxNumOfEventsAllowedException | LongRunningEventException | EventDoesNotExistException | InvalidOperationException e) { - System.out.println(e.getMessage()); + LOGGER.error(e.getMessage()); } } @@ -76,7 +80,7 @@ public class EventAsynchronousTest { sEventId = eventManager.create(60); eventManager.start(sEventId); } catch (MaxNumOfEventsAllowedException | LongRunningEventException | EventDoesNotExistException e) { - System.out.println(e.getMessage()); + LOGGER.error(e.getMessage()); } } @@ -101,7 +105,7 @@ public class EventAsynchronousTest { } catch (MaxNumOfEventsAllowedException | LongRunningEventException | EventDoesNotExistException | InvalidOperationException e) { - System.out.println(e.getMessage()); + LOGGER.error(e.getMessage()); } } @@ -129,7 +133,7 @@ public class EventAsynchronousTest { assertTrue(eventManager.getEventPool().size() == 0); } catch (MaxNumOfEventsAllowedException | LongRunningEventException | EventDoesNotExistException e) { - System.out.println(e.getMessage()); + LOGGER.error(e.getMessage()); } } } From 6f3e2985a4b19781d843c38c74772aa4d35641de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilkka=20Sepp=C3=A4l=C3=A4?= Date: Sun, 6 Nov 2016 12:14:39 +0200 Subject: [PATCH 16/37] Create presentation template --- presentation.html | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 presentation.html diff --git a/presentation.html b/presentation.html new file mode 100644 index 000000000..b19c85a81 --- /dev/null +++ b/presentation.html @@ -0,0 +1,45 @@ + + + + Title + + + + + + + + + From 4c24d99414e55fa8cf8fe3c068317f323350f762 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilkka=20Sepp=C3=A4l=C3=A4?= Date: Sat, 12 Nov 2016 22:44:08 +0200 Subject: [PATCH 17/37] Work on Hexagonal Architecture presentation --- hexagonal/README.md | 4 +- hexagonal/etc/hexagon.png | Bin 0 -> 51788 bytes hexagonal/etc/layers.png | Bin 0 -> 15887 bytes hexagonal/etc/presentation.html | 95 ++++++++++++++++++++++++++++++++ presentation.html | 45 --------------- 5 files changed, 97 insertions(+), 47 deletions(-) create mode 100644 hexagonal/etc/hexagon.png create mode 100644 hexagonal/etc/layers.png create mode 100644 hexagonal/etc/presentation.html delete mode 100644 presentation.html diff --git a/hexagonal/README.md b/hexagonal/README.md index 33c2ba9cb..30f70f54c 100644 --- a/hexagonal/README.md +++ b/hexagonal/README.md @@ -23,8 +23,8 @@ Allow an application to equally be driven by users, programs, automated test or ## Applicability Use Hexagonal Architecture pattern when -* it is important that the application is fully testable -* you use Domain Driven Design methodology and/or Microservices architectural style +* When the application needs to be independent of any frameworks +* When it is important that the application highly maintainable and fully testable ## Real world examples diff --git a/hexagonal/etc/hexagon.png b/hexagonal/etc/hexagon.png new file mode 100644 index 0000000000000000000000000000000000000000..e2d14e91dd692d888f85998087c881c559191900 GIT binary patch literal 51788 zcmaHSby!u=w=GCWmvlEscXu2>X{C|wZjhFil1bIm#C7-N1_R+K?SB1D3Mf$<=)H^- z)XTp=IW0x;;0mIHtd=tr6!M#YU(ir#8TjDhYZo~M>DOz>C~scFu(ockLP3#3$w`TS z^jJ7tc6T9}{v~>PlJ&b~U+-##rgS063(nXkoCJn8MUng)#tQ4v*~CR0hAJs@A_kTf zIre1L+a7$Ir6!Y7&6b;rQn!Pl=O;r4e<(R9YwA1i86)OqU9Ov@)S6Kd=Mj-VLnz`H zu;LiB3Djv~|NbEbg$usJV*11V=Q_0J|F|d)Yw+)4imFQ~xpUQM~pcrnBTS&67Yt5glcipoUkbZKgt>znEPu5K`Zq+dXi3z;J0BVJ`YRM=T`7F?KhmnoDpL6f z*>92SQln&*!i)m-WCUZ>zCtkn^KmA|c@ai;`OInmkQWr^i3g3!t9<+u92&c9vtjHy zY{Vn|pOyNN|544Or^k?s(0~VDO6IM%ol7-J`gG*CJR=Jid3i}>N+{&chp2~FyQKJ# zhAw!yGIbmgnUVpAc_wno+AEZB`2XDP#+dD+nF^mcpRm?X#n-RcXs_e`y)%GZUWmQ< z-}3z1;Qzgs|L*&LcK!dp_}@YBU%USQjg0?yxQH-n6$Mg%Jr?`-{vf$v@NkB|<`tjJ zYZk>XD`Pz9DDf3&k6_A}x-7W9q`vIkNOX{|ESwWEFb;HUFeAK?r2}y(lGnUB5{ zBYa{LI&Br0M~_cP-0lh$4>?AAw3ZG2)1A%32z)kgf^L(|46(+34dBvbORkd6wS;ZIC(I?k)jw&(ErhZ%6B z=h7p&2#|y!_-3Q$DkDGwp-GNx>G_=yc$XgaznLI{%N+(#P#p$b5|y)oVhFIW5MUpR zs?BQV&yTZjx(vA553VHCu<;`y{siO!;`UHbkx@|rsfKL$IlTB{~0loMk*j z(aFT(3TiZ+OY8Uq*X=vtU23~mo^wZN-d6{!666@SVj)cZ9FY(z6Sep~FtLeAGuc?|6Xse?aIBwFJl__`{MO4|fs8dhQ`j)U};?3F6o0tw04#~>N z^_8ZR_Uie&l;rr3hnG_#*jLaPnD?GuXWhsn-DS0~Hr|gaOqr>H;S-z6YB+uk2eTe) zN`CER$B*3GBeLBYW!RB1QD3M#VQ!vD2hDd3eeDE%&o;@#RIuj`-IlHcPu6xsZ&~y_ zuPv$h6*RrBv1+-vC6Y{=A0IhWFv-4jPI=gPKF|A^oJbY(`J&9~p2H1g#)ezZR!YiP zBQxP5XLLcAF|#Z45xh5~ zkp9@Nxwzw&*g|`1J7Q$KFbo-Q)3yzTtAA{-5;{_%flBSGsM6!V>Qga3kPYg_|%n zblrtlmfT@~-vxV|kB9!DWcjba#(-g|CwiZhjY@;vxdayh?m0d=iMsap@>d=`!tE1y zDSw2Eqc(g<*NIJv{W{Cr62x2Ij8ropDfw_siI0-=_Y~TuVOs#IeIbHXI%UxH+%OSA zy%cA>%5l!&%JpYU6TZA@&trGQ+0n@hROt0d_lyQ_*RexhX$?#qH3c>jCAMl#kOW=j zrq74r@I3O<xUr(3oZf(u+`aWgkGZ#`DC;naxd zR*_q8Jx5W5PCv0`7~G)IdyKtHHhcvTUDYm5gzAWJ(4P7UzN<~s@zC?3%4}g@p20Cf zGRLE^hOoGJ3PWUi*BnB?XXqfnh0j!ciSei`ksTchm^b3T8d00sbFf$?eLVWomgC@t zdFb}~(f8#CS%3SF?9sItLdnPY*jPibq4)}P8j7LVaO;?u_(UXd{_$U4TC!OO4bZ?K)cy!kmmPcRzArDWHxcpU$*B}_9MoFAHzydE0>U2%2X zgmF>z(#>u5fhBn|a zgOtSO#gRMPFui3$gm;hj0#@${d|HGptcpWR z7&N`k3O#mPMf1K_V+B4v-EJ%BcMgsU2P(4#1;0;TPi+&0S5rCbVN7Q`B)I=`5N}EX z!W$wZlRLS0c0I%E(0q#kQZ}_*zyM0}VpMpw>ZOZoZf?c(N7~X7hN%zp?26B#oRs-_ zhE?-FeGYJCi0b;K2FHa{}ywyk67I``w9&Jb0KoBm7x5eIgS z1o}k$0FR&(;HPm-R_|bad+1qBMBK)v$Fvx2At;mp3@vNi2B|YJe?7%+!my zAuknquar&qMQj<;@YDOlQ~xV%F@+k-II017@3 zQ@!+R3I`tre(vxZ{rgw|`Qt%{aKs&zxN+B}o>0vb`9mPZ(6Ay+rqJ)6;31TVX{5jo z4~9jWxHSSoSSZc1nGarm(Cq}cA%-zKA46>FG!4dx+6`bIeLY%M;vYg4zQ;d!LW4{V ziUX9Gz7o1nmiUlq7gF?gXAJ=R7=%Ei5kwFZ$hn8q#mZCb2DV zIL(Uy_~Bpa#pp0N&8`qvoAzsrzES$b$qA8xJnx;LqN4d8nyX9X`rQjk1+|AVSo$n+ zBmP%0ASfxJtjxh^yFVfupI5j~34)7~It|dqK2arw)*f=?=t7BsmefDPq$itwR z5ISMu48<|N^Hw2g{|}t>f5V;c=v4>@AMkHpH{|_5O;k8CFykx3#V(+s9~vyYVzxNmmnJVJr(OD*O3)t`R z?BAt^%0`6JOwLOZan8|i#Up{`#S15%k{3V$cSW+?oL_*&y!>P`b&!*6>hE8-0(~f= z7d6!&tJlSMvt?_LAW0{%pV1h{f6>pFTNolS&uCeIaME|MdRV?nPwYDyKwK zv_@{j_phUA+%RyKaweQa(wm3@Y=vBI*G7KQ%o<#E@m)p|p1RmFjfW1}%-?7b0iG7P z4;kZTlk!`vj+kXh8-}y|nx_|u(4H*{f4VW!Rcv*X)12U;7!g4mFYdRGO;9=>MxXqq zRSc>{lB)P*x1-eSeR1{gz@41}Dp79nr6d4LJzKIcMO3H#H(iJSNNk z3I}$DML3)_XSnb&(Z*3DQb<3IWsA;VNC)vNr^H4E((V7;T65I(>u{<|i_FXZcjxh` zY0yUu|NWWrS>24I#a(Z|S4AzPKS##N1y;H#gWld|D{Y3Q#QvmXqSHo?UGO!=>w2)X za+jYWx80dCV=KI30$SUJ!CGMm&KYS6&jlqmLnz71;TeBDSbkXMEf;coKR>=2FQ$a@ za|W4yhpv&LJkuvud|zySsa6F z&_gmjoP>tX(Ui2ElV!oC6TbGma#Y8oYb6O*I!>w23EFqAv;a5i_&H0>7tE;)FqGa z#}>4ogtp>VKnz1=jD3J636bEEY04-l-Y+VVWEte(z%pv^GfBvrZza>$Z`0L$Sdc95tox;b{b%OsI#*+HI{~}`nz&^ntSAh@l%}IL8M*_5}q`EtwPj+4F2wH5?U|*ECWMzjJFsuM^ZSz_Q1} zML<37B~0<;m)m~>mC1l(U-Y7__XK`}Ej<`%@(m{0`UY6J=DHVrHLf~CLp^wKyKo|P zjG)ow(>XqS)*n))A70-Di2wagL5$1!wj_KM%Ug+tFg&1n%47cwZD-gA_aQvS1>>EFU_ZRjtK~Rz6;BY&v1&xQRlKzrA}_<(HGDcu`X~@ zby^lpr691_TNHxBY(o1dEL|CP%}>eF2f5zm=7V=Z1V|>A>reJYfx|Wh-FI3RhllGS z(WIWPFYLsnw%ZrD*p&PNMhmmaJVdBrZh|Vhi?C{H&|30C2-)ag5hRT_4b1*Xhh$=A z&vR~fkMBcPT$_=kq^dAkvJzua^7Y)c15X}IX}WX4#>IT(CTC~JkT;)OlYw1Ra@~x+ z(2-#@;2}`{mLwZ4z#gwYgklEq)aB}K$k1IK51h$@zF$0Osv_sjjHp({5R9@e-#0;2 zEF}=}gK9OvfNyDF4jz5`pr#fX{h8uD){@&p?Q_|R7!-H;r{*0GZf(!|x9kELlSWkh zv_g?7cg~r1&l+X4Fk95Uj-Mrow!YJz4qZ~S_tU&OrSmE(KzhnjNfV@sVy2~1_=}1R zMIrsA-y)}Z3igk5!`Rq-7uc}k@8!sxlkpyozVPz!UA4`z#$BHrG>1NdaCSB?h|MeB z2*DP4qZKzcF4{+>CyG-*!=bRrOX7O8?46SrU7{_}XT)*d*(@LJCfHvvE3QWOd{j>@ zCmV@Wbloa$!>{~~U(V5H>_7_R*+K9tE#Hsa{7}a9#kaIe{fM#0i0G|kBO#x7kj)C| zCMN=H&|oE-FEnX{FZUHoY>rcstmQa1@-e_csLO)3+CMaIQN-mfJpF-*+4BfJ_3P%_ zESX2;tL57KVurTn2YP#NFVX2**R#k1K0Og{^EG0>C)LevKo9;*@!5k%GH=* zuZV7iJC&QaoY`lkb}i3PJV$T0CqmTA($dkJy19NptV#xS7gwT6w%sP=u&U!XJ(f4- zP1qGGbe2INumUsnmVA#qMeLWvQ^0nDq~35%eM*?N>~9bKQAo zmF_Xvp?dpD9H~Z&os;Torus#}eTvi{P}B@9Od{=coq6b_LnC&yVAs$~EUb3g?3X3) zejsKfV!w~Ck}9CagtYjw{IHdH8KWma6%g_Br8xiarjIWQm#_Bv^5T6{bdH}#!VrXt z4iegB$lhUD6V{mtfQ#%!@odaWE@ti3byvacWM?yqh?hEA|D=f_8E3wAdzU@2P;^MN zUUf>OY;@Eb!PlxkP_#PkESQE4CXqKuv#LQ|J^D=+G}J1A8nA0Okq@stPN$Df;UqK@ zk`YVi{reXvrC{0ee>cUXH{Op;pX3tsJ9=N25y*z4(Pc6zC7%SjC#vWEsEL7>fvls4 zux(#N6sg??^}*s_3V;`1x!IqP&|Eg*ug-Cs-xbVPMTNr8LwHs`m&J*R*)&AdyfI#@ z)u!hYFHILkZBgtwyT`4tKlrY8f#hK+o`ld&36*`hz0LuCKHSWd)>&H@TOoM++lnwo zQ;WO5^+IDi!(>^ciQcz#k#hC-F&;ik!fRhf$^L}R%9z`{gCywh9C-tF_eZ}iEq_^2(cXxZc!q-W2n10~hdZP0=)YR-{8+qC}lmY^w2DZ=;l@C5s*%5QRZK zvceDFw4Tz!LwYR46$xd2XBKojJ&gvIaNG+~c{jHPKYk(4P)Dx(B!rxb$WDoX+=-2? zirwtH#z$6ZPmwJeR#u=nA|LieoK9)pTw6sgVY=SIYZb%iu5&8`p9a??vkKY+AgH#_ z4H-sMogU(f0&tQ8Q_qxNb2ywq5*6@#{kDLfUS8?1^UmM+Ni$60G;;Y^a<%1!{>o$K z4zQYv>A~jah3%%lz6o?USy38TOhx!?aRbbF#$B5HP2AlqIggJD=5%bAPxStth4A9e z;W)#4=D;M4B`RmOAJCiY1KVgW=$?IcJcd_~5+h+Tl<8W;pXm|eV@o(1Ukm>Oki7?K zZ-;o%7> z2#R07N~H`-l$0oz7KTc}R#W?OgsmedNH z!B7)T)Ba$w8mfQ8R8y2^Q}V&3!!j6?OGrO9LUHRs%lxW#De94CtmZd-8nKK z%DWr78cKe}$4qm7c<)ZeqRAJ3p^7DifeVWo>FM*>Ino8NI~9iEaimMMqoCZ4UB|b* z3_O4a5*lQ!4#@s~9}y|Bu-R;$3gSE$;me=-!s~MFAgA!Aut%!HQkWB$mR(Wt0r1yp z@re@ek*fKM=`a7xwA8jWtJ{>}1R>6F?ykSq{~Ssv;Q4mqXzgMf&%r3+;p3?=)jbV7 z$lO%;sy`1rxbFgUIjdO(j9bqP=z}zF5&@Q#QFY-f;B-OP)@_Ku-7%-26+%hB#+_WL zCd3SaGYq)&f}AZ0hW2stL_gL_>18C#Ra1|r*5M|l8rI-jLY$b~QBl?%)LQ!di)wh$ zlFrxq@M$2y&S0a=_pi;R)z*Keu-iijdxJs^4{}vYtPgO-H8B)xzU3J#jyoM6-sI3T z22XBM6+K?}j!LKzSUQgXOo{YvsQ%&!A3ECLy9*kF;bk9P-9@Q&ML~0FsrZttdGle0 z5~O$)C26g<-%L~8lhq>JI|3Zie%+v+S1p(UFtycyFq^>qc=36nA8V_KMj5CKXd1k0 z@(1ZfJ|Gr9ALMc%y=6d}z@iw8E2e)u-kr4Lp;*{zZ$G6MxDS=80a)?l zi4o(Ps1)CkY;^RRkLj&he{_wR{8B#z%PN&aH_h(ii@?A))Kb6M_pfrT z4P?2($TJ|nY(M?fk$0FI!YFEQ6-7>p#d-r>+8?HIgA;+`(YSjPc|N{RYvk|zVS^&z zq?h6wUlZWfQQ0^tyNLgRX6w;*f?tBh3-AVs1T?P07DpuQWs%f<)zp+jGWetyojH>o zRy^T77(tVLcI;Hxsu(B?bjVc5WV@9$@kafYH3o~ZPCyM94I>w_g>ks?54}mARh1}6 z&tEp&uzNuOA>Lw-fg2Bvsn}$JAs@kA*KCJ8yJ{kj(Ex&`V zN&AQSMH$8%4uBWKFRS_7&%449p0W%{32tH+?TqV}85&{1ui$uNEUS_VS|+~udNQAk zZ+Vp9tQ##UR#=~Wf1_|TDT17p6#Jt&H<2-2ke;QpTgA|=YX6RE*OXu@%64p!0|a0g zprIy*K+@53V@PZCWIw)$fWJ$TZ(tK9XcY@XSDTqEo~3(rIz=e`_Hp7k-$7HM?_Jo; z<)?_*18H}2I!K5x0(@Zn_b3xNiBB@<=uwd$fI3vvD-&_3fuVSlqd}JsB91x^w2<+M zoXw;iz3fC+pmXrwpJDmPrFg>Ru>iL=drc;(tU}LE8`pKHKFpx!T3f$Pw|d88cQ>Kd zU~+{dbhj(XMi}+YL~HVzf->>}W@&C5RW9!5dIsFaSG*v^IDC?5kbrh~iNsFE5aK-u z9@&qu#n%;yP8ch5zpS%k`WFTCjOekH+ZVE>!x5Z~rzL*=poYUL`hbGVDvDg$T7zdv zkP3K5DeL!~4AEqPOxErQIGp*vOYva3jB5e77i2OUhe7C+a&3@GiO(EZM1$KTQ^W#+~)OV??<9r3Jl5aN+d9oHe}q!#9jQETsl=i`{c) zTuKb2+}0Lk3Te!AZV@R{NW!3;W31hEJ=d}_eyUIfT<`r zoF3aFfQlD*_v8y0w(%~6w3@|VjACzyNFgAb>8dWuGcWsO5E9W?N%@84G4#EUmI0mi zb<(t|xHeW3$z+ik^cnU`k5_2OS+c?+|B_|z;gHG1K`k;7+7-a9AbP^`6K1X~{K_ z6voEJ(E}PL(CD65ciJeNELB%?tTZ@M(a_LznAKF_pCPBYcngq3lL$ieD)HQx97D}! z4Y>&{r12&`)<{$MOAp2#C+{1%@=6H>AW!?R8_euM3^!D+Y9hn zL>^ukg#FmmvW)2!b8`dv`)1^41l)XRPAp@`+QwKU&|<1XCK9rlzu7k()h&MC2)5_< zAO@TM@mtm(Otf^`#pp1EIO;E{u?cbE{;Q$-k0}b*yE6m_3nmlW=MNQ9-(+-=i1T(6q12%DRm4Lch3RQMorX?_%RmK+a3g%kt;2NxkKL)czPEy^sZInA z3OabnytU(zfBEWkAR(26XCdD2gWgHFO=}-sWAGv-MNc(oXD8 zm#XOLDK6IA&t7WdZks8;v!QmsL{q(K#~93$n0XDu29>GU3HX3r6U53xMhdme#{7i0 zS4a1+#1H93pz9~2gZjSei$AOwF=Q%+!Zf*40i_NFo{C{0dVOA_o|3K&>cRcw51f7j zLWe(3FFF<`JOt8E*c9XRVZ#HWnqjt@oJa4m9*kF9SO~|v>dh%n8&6vU9dKI7q+N@! zx3}l;ibxcsN$h$lG&n5N;FA(cnM(7&dmo+GS_hx2 ztX#vSlti7tTUW!2QINVPM~t^VaoA5nO4_qMoSquyF`UMo*NZ{>%YZE`7#WXJP%xd5 zk4g_C>Au6eJzL(w*7$ev)8gs&0m?7d*#(ZgnsMyTPHeHkQ)CVRT! zWv5~#8)vT~T#m$o50Uv@Sc)F2D5#FTWg%d*(&EKSChVCoQ>hg6;%3*mnHL(kEMAp|ehn#QrI;=NFC_S};54L#RKvci_ zq@(LTsbR>K%4L}k{2&W;EQB`?j{WDq(@5*arl-68ULIE8^77&#<1&#uPNlKo6qg_+ z4+fW3G=}Tw=rJ=}ONeVzn$k)+yS}H3x__iZ@QWO}#gCKiJf5%$`aVZFD!0ms z79Dx^94^3t?~)Nu{5p~D`U?VFpyp4Lx2+!C)3@vOZD{GsXzm_=f81~kq2%{RPF#;C_+yYo*3}j~xF0Gtv-?qD9d-6dJ^-8^AmgM(`cR1fwaU=Pix5qkzkw4E? zeEO)SRyh9)-$j6FXxJaf5snH}E`&+3nL~%TZzeYK8tTf^-yP@_eKhCXgE#gjzAMSo=Io2$Uz;f&ydDXyv6nYI1*GkJB5`($5&wI<0ouU?N$O}~y9?_=EA zwj}hfx0&x$P*6xnP3<2{W-a=r+5J|Yy_#wBe2|qcd$e~{^hGEpGSVV>ndXldv6 z(gK`YH&>|@9+t>Uk#Y-F}!QOLn(ltpjOP_ERAQ4#9 zK6_{ritNquB0x@N>Soq&B=l>!x!FBA2%h;+M)D-N1e7Sooxhz%To$}K?0kK!Etgop z7-HA34u9({GA@YlK~+i$_Fs5OhN7+Sj_0Sj?cy;p1%Z|E@xtqQg3c-{&7+YE0FI(- z587HK6L=dlDw-ZCHqJ@Lhj3~5M=dx>B(yAxHI+)TV9T##3>^v7h!1WpfsAdJrhj^R z1H(?2vzJ1=$nJ@(6hE$g5q;LHxoL$0tlXxQF;R8A5#XZ4CpZ2o37x@udV20w53+3b z^~qKp$);2TgAp#XwiKt?P&*8|kpGu2(8CqoW<2AcFOWT^4)W7xM&weyV1ZmIu&{XA z_vF_ZWA{WWkvkS-mkrwA3FCZvj-fA`znDMHt_agqugMYlA1pLBG*=~7zcJ<#%z9rm zxvqJJ`FORmY7Fc@;d%b4>^uVD&7G+YJEQ1pA(c;}x7-7lVPQ&KbyZAqTz(M3GD6Z( zHC5Hl*XX1L&CNo3bv6V5>5fMre@H4R2@4PJ)H2Tm&IPd;k$ZZ{h{pPpw9Hfq(Eltg zEGs=_Va}ZDCi?ADL9YczDQz_AzYy*pSQ-9WI34rx3!1h{AG0 z9&5q#^|&yfJh*8_a>=Kbo!D5+=KK9p1G84}U3!~Q9vS$x{>5V|r}=rVWT?f>@p78p zXqt45tm*cBH0dqOLS;Fd4pVVud51>Dg8!o5rEuBrU987T4fl;u(H9!G))v%4n(mao z52GK=fE)<;2x*-YsB5(;#d{_XRrocH>qLX0ouZ&!2RF@M0!a~TH+O4j=rT6mOTEzz zTtBW*$cyQ9SH>g+w0cTD-=+Cz3`OS4#GD^5H(7!t92OmoD_qaU++4r?x1_Y<73bzx zx-9a_*;1{dW4F1VHfB741^eOW@v%vQLP}Wz>G-*O)bVcNB34H^%>HGq*TTxipIXi# zBzV2#!2VC5-!s)mQ=fQbE?!%w(#wgRO~bta*UWToUKutp9rbIOQ}M8%UAc0^vO8uDwCcE2v9N zloO(&TXkEstyf4(&mtTvPs#_PHv>pPC*-NYFwEcv}WElo{H9n6$VDk?^&_~L#ikyiPZ zkr8=*?(|VZ;{yZ&Z>_d`)ba@peEfn*IbxjcjMHU`A(YbT@PY&`p}YD}$L9rCVEaIb ziTpDeBOGusTM^i8)Lo6kh`H@#eI7oNGpizNT48rA1~MFfxf!PaOJa*D_dfzT&X|%< zm?gZnRqzYDH0s9EGj?4*#ERXkn zb8@?7jRmeZI;l{flE@u34i3&)H=aHd(iOsF617}HN=g`spxfBo9DaCsxNPM(dv>fL zn$_O%4iFu}o%jve32D7uQ}XEhGGYVsUxN;}kuV~OMMhWR6=;{jl;kCJ-XqtwUL#dI zJ9GD=o5%&oRmym+lDl4^JF2K7SzsNnrg1?xm|LXOll<_{D@ngbQ322`Lk7qm4~NE~}c2hFQ*`!mILHdeOigvm&b*MUm_n z(9$RxnYG?+r>{Hxmbzw?w?+#M{HV57u2ZiH_JEGsqUJ~`iH6S>m$=eCH`bArPFhAR zg1(3W$q5aHy&zY=Z(w*pc#oS@$b6MpmpBrX(Bo;>?%rNUqwB%9loWafJ;cc@ra{dH z2a3Xig0)J&Cq``41GJ)U>G7dRYEoi?d?1A@+{>Fmz=AyQ$cTQKHi9cY&GU$))zWIpX&CQ*KWLa4IZl2?WV@uB@%bb)WIZ0vgUxEk#Tcl z!zer^X6KjntSTGd-OVCm=MJVrTwI*P@$a4Uxw$znuRw0+vx(n;t^@AnZ{{w#@km-g z{{@aXRZb3y1DCnSPG=9Fi^1D2$(T+H4omI4WCFH**MxZD-ZBooWetwK2WW)UfSwzU5jpydA)J2Ygv zRoLwnOf)9RCBhxlw)&SODT<6QiF3vo&70O+;c5cEn&?{ZmHq?k<6%=hC5Hgv0n0K} z{&>(%mglQd7R^9q`r`3G2)(rhoLDVTl8-njXl`k-(B%K>0WkUEuT;O)_F-Spg!A)N+OJnw`W!l@hL8wT+bC(wBb7V~GDvLNwPR?PV3LVkVIpkE6?jerba1+pVKNu+B8Ajbb zKK@Df>Ngq7XQM)dwCKe{0C|bxg@FS5EiLQI(%}c#$G1M-a z{AY(8p9zt9Ij1XYa)GIKzF_kk#~SJz?gIW=Y-w?mk6ee*U-dntrSLEA8(LdJsVQ4M z=5-b9ljyR&u>u1FUB;#H9Hpd!G_RO4s$PA8V)^|Si-Cn@`|06ka-#4(KNXc^JgG1{ z2QjkKP#Qo@V2i>5E+PNey^XFGXpMGLc%aKFHF&VD{s_}x%7muo|tKqt*(&#Gf z*J*T&HHUL7{@(ZK6>$+|mC(m2*ai}w;S;K1y@r`uH%A3)JpM8>#fYek({K&X7Sg7= zwqQZ~2gK`>c|>?N(Dw|XsHqv&2z~>M3&8Zl*N?Bnz}SG0@usG5B@}MHcnyV)sVPm{ z^Zh|Wa&jom`y?@WVPta-vk<1ihOH!>v5AQQKn7X6JuO;vWw0y76!8_SjC0c@Nb8ygnOjjqk+qofSX z%+rV3KndYu0s{EuP%Lp`jOVl!Q7YB_-274Q@QjhohoP8q4rreTHb3lF*cu(2MFtUJ+HaEBX20 z?U$4~7@Uw^UR{#oqja9!SgL=}uS||5ChAv@|Dred8J`06#tDXysS~VMS5javqEt%0 z3JslENWY2aO>I6xna+zelddPOz@pCCP<)KxOV+2kCg;}`FZ;~0a-(A=T|Pia1ugB^ zMzefYeC9iCl73AUl@2B0D{N_L=`-f~C5iAJ-ZFA|9^e75W-6&E+Q&~HGCTA*Q1CurB*yc&+a^;JCs@vRaU}heCBqQT&dw}sZ2kZq!18$M_o35ouFqzGGXyg(#kL2OfqK2` ziVs0#7Lrm3=rQe!_RZ0NsSLcBDGThj>H<~UalDX7SxqH+<(Q>mX+6!flcfoV#3v9a zHwA!wtFx^A@$LB+ktz-UHVJZ>*FWk ziq)T_z+wt)*u8}sdQtPvJJ!`>vT+DkBrPEKSeijNdP71jc?1Mqb}>#?+sH~aDj^aQ z0U+@pkfo}zgSIo%@A(c0OAR+GUeIDSvHPHt>o?vv^e{eVvxl)QtlF3+%~u~jQy!Qq@o(UMw%i7pteAC-HUQY91oQK0Q3btEz9O0` zGAb-|GtA5ZdP&@f?N3in9;Y3zf&bTWQh_&CZj&P;fGzb05V8}n_m7Xa0gn$1kiUQb zUNBL^q8PI4`A1t2T@fGuv^*~vwcw(x&%uDt$7EJOy*(>m?OD{(@5N(j#STS3mZ8U% zu=D-G)6EaXSB|?+MzD1ZjUGJD1nggQ&9SshFf0|88w)cm;V~{$Jx3X*!5VQ)pq!&z z-WV??&HlVNvbC_c4Q3i-OK1M4fUGCqJd##8)PF~J0y?@&To8`*ZyO$q`lH?Q`jw56 z5(e!WGgM-<*RbNZCO~2!;<54XT5q?mY=Imd9i^FeXdzZ{0aK8*cGDWcf%;wU1y}DqBb-l4+C7QK!OAH zv&wsm0rV@n`9I7NnLqg~?GO|KIdW2{GJO7o}Pjz?iv zBI~Agj%@i}0T|vpEVzvNwRYC7oBSeJeXeku9}gi*-bXlm-VUMxU!WuiGY*}rHxjdn znmi51_B@v3__ZNIttYJy20ZCiR?`fcYEBEz#T6m`Q+pOhK_J@q;lHUGq}Gyite#$&)Y` zrb3F?2ErL^AoQG#TbbrB!nTKlElX)+Xt0-kGJegE?1@iMGN6vLbV?| ztTm?F^-RyM7R*C0b{XqU{c@!cd>ev1Q7dTmv$Qm#-gXfJ8Y`-D=Y(;tS?&C;;0|DV%oa@@$TrNSHu8+g7b0w z@?>9ib|w>>kP%?-_agIi{xFSN>}#xDxTBzBL1QeTpcn1opg{R5#MJrq{$dlbYL9A9 zu_u`lunIj5i(<|v#(q9Vl?zTp~0BSnANO*2?wE|r>4qB zZFWICNYs7-LwKj(!{RENkWeHl5l_3-uW;cuV8nl=sG@=i=n`afky~>3*RQ#ok_zGG z!yFcVd$mh`dLo_4D~>5CX?UqBI{jt;f(~$BUE6OQ{re4RdOw*Fb)H;p*rTt+yl?dgrhUzVfe8jrbyw!zNo)NOa)%IFs)-!8e}VA; zbg%^|V$FtK@Do;NVdV07ibZcA`LQuT1O?qpvr#uvxmi6u#Y9y8bktu|Sd1e#i6Zf@ zWj7`IwqTI1`RAFO?!{K+#)D`R31+OyPr=Mx3wudVGh7!!YKkHMVH0W~Jd*fG7L@D< zee4skh4z>|v--$Y_rX`2vNMxs_`BNjIwl}<%1V?IFaXz3b(oO|ro9>t@I<>9F8f9)KdFucV3Z@JGhQl_(uBAdPvAE_{jcQLT{3zF7qj%0Z)G7%eO!BLDf>R|J$g zeqywdp{Z?UoThI1XM?ao!i9f+l_9%nvlzhk-qB^Z1FCL)166|@13^qh0!;SAW~Nv6 zryiV~#CDPJSRIk9W#t;ai;6OOu&nszsy$IY@=USfS{829)rCQ}M_Eo5aARKAAqK_H z?ubu}-<}r13J8{+&dLsUBhSpp^AL4l@dP<}yTQSBK~7EWaIPwFaA3gVXyF$z4i1f{ zqWCSb?c7gjvzk<1+Xbo2%*?cwS*?t0adtbp**aIFp`!7(_E0l=PH$I0R`Y;=EpqBb zTZ4#OisKm-z;@9;nfSoFJ)t5%vvCf5u#s5ci^CJ zPspA%ZB5Mh`~kK zf3~bgyLx&_rYnRGSVK=j8au zkcldGcXy{9qmC%ai2(u%IARqly1<~`d;L4Yq^w`BL@M#V_>=ugO!V0P+Uqb_|ML3b z=D4#)NdzrlCH*KxO3cg~8-K0E^p}t?p*gb1ER>MY@z$~_H(Pona5n}G2w6`4@L#P| z=w_q@JYNntykN02GOojG zPBkYF5ClQW2%GA!IXTk{GnIMe#gq3bRhe!J1Vu+vBXg-EQ!_aA4B=}7v=U;mnLnw; zWF_L#ecI;Zn^s5fo(#7%7}b^g=)T-sh)OxFe)bc&X>KFsvVY!@ zYrg8SKJ^ePDIYZ%`=BntRg$()Tzxk1iAYx+dc~(XBP7FaKq1;V6T`Fw2x*S>d_ zS63J~L`$`eyH%of5fMei8#isWwP@F*ATNN0P{F2Nny6l`-A$*IRnX#fQ=(3kk&2CGTXV*a#I)@1{!sfIM)< z!zisSaoQ2fu}|iv7aQt258Lp)FmQCHo_xS+y&>!;=81>vbC5ZQVeN`B!;r<^{`$xY z^iX!fXb0q~I%?Hp6ZQD;@DGXm5_IV_()igs@`iJW&;Hbpf351(!EAm}kqkGw>G+fc z?4GN4#g9zzyy{(M_fNh|I*!O9bC09}fq}6ZX(7&u=DFh*r>t$h!~!jPzZlugAm7A8 zryA(5?_uWLid`-}+ZF5aWJYH?kFL%draWA?AD>Ondqm5A6FvDn<*NpLB4yR!smmkh z{=&JLucosWOC@vrw?951J$-PpNC}U-?NtW?!PV)h!%zl)d}=DNBNQ!Y2V4rI@lv3( z#NgpXF_Ys6V6t;oUm$%;jE@MORp_X5UxjF!;gZYAD$2nz?n9Juf@3iV(5x-kvaPL( zYOa#~8mCP$*Fw-{H`kUR@dXMw4&}2@RnOo%)}8!v$bo-)|44O5WYwdGC%<2zcNAv<31uo*k9Z(^#`L}2%-*=WB4Rhak5oGN0(n0b5Qe0>K_M6Psdr?}X_d&^7@E}S zch#mW0p$<{u`w!@9L?y5{PCQ|>R0tkzI2d9pYPN@3uh&{J0+yPf(43SEBi}6B!>LUs=J?E{h*iuZ`?_M)CaqsiX`{^T}uP zBmaimge=#nreKm1%FB(%E^)F+H7O;;u%O?@SHE*ZK~Z^EhDsZ#ml!?Z+eUU`yW~F- z?Uo_%86Z=~si2&%2qOAWrqiehh#cn`dBoGLHY6k@|LWtw$jCMjXySyBtZU%{ti}B& zCnhY$^Q4#N=j8yoreVv>u8us+G6cNdq_yrhrAFx~1R~k!zKLj1`oXLiVs@%b@(`GJ zr9{Q$O()eyle}1KJ<)b7KYqp!8*NLaCr%-efI-u~Vhd_&+Rg5wmmpE0GaU;q!fAn$ zM+F3!#Hezi!}GDoM|n-jY3sqe`-94^%`=0J05}Ad+?!uw$@K3H>ZzK zQyZxykn!oIg>Y--pX>~()JAn-CjO~2x<>!n-a&Brcen2grM=8{4Ix~Mc5h?3Ut9)= zlUcgD1n$&n5iR>%{yhk|g>H3qb|B%nCa=N3f?tA7uqwWMjthb``|oXO)9IA2aB=gt zJ;?u@U76eOyxj_ML$0}nPh*q!E>-!R*0<8i%|rK2qv!soS!HkY{leB5yT4IT$l8Fv z1{H;jYO8-mMw&@QQQa5W(94Z8dAXM2-%*B9r=g}#$I`d3sz(}67A7Ca@sQf33F$SY zC}|KIHri1STMFn@=pySS2cL4{m%N@%Be;84p>fga4la!ZhEV&;+i6rLC8gZjj^L0b z8WM^t1;K=%f-U7qYoW70TkHlg;zw15YD>2Q4W3%FW+`@`TVwtyk5f^Vhunm-Za>MG zh2-yHNq2s(%u4@bU*sVT^Z$2x-QaFLg>c4eFtbM@)xSA?Usz6BhgEl9Y_VdV^SWR9 zhCsbI@#k317&|*V6MxR_w-W(eL#e{ADFB-Pvs3jc=J#*AH$4i;R+c6t8Bw0^w7$yr z{%*>jzk_?{9zAnkpU?=kmj2S8XgswPuFqHkF_{hdFOA8-A5u1)go;$D9y(%g-!(o? z=Sm|QvA^{1mb|6dnaHFY(v&^(sR7Nfc)JnLWC{DP0oU8xm*IA4$!tgoiUd zPbF`CIBINsmho*$_4{h_2O23uZ6(Z)4ly<9+O4Y7+W^deRa|ts%-Y)Bk{M~{SZup+ z1r?mc!H!>Or|}b^;rYdx!0+^|BRpRM^a}5P0z}LG-}UM0iRbz6)_sGHm6KQKJ~p~e`ah(uRlKa@CwCc83p0&few=~lUDrvG!t@!8 zQ(i+Hox{qpkxzX_?K{sHu9k^n&4$D?;-2y0rhRMPqTPZ^K-FqnJ3hNMu(L1vv84<+ zf62$kp?I`E1JUs&4>yKDiHAP1uLl>QxMa*{{H@l4FHP;NoAyTL$>7`V27RtpJCqjm z5M%p2{9j(kSID;y;#Z09l6-md`i0Av@5c=}Gt8I{+M1L(H6ofI*bhZRFKxlJOSvO` zH8_@gcFTR^{G|yt|LXBz;@P)Ynm*~PsmCjSo3!;(xKu?Awb26&BdtBGUul&JqykO= z61FE#o_wye93eDf3NRL=eDjHxoSalG-TO;M_Vw!ucdDiFKYt8lH4zG>VBSwB zG{3$6m{eR&(N_P>Zgtqdg=aEZzl~AyWSU!r@Yh1i+=Pg7_(zA)M-iH@W54^HzJQWj zaDKGeZCVp%A0@;0<-lE{>H6=2NsaE=Ks=+Cre=NwshWJM$UVG>E`#N-y;3#Mw5|1y!H5;t2>5zr`R{^q|&`r zeg^`GLc&u_L=&sjfc|u8I^;odh8^1%3)L{O@Mm_7l#iva1p&UDTI-GcX3ig;ZWLe~ zg^z(67a#usA@~E*eG(2+tu#t56~YLhsrzg?$-Rhf6DyF#^V0J&(}3$&RL8o%&~EA( zR`nR|N)~f51~!kfDpIK~?N6uX@$d6d6^jyAJCAP&(Es{I(Ow^YGB%h%-Cg{s-SFWV zAwkO}dUI)c=;Ycf33g6}hDV-2Xf>6VVjle*SwB8@p{TspzKznE;;s|%7Em4yZ*K|V z*YiQ0oe#9XnqcB~{n*v|dwxq)a~3;#i`wr&m#o@5LZZP?@C(*VIjUe?C7~ER)r-_o zqD?S+U7h+?v19!%LA^eA7)EDjC*SifJ}+5hieEMdJ+wIw6fH?WCL+siIU^wn2E2=p zJfbgX4254yXmLad2dZO z`oWSmr^D`miB-M+)o#kafJ)lEe%fq5a?e0yS1%mb{ka&0Av>Md=^;>ycII2H)HQG! zxZjtxy@zuCywOg<&rh1hbBi8h>=_+dD?UNd;~aI(BDKy8`;PF73(p4m)Z`Z;G__2t z_3fC*3X3nVxrd|JRM~o!LL8O$k@m#3-%NNN7ot!-A*QM-Q?hmAjo?qzq7=~O^F^^7 z$qF@+xWJ&f-1K|fUW5kuB^X%ztI;V&J$_eLFWvvp`b7^z?^$KjG>Y6qn5TS3@Z6jO)Is`CYBkYL~A+uGX`b)!{$I z#?|!kO0j7_Q4+Y3LDCDq$A?aNa4?94E&76#IqlFaR`Ty$@J-&##L#ox%-p5{2leQh z3FT1jaE#iD04~)gyRTFRBF-db9HXY!syi!NzvL~|d7QAY9CjKzqML$H&$KWaza#|x z`sr%tcsyCr^=ec-N~8C3Z+G{{o1L%Ft6i<2OZzM46F4%!CV+vEkcg zA&!s;GujfAOOOg8`oa|jvNA?jO_&M`)>!{ts9v2J`GpfPD;*sFyB3M+qZ_ELh&Y4M z7%jB9r8&^Fk|aAbt88B7JP=Px#@Sh*QokVrl$&R!7^u%MVedjW%1}P@h1U0sUPw@| zgb?McwNU+T3&U@6vb8?f(5*5zWR!@vXJLF1AN3JKi@K3~XvH0lo%e?ncDq|e?$1S) z(&elQ@^6Nti27sJI_#HY{+;hty=VJ!j#|z>JMvjt;$n>Lz6%CTN+~Impym5)A>wLNJ&T{>;q&R?sg6%pnJeI$0sHN0E;RS9^qmZOJK1m z%!LcM2sK#aIg{16V@X`Z`jjr$K_xh=!$!B86m@Rl-O;{Kxs5eK(d!|ppx?Q2ldG}bH0+V3gKxQf*x4k=W8gB> zC$C>@(K?wP)XU;d?r3@30<|Tap(EAbUgj&2O-P>6Xuy7MQM*hAOl_WV-k#ezS|3ldIYcMsQF}}wB>rWXjEYLe zQ%9KQa%_2ZJH@Em2k#mmEzsmgyAe`*V7I}-{DW;kcvF*0zDTi0ynSZmlVkvm@uzE7 z;fxUmc3HZnFY!#6L@a8#;Y6&5&{32$H|yOcfc|n~I#bZy$5%{yVW5^x^&-y>xjH!b z>09nhRgS&s$(e4yXZ~YCjm~ndx2$X8VK|Cvx#>jyL~9s}E|x`u{K+WkYUJN@vnv?|*MMc>45hsb;b1T2FZ1dXkI-H`yCYxCO&m;-vbOB>yfy{ezaJXroZ` z?Z}s`_FM2djPhqFR_2(469nV7LUW!a$3v3F3MPWCF5OjZ@F*n9iZ@G|KV}DjSbrxk zJZ&&65?j*(2LQA=!0&J0zJ2h*ZHbw}4g+--KR^aavsk@wanayId3ioSH>H;N&xSKm zW5;5hAMO1(xzt0=la9^f%c~^8x<}DGGogCjZ8S`kf@D0tp{V&%q~fP>$;_bjv^|S} z`iw9gl;WNW^Ag83P2$_=xKt~XlTRxQ+x3(9+GOaSkXFq`ito1(0moU@{+Ht9dL)EMyv%=664^zXSa|CYEexl|5*ky$%6iUVWEW$MmHErX66|XW0I{P zg?_a$vaFn3Z#MzP2Mq}tJj;=Eh4uc}O|$-(iOxWD?VY#=cYXR00~&Y=k>A$+Z0nJ? zTqyAU=~FJdP%36^OfZGt`way9r?y@-(xXZ}pH+hiIZ~u-CDebTEG^7gW><0!jbBedR?da+JxU1#2sL9Z7 zg<&-s==uj@i}fh#j(?v*4_0_O_7Var0Of$rn~z;QI5D45i}K?iz}^yjO*=vS-y2AP zfog0S6dG!_@g+&r^O$W9YU7M(>P|g{+NgT){kgEIH_`Y4fznmO+wv;N2 zs!cw>>+eJ!8~t1D8(in3XH0v%kWpG+6mS`u#icSSl=ebu%f<1Hra16y4t5XQIK;;n z79zQyfAmjt1h)|Ybh;;^N`4Itsx>@GyNwNHG(bG49-1 zm;QG?_QR=ElTeVIGZ>)|uWXH-_q_O!hN~x!3ZWD;A_JjgUnjTcSt2lSRu?wa*Qa$C zQX)1w{K>}hfP3Q8s40m+SpMnx0{m?=2!SVljd=kfDO-nFTUP&!#h1YWz;S< z1vk62sQYF4H@~D=_S?k4Q2Xh)m@owTElO+A6g2+8INY^!GMT3ksXTp!h5ELtYxBqi z=FxX?ai0qd3tgbtB3g9eiRi>T<7--`=ug{DHQq9h;XP4s@TKveARat|Op#I`tQs$tf{Vnl=l zC|J%u8MhiLsef!y%0p!++I&eT#6mbZ%jMnigSep@pU5(H?0o|#37r6adU?jYN!Bc*@#gIvjU2j4D8E}H7!!YL#1RS^13Fx=irj-$(d z@h<<%FQ9eKuTPg*8y7}^EL}NItdOC@_on7`heiQ`hwTGj_GM^D`yPw6qwp7%n01qs z(6Wq$zUijt3^FD^*R|iY{X4$@i<+zmU_8TCCn>C_L~H}Omp`*lM6Qv)h1VPpypFVT za^<+ZLgtWi4H=zos9xBiB>L5fq)+X$I5G9uInv3b1v}&7&0O6}JoPNGV2hz-aDj%q zCc<*g@W>UT1`kpw_h66G+)tdh%R8mnl9rxw~0-Wfs#q3sBK1>Q)(+4HX$>0$ba_ys0f}+ z$L>x?g-s$MwTdHw30tGc(P~`-TWPhXnmk!??>GGGZMGtfH<-Kxt6HxaZJE-FHj3&7 zb7?*BGRgNp{gZNg^JbzOPa3;Yhm$K5mJAm*9v-5!y8PYMyE$8rwf^#s-QdX+zBLq4 zDar6JWt7by+9ORXNMf*PU(8U~GMS8T{0wnL|1~ehj{n3;-wy5ZsLE;yXKJUYVgPbf4@ugzSPv!y^^L-jOj&>!Jk%q!H?(v>Uxt{% zMpEy|CGm#91$mlSZn=mpI*&hZUOVScUUBage!jmE~w{B!Yh zD+O-#g$y<+{>=T>Z8Sr{2LHSd4(HPrm=BCF0@WjXN-%)`TL1goSMZIiW@LT}N(A(A z_}W#-VMtZWV@hN5;Y?jik(Lk2<5hxr(WNi8@~d^Zjw|hb?&y?j|93PG@pM@p70cFo zo!ZsvS7ye?-&^}TS~3+N!&X|sXlwN+1(%JCorytoiAKu6Fz`Yc9XaT^<)fargSUxE zUQxuCf9AZw6jo(hs&f&p%oIwqP+5z((77n6Nbo|>DvKUTP?lAYiT14I z;O#1}>cA?VQUP9Rb9h)S-kljA<3lP2uR&9sshJtVVKqH5aqrOe83S=aujWHF)STB= zA!D>pUQ1sEAUzXqI0#jGJe523sClsFYTy@TDH~&2JtJ9RyD80|WkR!t@#!`fxY&9z z&(e<#w<`GFVtY>7HZTew{;9hkeHW*a*bHZVLx2T|>>QjDW7!*<*!OhKhm(Fh=;@;QTIb#*au0vN9Uu-=@a; z%YKdj+{$kX z8E7(*M^Pm1)B(7zPI#S zcV4R%Fb6p$uCpmuZAOIX)Qfsrk8l6PP-PRO2__C)Sb@86F+ z2^Md;ht*O9E>w=Uv+CL_6IE>~O52NbUM1sqnB52x7qV(P#F=OroR@w-pr5n)42+tm z!v;!3Lx>~nEmvCUzzbJ&zmc1-Mh|_Sv*Ka5T0Pal3Jp$GymC9ayq^2yCp|keGx54{ z2`ztujq9xp9hnB0Uv)khgjZMdeQ$PV1(8ar)4vAudG{bPoW=3)k9-2VQyS#H#tn6& zk7+sUy}9M#EoCTH88`bO^Ktk`jF!a~{-WDw0u0>rP5VWZ)$YGUg}3T~Rgpng&sh&J zVNE@!3@!}EP>)R++Ib#FV%vRoEU%sIzht*5^4blru^gAe8ZaAJvhp*K~u5X^8>gBL>K4$H>DB4%@eVr=NWP2_(js+Q0s=o&+2X$1m`^vpaeBFrv{B6D;A$Ghfwv9@f{lm> ztaM2);g{y-VLhAyGPxZ82bzHap8L7m($A*<*8+Tu>s}@Eh>i5WzwSI>HJ)EqdXm8M znE**Id0bp@xNru?drM7-0J(8Ey{CLr?SbLLs}j6>F~WFf&bn^{*%;~5fgx-zYQBX- zjr)t7EaXAe#tPl~v*h2vpZ>miAZ2FHlCM7IHk^Z&r6{n5S6Esap5yV8919b3l@>t9 zaVx>RU1d7_l9&lAd1Yk`dk}SWb#;k~i+lBicBW!`0t~`aWy=yC_S)oUWbGcZ!m5*( zz?U8U68mwLsiR4c?KcYVXh;jcJjtr+E-@-p&wpU&L}kI+mv?qX{@t$(OKDUr-uTYu z+j{wgKikTkyxA2PJdNltcb=EJIgsHk)#3yD98E+ZeYsobAeMF3iRbGN8-Mj0+Io%d zCdYNFuN8V%Agf%3PH{6eH9ne#udNya(@QDJFxxwfp6c z{)&s&Acf6ZQXLC@rzN#BPoe#Y#RFCK3nVpEmD#dB?;OmH0N0I59cpo9RWa2~6QI zCH}A<$-u2+w^FmLCyedXE$NEt-Vic?1{~&ZqyV!Dk{~ql&SAtm0+j4&yX4;9E9bkT z=`;z~1JDj46JugwVF=+PHWs8%n1_l&_690S+wr7oo9!%*eyb}tuVI_+-RCnf_AcP1 zbbg-)Sn%gu7#|sqSW~;9%PC&In=yu^CVpYx{8 zc+*>3?yb1ULDD;yC6mJQ_zbGhvjGQfnkRr)0959FeR1Lr6y!ah3m3aEIBi?DdcNuj=(KC!g0(s4W%Wjzkn}VHEVp z8{QoqP9<6SXS7QUa68cAIUk=3Y!OhH`=`J8h=YT3wUr;6mz#?Oh$SuLRUB}WVxZ=e zfGQEewog5leuOCXIafbe%OW!Sce?$ja6S?Gs}a79_CzKBz$5Odef;2^1*VP5#|tls zlW9#1EUdiScSt@P^U1h>LILV<{lMK}>CLPLWC5fkCr^HO(drIDg0k>x!(xR3buaDx zW+ubdp)ruSpYMLF6SVk3JUTQ)gqVN(P(d_ty6B7t$M8O&Dlh~06k#CKh#&v`dq{ip z2fd)6!1!RTH*X;c9+Do@D9(zsca9Yvd!qcFb@CJN*&H6Aj|4^D#dX zH!E3xB@x`vTM+rcisTIkV;BzNuaQ_P+S&0uN*4@QefV$-U<(2UE>!p9jtZCtf5Hc@ zfb~g1S2wlk@-F;s3cchS^FhM7SHd%jBv{BK-pp^_yqW9p5x+}J>|kQ@9)aLu^hxAI zb7hLV@p!cxUR>|{@d_(o{MkYb;{f%77oghv+$k)C5{3wy&J8CMxD(2%s_O{}gkp|s zL4SCHkYZ^bK78mtmMtmh_4n22moJ3v*|+maDs}Ee_M${9G78H%OyCnN`J68G3}1bH zZvXz%C!?@xeB%>x3W~Lt*&ZR#(K*7M!|Ha$=^h3#J#?P{iGaiNft3~8v1fZ3x5mFO zVQZl6>pI?^($Lq((o61@BQhWcICNrSq6r+0@P`kf5hKcAK-Klh_W7&lEhq9&|*E>3nJ5yH_h3}jtVq=xRuQaSc6-rtxpfl*X#{+;KXjoAAJLh-!%6Dr*U9Lrho zY4?WH`_@*<7cX9H?d@GJE~BF$ySTY^Z@YA@I(*)91%XR$dHEf1Op#sH(7FblNmj;)Ym#YWvqkcu*tNue9gm~Hx*()o?h}aEK z8-E1%zwalbS6@Wrd(=Lmffi%7$_UT0Z@$6yJzE4Uf=tpnAo0i@9UXPyL?PiZ2y5N% zphP5iB=Z{KS}MMN&Fy==W3&!87GhKQ$grEXi!%QF>BeJZVnT&&%f`Xc1;4DudWvPy z`)C9n&0NbHPFY!5M1Bv$y?X?(cMu6ahTaDXY!N7*mSX|mg(QV*ZeTh)hcR$*`(Vt9 z0;@U(NL;(SyXWeyi2#lb9>cbJ{20%!bx&9=OYH7&R3hu+yy9YX4-b$3%L`%^Yr!0y zMH|bJrp*ws?~5WAKsapXq*jq*xnNU-F4+MO-4YIYFxyq_m;vyrkFGt}{7?UD2!R+7 zLywKSFhPMTbY=NwZ+U!vK4LS+j|Nc;V*Ren5C<(nm;u>`;0#6jY+1MZ*zbY}xM9@d zsc;0<4#zYCs|2!l*Ht{*eGPLFy2!Z(TT;Y#ZToj~=?-4b(USdd z689i~!khjXkb&|F3MNCz+^GUDaX-FZ2tj-}=rH==|9fuT&FnYkTLBhx1rVHzshk^m z^b`$eNooCG)(9Xm;K-1=-tXcLzl@8i>y2Jw3%hk&SrHiGxA#IdCid(_jw-z(Pfe zl{mzhoSftX%_pF}w_)>$^VSYWK@Zx~(?iG4f2b;{2goo&Obg7{xJ`rdpr z=)oWfFTQ{@grM1->qW^wFLRDgy9NM5faNFeaPJh!WpYx+zkty9hNj4la{OG7#&y)vYMJiYwPRMBBU3xOOrQ-&6CSFSrGIB zwI~{~M}RNrhkUANMx~g{PyN>|w$wPxnr|nffpCXrVs7Vz0Xo%VX?zq3C-avt%>c(0 z^*-YRh(~W)6RYD-VFHtK0xHxu5I}UaOsuSO zhfCgvr+@ClvgP39tbuOgYD-C4R!fWcH(0>k+YJkficCR3 z>i(;=_=$!_07$fU=Ns;Lo&N4kU{-ZtpQV7?4Z0;OTU$9JBid~5LzN~29#ENNeQLa} zsMxA=VzpHC^ZR#R%S_+(R`r1fF^qrtAh}q+{_S?3fkC!S28vg5YATsNL|24_hHfW4 zGhB^4(MNs8EAL`>+;Q5zZvt2g;zWWjwHn-ufNk;#z~lElh%}Oc#Eg#1-`x>+IsX{_ zJ266}_f)%VKZP5npt0iG3S}^t4GZvCI3GU`gKW}&VJ~EMrx)&pr?2S<)ERWRv9$lr z`b(g%JMB1?WQ#!9Hxcj-;&iLF9H9`+Qb+6_-8T1o2uvQ%2|fYvH-MLNEVL?(9KJlh z-iNoJeEauY#eww8U{TK;fNDszcKPV^UGG+Q)ySCNjq``f%EHV2PdUYEX$<^%RgUX| ze0)fu-HsiD!Rp0wy1Hb*K}oyus>*Ne?8w>M@1KjUKUtjMZ2KM(b@B@fa#T@1Qn^iHW zjf=)QQ;dG{BfG-PmWuO+~6F4L+kpBx-I#A%@=I;Fj?4+iSPVyWv{pVj3 zU%&Q&Iu;3#_SFd`T8qF=Iz<9#*UJz6J-~W=1C7Ar#wAxuzth%b=84Oj3`W`UWq)|4 zEtkJrn?HUeX?5KrbnAq!pp4iExVu>+KkEDU@9WlE#gj=eqPn|OTTL*So16dXr}a~V zu7gYV4WffUyjKX?9tjBvHH1KCZcf+a2Xqj)aJ>1zCn1C=u6y&$A^aF{DQK{LfU-M) z01-A;*3cC0=PW(Xpf_RQ*DrX1aer&2ltz z@Ybzc^%g@U@dbcl^wpou@43S8`NY70s!G4%VOSM3awD)jY3_7)m7Ei4MH#u1$q zQw~nHwXJQp9G)bTusr-erK;JfbRk3$uVK+mdi%fv{qD=t{o+E^6eoTC zbUssA|9-Tzv^1BU%0?$}BHtw?z4PCfVuy87W%P*#44QCf34##KW|3}#&E0RWgugf1 z(|+4?oye7gUx|6_DT&ZE!RkN^tgI|7So?6RmP3)*uo!dMFxaq&lNKKQI`Nb^9+#_L z*qeiY>?J{SP=pB+S~S;CNm&{AhE2Z=5C3>>->&_lbrgF;AmamD6UD++%(m8xs=YW@RsOXGo!zR%T=2tDB~r@`~oltJ4Ae97X7J_feV z5tMOFLN~Z`#)5e>HU~g69m0983gJ;J=rry!cQfwq{#_aPrZ44iLA7W|t0x!ue#&O$ z2%T@mrE}u|0`uRpS`<@`p=A4{_ghH%s`h<0svEbFFx#}KH&0!hULftD}Nyx zT;%i22z5a`b4BL;@H#>>Esyu#y^kJ!hc<`Xuq_o4y5ZEiw6?$l!xat;S06saz_L}D z+&Q^wUA~TqQq1RAyZqi^Ci;9i;%tCVJt9V4IWC}{g8arGC8a;IgPwJ_GE3rzlctjk zQ_*Ijvz^moYI`w_CW?1OSpzJ-HQPe`XU0qCy)X{>vOD8-`F_y>1OAX6Nuq_gn4yfkx%zQzdu#7H0X+UgPdljYTwvJ0K9dWwh94F`Fp>jQ*T zf+cWJR3x~0qh;S>$4OK2-OS=0@%mwipfj@Gk6~tb zHRpq2LnRC?){^ffys<^%Xjp)bVS-a1Ry0Lfc{xJ2lzW#`hYsQc?ykG68BpiI0($C# z3Q@FE!Fw0Qev>xl<~<4%SA*vm_sE;uI?}Q|{6u23rfc(}Dk-)9qu*ZD^NemB9KJua zd9~;q6tZL(fh%%!eB~maF30j;oRF3bXolSC>MCPL2xKgJJNzI%zlHU9NVPa}HQ%?Lh~YYilNr30+wQ})nTyI!AZa_|5*`Lp)79aP!YwIOInLBr-9ALtTY zC~$7`JZNk4l|FpBhEHYw83Z#Wb@nnzjFWJL81tvW`J?vw^=mGhz}qMR=};LEsH=j) zZ3NXtL`0aMXL3NIbMBd423>zbA80Be1w6 z%_gy;+WURJx3_<6yq}fx^YFmqa3zTL){}iZKzrtCn9rq3Y${mW-aw?@80wU`rq~8^ zbTMPbNFTJPj9``6-F-#K0CbMly{p=&zCJ}?hzDeol+4<1KQ-KPX(4bU7jL;dt88Z` zw!gD^+*DGv(ZDYtNI|Z#`raJ#9;DnC3PqP#+ZD_B-xp@UP7oB^zgB!iT|Kql`+I%E zKx0`pP+g>$Ri2Uit0Gz!$uW43W)(EZbe#DLd*mH}5#pfG7v*L4?V(jhm=v=mGu-y( z!NsJInU==R1GlI%>@X$W$af>@8MF)FX5xX;T5b~Qe$<%=db_7)4DTlfj9R~;2?Uad z35I?qq=FY;tcqILca0`YX&EjL*Y&@2b~W8CscX#dx-I_Neyw9~4W{7Bx|sGxsGhse(>4lzw)=t(cz-TerjeesECG%3k9#Xc|brB2IlaC`IC~ zyE1Zew;pAQCG|&B7Dw<=SJvkjmWKkN_6puku`v*@oeH`%fO1n`qy`@cvDxkX&VNKp zT`1y8yGEblrDb7V$^tt15Cc2k*PF<`?PvJS?NSsu@jak_Ve7GKVjuvdH4=pF?`DOj zntuvw|El5_5U4TkM3M6P%SA2iYhW%9FmJrTSwhgqkN?#WKx2GY0?@VeLWkDZ@nW+X z+I1o`3v}7M&l8^t)kXmwnf@Ymge5<_oMK^Xu+i#B2=9~-w->)UZ}B&jB1F!S7I7Nx?CkApg_ zhzb)Ul+gUT4} z-sEfV*r5}7^Y?RAEq<&OA&J15`5VcPv^>3oztAGEL^O3wxi(q)69C9GMzv{zt;Liu zKK<>HdSi;S)>fXWAjSI`oAW=b-P1EO!Q=v#VYN&kKI|>6sQ3Y~u>VOyV#I$xQSdI$ zSnx3Vb{`8*$kF#9%8TvQ`+n!!<~TS-@a5p<0MwsVVP~Auf6KWVvs1C1!|R?Yiox>t z-sgBpYswxt9@oem%8yotgRE-P164H081Ld*B7uYir$qv?Ngp`IufD>eK1U4#+rN#C z%^J)cAoy7Y#*5Ic3)-cJt4HU5zHnB3UOyOzDV&{)>s8Mzu=>U?2d!Q3aLx4X#H(Au(IK0ahUxgWvPtkl%jLkv2?L{) zXU}ZG><&8*4=z9eERbA!b>-bc@zM}XG;ey{+}%?Vrey{Zk(A#Zmv;PQioTgSQ+vHd zv9WYa17W*8WRo$ur(O^C6ERoCs{7Tp&rpn$FD(Is=y2OXF!fV*XE%P>q@gFC3rep#xl ztnBST1jsT{W(HIV4c%971B#mtllyZn678=Cj@GwNvBlW$i#cgU699m@K1pb;Z-}Op zD)&VH#pB0qH8_PrIJ*bueKAOi?L~m>E}GV*93e{?{FW1g(zceeXSC@c zN-scutxk%YQ>nqssGe-$z3;UgxUknZnkD|tEts|mNJ&?i0?vLUK5nY7e|LCvbPuL` zZS}K9Sxeq4!}oiXLg;z;Urj4qz*oX><{RM}{<-+h{j0TL{dRu-@z3mTgQZ2^jop76 zSPy8+%ht1)UpiDws%xy0{3z~W{qV}F5DX@`c+}_d!6qgq zK&3S`HKhVgDhkq&pgcH$MWhzpTwGRQR1yFj<7R``uk=f%k>$^4ZogTpq-EBp5=BJ^ zL^<{rjFRQ!f8s|}2UQ!ED?D;W2k}_`ONX#-Sv3q{3Z8N)Z!G z&EdrZmdC?th;0~#@r4XO0WO7qtDa5D7tQc4e>}5F7wC!*A#(^j`?gC28Z~UE3@lm% zI8jqW0DQXi^nfRte|zCw&`QZaeV4>IOrPKJgFlyzkNo%@_&uFjemGSReum|u|7nNL z$3VX`#rb+!-ru7?Uh``Br{whbYOby=*;q!ZDhLn?W(LSqaSg2EkO%JxBZQm+4Ufty z7A@;0V5FYgJem*~leh)EEms%_&*nofAp6eyaF7)N17{1ojNxFth{^Vq^8Ju)uJ^O; zojYou@~2yU#e=r=inm4v#tN*Pw|5WSJ;n~|j(2~?Hszlls?D^TBjchHXWH7V|MPVg z$4v&%FIE3E4*E+1*tXsva^PTRHvw># z>p#5=%;+_4`-ZM!S>8~+Wh)8$eTvJ+#kYEb;8h7`CNlde@`R=gT~^_&5d4f&y^#FG->3J~dJ|fR>0ev< z4$gdI;1TO3hG@s=H1`_?dmiYrA^`E{0Zm6#908yCftG zl9JQ`8vN~una>d3N1W|@VGZDn_on#rDqsuRK~-%Z(l{v>*m#+<0|TR;X)9XGXynE- zGxf_SaB~p@w{9>o9?^%34pF&BZ&l8#QH>0QMp8UKUw8BP=AYrm=u9UpY_8`WGl6sL zNt~h5Gv|;G>gDv6TDz;WRUu7#sVGfKUQ1OUU+X2}1``^|b>#N`!3q zJpw91^PUFdHkeCNHR8e@A*vaJ4PldaUw8whXC6NckIB8Qi6uHpG717f>+auj(4M}||1B73Mz>u_l4T+cg$Uf;&bt)vzi6B9EPDh}wWUV}N+ zLXRX_5wvFyyvxhV&c@%%y-QB+12k60f*LG@uxLT(6Q4mimf*7IfsL#Xpp$H6YKe8X zh}97k;_dCHY>S4=%cLv7^xc5k?Ujio&llyQak@Z`_IRZ`wOsVS>zq^$sJg4?~M?p0B zb^P&Wn^7d6AH^f}=S~^k6$YXLP&0Pt_=u{2#5? zJ~fTon~i^;#$H~)${(>}iuT+e`M8K9j26h=XDp^dS07YAl7cg2De~rMAz|s!-^&rp zM0?>^hrvwv$w+G9bEv*$y0p!WVFA9{iV{`Wv6(N`o$GOA-M zyEG1bRKZ@8q3_HEv>1*iX@dz}D1?%Jis~j{@U|`G>OMyR!~i<~_hJU1uo&c$WvY8L zO10+Ny+m4`wY0TX+E-(ViaH;Nyk7L7ZHrs&?lCUt*B(FO0bx8=l zM|l)2r%5&v3KGtgpNn`0nu-TeH#Zb1n#MsltOt1KIF7X*gdJ}sX? zh)vjB@7I+s3}yxLa15xeo7aU0DTujM6kQ1*`I|d;?V@BFk24P0^==io4H|W%<5+_C zQNhBHBr|{AC9m#rymG+9!mj^4?1;uBj-trO0*o#80@t|&wx#qQ zrG=K&v~-;UYFI{dwH9~qu(8LX+3Q^}4lq_Bce$IMk#P=`jJa^eInch^YA1%GE+{ok zQC-7Y!rO21tcJP1SM`gJ82-a%rohRRQgzHZMfqEJANPw&!&;Ox>KfMhuGKUL@ykN9 zFSG@X>Efa^&x&$BbX?d#w1gSJ-eeRMhzXyIplg*60ct^^L7?Ul4f#v=yY@y2_$hG= zQsY?!&4iKB#-)D+NR#ym+1kFm7TL$F{#K&&#sqhWUsH1yiFbT{kd!)uIRHyw*So3V zj(Vd~Ja|qXk+@^jm$X7 zJ|C_b3=DUjWv*YNn0>dVAv<}Zo*vD4$iMvbH>_rYXf^OqPo!-_0D`QLnGTc4zc*e^g`6cJ^yPT66b(*$G{2Q`@8dfnjA~ zN_G+M;QschIk&ZX)4KftbQ-$WrBMXR`~ABi0Za%a>>Np0z_TGZl_mG}=z)QOCq062 zwopk=$%QN4A{BkA&{uwRGIcB{uGDY+NP$57mCEt^+jAzWdD=<6sj0ZRUUMTHNq^o- zV+=)2W@3}o>)ToF7p@+tD9F!Q39fab)5-&<`geah)=H2AO^Hs|{6CVZ7eUY_y?bX2 z(0D{WBTb6ql^R|vOB>tRP>>?G@KxOdBz4!nj6&bu&gW%Hr!Cri-8ZOf2~qQ;7FUw| zad4Y1hE$sFGm;iZ9z^5>F=(`TSDfSdNp3=T^Ayy!n>c#a%-eTRBe7v0=iD3@E32vX zfWECyF<&EILF(tp0VV5LE}KB~9!VXaU>zn0f&N8^C}H%}m&q&X?d$Ak{>aAteV!06 zgdP3J!GLK~6kX5KynsnFL^2J1iO8k4+^DA41G+(({0ZaD(JTo80Y=1^V*=J@7q}U8 zG_(>xRU!A4xX!J0`98cIS@r(5@alE8l6NtRz@o^SqT)kBog~tm^MB4A_CE?2N?Z6c zT0;~EN%0kZgiRgElbZF6`C=MQ;-tx*79d!RdgyHIUcWAcW+t)@HXA|i(^5V@zRy)1 z7aZ{3b%2zmP~J5sJGZr`w1zIe%Si5GPnIXd%&`1c;6E`biDWsR#A&OWuXFvaMyv|S zcE+ZHhc`&0SV484E)t8hE`Qd#gh3?HOR3MH%u6QzI8HtYvUaI9Ha4yxqG;;utcgvJ z4WH{6$CoPv0%#Io#sg{jSa^7NM7^1fXUM6@M{uFVN7hc#+ezj`>KDo`50J%r6kF># z@@y6sd$ZlTVzt-Z5Z~2G%IT%4%4rE%T6_J+Lo|basH=+FKEPfvO=1E%5*J`?AvzzS zWPlI=Q)AS(x3LITA<_jAl2Y-!5f@Bf56O+bU#l~syyxRMYX>du@j{e#lq8*0=7t~PWc8xqWMlt$7YYV%YQ-cBa^_(LVXpI(}2+jmVM)A zsIgwfj!P{TPyB*vF6s~m^VF9^*_d7no8PXo3Eoq?WtrLJ4;P z?&e5@M`wzG6K17u&0EMPR|ZhH>kb?+7!=VVv=FjtX*mxf4K9*MhP^)*FVCVAU&dt` z|KMuX#vb+%R%N8&#fwoNkC^lxt$!|E%i(J^l$mbc_w(*uXc|o1y`NHbkI72#ON8e(Ied#hW@cfPq!GG6^B$0*+nFSThWvVFhY7UGL^29 z?{1jdc%s=ix^N_O3c<@h5E>N-HcGtZ;7ZR1XX!&a7Hxr3axJ3 zdi0V_fSH{9BNN7uBaclIR&gsjet4gig&y*Pl%-{LEYoMjERq!7s-9!DFtmP&u97hn z0mg5y@}NlCxy9s~eJ-4P+wmhowFEd#g#TCeeVno;JN~d4GUBsXSXmumj;S3qfBLHC zw}b;WCfY45fvFy!oNs**7&Oa*cu|kyxF>p2rr-Hq<($MzmLC(Baei49xMobn4e8PQ zw4B z+J?e>*7#h^7#dUw5xKDa3M@5;7D)-Q?ZPCB+nI@$m+~2fu^WUNMTJk^m^Se|o2jrW4PSm9@<;ED+XYLOSJH&XpFN!~U{%n?^GxuMQ^pRQYM<#;T zFJ44C2!{O3MlO-h-qJ(o>P`-NS0Hak>!4w~A7@(U3G$kENlCr%pL~!jA}HD?WJwPp zE6$fKJjA?}O+YA0{z$TOl&ddr!nD3Ja)8QFtJ4}>?13Jvf(FXeTb z;JsW}0#7|$x|D92C3fA(ULq>`b;V^h!?7zlAEYc;l!_q@R4usBKr;TxostWm4W3sg zfFoyMX)5^j%ZBazXQSD8FL!&OR(1w*zB*^rnTORLWr$9Gk@nqSzF!TbKVJHpifpws zy!oG|zA~z+E@~I)?(Xgm0YQ-NM!FkBx;v#oLOP^Fx~01%mF`BQ1f=0x=l$*-_xeK_ zXKdN$oW0lDb3XG4Rk^U|M6R$xH7E>V-2nYa!fVk(@kH+s55YS~-(b8S_r8Afkth>ds zx#%Jiil9hN9AwuIXOz0J@ar7~fBPJU*atAmC&r8XB69S7;IU$c2g`oE{tU%@*|3>~ z^tZ0rL9&2LYB@1CR~aD5R(Vr0kW7b0y(&V|V3T;&Z@+A8Y&OBiR|hs78&3Ub(NT_h zAF@f79~jw|`ZAcbBCTZ_5NWYm{$Ws&Mr|c!s?!pq5x8}*M}mMhR2@ULFdc)E`DZMA zvDl@$bX3jkjQGNjZ+SO!RqdONeNUPo({*s4#w@R_=+fmTBEh}M{xr<4d;jh3~f7j|Ao!L}F6o&zhQLOSU;}5&7ruTyc9SQ7H#!0blxUf1p{Ar!qPb^Vt-WHE-L6>X<$nG8)#!a`< z_CwSWxhA!brsyj7)@2_?1}T~ZE)0NeozvAx%lU+3APk*4&wkO;=S=%8e+K2bu&J7K z#0}?RGD!Xrkg$J^k4M+~_RH)S5-h>!J|Ox6njpVJ$Az>`)!5I)xS?%<*<~0<%E-(D z1A46c%rC06V}=s!Mf7xkGo$-r{`s=s;@cnpCYI+V{_bg!E!+h)HC!0(B^;mh*X8lA zwWye*3jh9J)Rc_;xr%aLA+i}AQXvd-gs&5O5@0y-e*z96JoiK}^kY$>Z0#x2WX=Y{ zUvLxf0haj|uo`5ZPwlNk0&quR#}%%!oFZj0^%v$Z#3f;{gi7=i!$OSy)y|4jVTVb} z+}y^SG1>(0gWe~Fousjb0?+L(tecJwU50UP^*OTJZ3&DWed7n?X%bY|#|NT}e-`p` zuP@JUadZCs)~@70MnQqB>OP2x3mEk|dvIVHyjwR^fiSVDsiw!x`qT=IuLp)>Z|fgR_Ljt98M$6?WshHipx-|dCzNoU44_-Sg!dO@wM zJDcSmnMhK&OXX$1>4a(M_<6}^-MJyZ_18YMdDatS#s{L*q zw35TlJSHzwF#1)NgjNpD+8E>c$+$Z~=(LLf$%@C}`@Z~tXPgoWPu!xC8djk0yWn{% z%XwJWR`40EEvB8T)usiixw7(;bk+8{DSrgb7!cgAqq%0=2?sm+oqW5U>3*a+ZF_O` zx{4~j*fsC&`PvXT8G~!{p1Fd3!t|yHBSP;D?r|0{6avPlFreUS1hXG!d{#^Y$_t49 z3s9|xgU&$Y=KB=WeCj*S*t7&*nl-B}`*tO+QrSW^^Qkk>?cc{OJNINQJ&B1?LZZGL zM!wz{U49#Dx2MK|N_A#j%yQyqBZMkS2xW{sU&dXy*?kzwyB^lg0&dJ6O>(p(ptdv< zlCfjqmE}2^n=g}T@$Mgd&SUbP5dt1=In>mRg1evAMK_a_vJy>ROBAcq;G$A>*J9SQ zPU*H21}&8hhjBn1ltmzOtKXUB@;?eJk{kLYnW`rJU;qP&!xa@Dqho$k2rxG;uFrGcRpaAusz)EMG9;) zz>M42>(G=o{YP|cnkepmNp*nDFXC0_LA}`@z2l!_nty$cRMk$A0ELas5z$v0;p%ig z?GHb1CuxjBSNLMj{9X{e4r{uDV<%X{`b{yhn%BH=erwmL(Z;07CzbIIiv_C^f*O&U zJPq%t5KuMRuIKgh)yvPpb1E7Dp9i3+VAuqT{>Mq7v*~{)D|l#c^G->&bo>iAW?QKkqmjwCvE^uX((Ur|?IBFGPxp!Ur~Pn!o0$ScGKqn_mG;=?4b#~R zr6CTDDm}Lp(S~fIp!iNqnwi4!toU?GO=<(a#;7wB$jKp*Skb~W0E2)5CQQEn{saR- z7RZj3=DI+WrtWx=WEtFcX5|>wXjBpJrSxfglbCuM^p+3p1HVD^jtu%vbQ8<@cJ;yM z)KgX3-~SwjSisZv9cW27I7YJ?F4_)z|AFFdL{`o$ZCHVQs)%|jDV^xwPu|0;`;hLmF!6xb^10V2m|H^)`k;wRdJVNb#yCT*rbQyD}wjr#jq1#VrEc;h}e(aSj zhD{al#7)GYvWXnpuC%bwNYb?N%v(50FsZBQp9Fd1R4r*-lZtELhEO=2IK`#CD zyXmu~CAUkQ(w&!yeF%FMTc~CH8S{@Q-(<@cb_7Bk2K7RBi@!?+)f34 zV$-kb@87sZCypoUWy`xq9b;ym`RQd)7bC;X6U{xx$kZFzUuEc|#HhXO42+c<1DH;)$%6-zVhbH9Lgb4>Xyw3@;&yK;0C{2LJliP1Uv$QcwCbrpB{KzbW2^sg z9&nrtSlQphOG&cW2OX-C@&g`{6i!h2DAM7TkAe4zd+W}rFC;-}<7t24@azQOpR1Q7 zU>H{@Z7GH?W9Gc>ClvN{{waqa4%g|3T_l^d;CFIPE^+j(6NN)xcqHo^g@9No9R zv@7bk&VHInVIBvF2ok21tSlg7o%aSS`TM<;UK}yMLsj zX#(X`L_0H9FMbu5OCrzSmnUmFKF@P7#bQn59jcEC0*#^ zjj`@ZZQyjDThOlP@-cyaU5?)d>xq%nOFN3jZ!#>UO>RktEMX{dR6L0Y`qyokKHeiOtYluyLhJ-po94JJ*?xF~NuF%nEo zeo9yhqOa?eu9BPxYNxw>gS)o${zIHslz$S+AlX2pQNW3v-M|Ai>Hz-=3R7P*9=MRv7t`EPDW3P4=qEH|Ys%B+ARL zHh8P(Xfk64>FDeEAb>6e70)|^^Qg&{+-Kg- z-R8|qkgsDq(t^D~48`-#%~!2&buK_y0mIY!936K%>+e}u--e$gUpxX#WLs6YTmZ zll@{VR^a7Yw+t=z(2^UuYs5rsqXi25FukpfeaK%@kLL6g?`^Q?WlQHwfx`p@=>Z8m z+lJusfD)6Fk8e=)ekK9rMjn1Jejo-uiqs#1GwNO}Nb;QHRsD5Eu<;nJe-lv*7mD6_ zu0HjIwq9#^<`=XP^RM~{0eb%PPQ**}mk;w>6(3si8#}OPWF-^1Vg`4-+KX|R3hBHt+a2T{d zNekCq!o?=UZT;%x5HFr*oRxu9{iucx9>t{gb~3yr6MMiz(rL*uO-)G&4WfVmsuLW? zP&fr3fD$Gj1`fL@01N>f9HEsHk3sz2Am5OLW)BUcww#YqR#M9|&Lwzk3@SZ4L=wEj zV#4Gyyx6^Do@=4kB>Y>~Y5yp3QM-kZ z!&E`>>!X{HCu*#!ezyxjJ*c^AKd!t+kLdThKPsilr9(=^1`;=rdh7>wC_SKtFb=re zlP7i!c&>uC;UnG^Qva&P;##7s_CD^R>z3g52M76}_UQ|2+nZ%mdD);Mbt?WEs6<(v zI#`(`NhcMhhPjh`w-4AgHS8JM*bElM9!KX}=+gp(8nYv2l-C zfSVgDP8ustQdLhYczKTnQ~O*`6bjd}G*Pc=+f&)Imq3-Z?+p9@ask*yFCiw!z}^Lt zCIG>J0Cxs9qj{NzwrrYE7=|e=X&r2TOz}H^|+@dIJ5`}IR!=v>sy5)xu z>=sDp90MQp0eTbD)*B*~z&dUNh^auGx&8cb7SW%-%9HAR#!F#$N?QejV?yj1bzAo^ z_~xscas7aIK2d_molwW~tdT)mB{nD`-Z!~NH!9G{9TK~kj#0b=iv$3m6YZDWQXHn8 zc}1`|N=j2sH?>(;#Ay0#NW2U8*a^dGYKEaf8yKOzh@gVFWV)qtkJ1}$^Z~5BVXg_(v_zK|ltyPYZnn?pU2Chs+-d?7b zM&H@e=2H{dxL#Rj_n%LN;W6n7;2>_EB9Kd}$(3(Y9V~U4p#7ay$4txc=w2&3tY|-J zUIB(8BS7d`0-PG_Mn2Q&RAOR55KRC}d;D1h84eXX`pP%x&Ig-}g6gcg+TA{YSJ%jsscc(QA&NY-*4MHzuuF0FZTK;GZF{I$C3;u9WJa%5E%+Q5TiiEx0<;*O$;YE zt9KU!jR$%ca4l}HN=2)5*xjt8!5GvNy|s**1I4FG3w8R>KGu)7FaWKoZ7T>$X(Q{R zgd>DQ z9B_+83p1(r%&qhtgv5Eca5mQ9(aAWb7%o?{)7(Y%n}kTCG7spBsyqIIxVX3(V9CUg z6cVI$#)D$V=0)d3o}$tXhDeD+4pW>4v&u^ZT`BnxQn{YYl;Nae8fy zEt(Gzzk>nD`D+2>G%+!;$zptm%(>ugvoXB62uopmEbUQ&hn^K~p?gbr5J@Cwb4(#E zfL+M$TfEO=|rI3#)i?xI7U1AesT(DY8LqqRafXm>ClqmR%&f%d zfbp;0Sk>{JK&XvHHdfQvQ(+NN~-C>}N?(M9tGPzwI>H#4U)5JLgF z+)*@3bXe@Zj*i2@@zPu%EI1vZ}O68Jb5q<|pt zy__k$i*a~6R7nV01tG8R2O;xmA+GcXKlaQ8mSeEYQxuA6zw~KkF6FS93g6jn^0&mI3%_6FafmD0)G!z6!A9q!JulY%bD%r!N@@ zuhjjVp{AdrK>Q^dgU>TbyEiHPbyl1MFm53xB>V~l(h_0$aF@h!(xG7NEaJ2Y1>Auy zz`j#{820g$e78DZjd|2VHAIX7f9enR1lwEX*EW1Q8fu6+9$R0e3{?>-^nZUFDVuZI z7!l}8EK3ih2+GJ`C{xqU4xN$X09S*l?V}OMGz7#Jh-5$4fIV%I7iqtoK??XIKx{s2 z{rpHVL?1a*I)n-12EET_=!@tXs9E@k%zkCZ$R|N~P{RaYqaRt>ClvKRuQh&!6_~N; z0ptj$`1oXBJG}vm$sIT$^~w}8E?13~0Q<$s!J)cf$ZtV^7%O2sB{{QCItRUP+TW=kHq4w$WR2$?@Ho_-*JfM& z-ZBj~1n&&Zq?65ka)v&&Ex4&=6{rg2dLZ1pTg-5XA2N$>Dh6|5kS5X#EE%pIFQ*zX zO?&-7&=W4i>lYXecmtwRbaOG7z<}9uJp-MKgHN=V2k$q38eUH!thmA2;;v}4Hzy%z z*sQJmZvlHrD`g)ri^|sosrxby67W?`wTOv9bed}%%W^7^T|#-ZlYwYFZr~;h=xe4;-?_6mPM8q=w9-28(j*ce2x?8wRUin4i07Si@P{(v`0 zVhFHfx}~E(q}S7nKY6F-^v0tLl4y5@{-l`voXPE1s4k-1Fl#6V76F%_N5suZam=whm_g#evo3A;Wlw#vykpQe!w6R3JIN0J zeq?C;e<3BXI=Fq+`C!3CP<_=r+|Pgi*_}{JX|V&*Q&g`%h&Y#e8Fq%2r=4>awPHwDTUvS0(cgbv>qX&wY84u4|s5QTn zpdEv6d;J3#Uy;WQh5#Nsg6QKG#u0z_9U21zLyQvyP_nA(*rG?F~GB4M!Nb-zy5sv7!~sSX4+;z0*EA6TNxK1_%6Oi}@E zB0gR+Fj$=VTER&&tl#e3(TR|i`koP=4UmSSQ@wBy_hGs+D9=P^q~|4Z4oX(0tkN-| zA7ubL6Kt0a3!)N$Fe9*GYOLA*Pby#2Rtx2~0*V))4$$mSU%c3J^2{dTF#Sjkqp4au z_j)SOfQ5#;TYIJfRugwbww%8k`yQU4B*V&&pl;fStOxpShW45exa4%w41?`t{yhNu|s|5%CwXgQ&U z=Wrp5&bDuVGXE;zIgXJI!cl^+WahBYh0i%9c|$UZmCci%{DU6w^|!rzG2mCp>-GRY zBmEuYgp6K$57cjkOH4e+fT`<%SFuV;<~DvwV=g?c6_mbe#8*=8I&GB#X@AL>ggM_R z)9fTyYDG0{VnCL9QEBa<#Q={Zsgz`|@Crcv<4iY1G5pNCk721T!;0+t4;%^R9~3Ch-yi7*<0pR-Zfnk0aOdiZ$> zR*o8M39nG~)G~*grE(Wc)xhSomHEpZT!}-9YbS%%e{Uh=$>L?%Laocgq6Fyt+Vc?b zeq;fgp?`)@(0+8o8gBq z(|}9_zD_;0q~Y(jObXkpPHNqAqxJf>x^mGKzdsCPhA+gsavGiCVqCrEAwoj(w%OT!vvjBB#p$& zjg{F^VB^mzFxYyC9FH}fqQ#E$Dbi>A?~}+nYY{`|W0pL=njt#tCrKAOizFGB|J&M= z*j9vkl@vKTkGDs?;;;vvFoH6}x_aCBHq_8OI~LlaGStohvbOBhqVb>y8Y5Z&r~;M= z;0P5XT?qeud)5L7*35DR*Y5|X%hKjo4vPyU-FAwvi)PBc`!2?rcpZHz0Hgp})=#PH zVyEQ9#cc(oM*6z6tU$z?IAi;>HQ>obR?_CrVgF)ELYfOVdenc<(hJ3zvA@uh%1vy7 zLX8#%y%r5f`dXTRh+h2a1~zrO*yanZsoC zQCAae(hE;re>Gq^lsP622Hxy)GC`@!4~smLrq9>o5s(Qv3rf8$(;wmC62H}-dy<@_ zR3FTso2&GP0EwaR5)TnKjHu(dYRBfc3pNz4#o~8?aj}>uQq3g9Q_!;79_R1E(!31* z(0=M=!iVlyjFL3>+B%WWK0Mr08fP|9Qq*zV>xqQQcooPQ79Wh|(I#x6#GB77n#G}S zgkGh`HlR(J&Ttjq>b(*5`YItlS-EgOvw*aSHdF4K8b@0pH#BClWkCCPu&ZOP1)k7P zHZpMN`bsKrN&Eyoo9M;wm7*ltbscT#7^bU2Eja)!EFR^)1H0CCee80dy^*d~kYf9L zL=X~$5d}yqGc&`(E54w#%m@6Y%UKN*75O634m};x$yfQ-i$55I9&F7GiHyJ3`^c@( z>Qyii8^7_1-f%c7swYLz-nX6+pMs^sdL?;CM7|fSh7srcG@_)k71w0RIH}BV@vKXk z{sOW0`}5}@v~*caGR0P9zkU@p-R(^@$N6%vByhd!-I`ZEL{xb&be^uX@tzt%H|3aT2M*z}8d!g%c~7QmiCL^g@#04M=d22H^%mkp^M+V2#;%ZdTUiRj(E z5NJQnm&eRFdDsTz)_8cw$U@mA3!N)QrgpPlSK}UZK=)FAt!v0L7V(J|Ph`Yag0E&7 z3#aRCrIhmWp&tNU+1EFsBrE)Y)2iIQJDis4^W`gpv2T_Tyg?&)1oE8B!*SJZbdEqd zQjWxt`JW?5q&O(`S&ol=r{-{-L3HFLml4305@x3%CK#lK4J7_TE0%-^#*IF4Rx=$e z*9a0F2TnL`pQM>^qY6Mjb4lhg`+*N-pNA7BLSG0#7IPods_<(#!=Umk$3**IE>>B< z1EaRS66*5K@Q-e2UwSsWQ}=l2q!>Xl9YaAgX9T4E%Otbp#h1A`XKaI)feZrXdNGBK zx^-$pE=jyNL9ZL@!)9Hiqn48KX}gkFPf<$x4ZHzFUO@)KUQbJ?nvyYeG*1iOM>-fi z0dC2Egf?FrC86ZdWm|!6x%wY`(zz2o#%66)U5TIlp_-Ju|uOM@JM?wqjE(k}?j~KH5@?Gm`dZDOrDA zu(@?zaFhmZo7UgXikQrrI;#gThe)7ZnNr8hlmnxmpCxc`vp)_8*~*UEok9$j9E)T zNHbY&_vN$<$t*5pDF3wDOaeC1U}vV+V@wz)5>~&X!LMys+zw6vobPdhL}o^aTUxp^ zmF1EfpdH*C^YOGfY|Tyuoe8s*_|L1&<6*Y}wF#00*~Q!(F@QP>IUL8Rd)r&LuucHn zd*0yvD=8x|a{QPyUUH_ZsbSVl**t(3E>o*2j6X1N{E!BJuyliv~G>2z&# zz3^6%l$Gb4eOmZf@DU8?lne7e#ft#3TO3S&?RM9DT4IT*bHeaKwN>vyJua$nsF$O) zIp+MEmd{6SYkSMtWN9cw)1Qh+pShGjUj+`nfq__Ir~ zHsIS6=A3Vjz2^fbL^<=sA0Rq^7-`lo2P31Fy0B*VCB5*}oR z$^+f9LH*I?@}94Tl|{h!l`R*EyzbDh8x+Vj{{bJWQx<{(4Kr=qD9icV+rlpifG$~A zF*m5(OZI(nY4aMxUtofK3CTp zD6|Bn0#^Rexg<8)hS(UQ9D1luc7CfqwKgAjF6>wzF03i*7b${AF6J*`CnQ=X%$%X8 zru>5(1qhYua)8!Zy^p(C@M>CC!}6-ZQ`J;KMdB;nyks z6#{i@C9bes$(akKLbA$ zKNp}qH0*4{ZweRexHN&eHzapaQFa9c^FOJQZPQo`Nr(*X_oiG#wOwst@2QLEU~hM7 z!7Q^aVs-VcK=dvwj$tIKu4I@K?O5nevH$=;z@*fO<;949856N4g^Mu7Q~W@RQ_0$(ITx$u;-q`*+|)n0PzfB7CksoVzx?J7|M5`vBY%N4t~dpP+7yC51yI< zrNzkrgfxG-rA^xx_zcKEA!-Q;z8iZOf+))f2Am|}pT+IWpZB|Nb6(|kP zhnfh=?t)yxB7@%OLV(v7B`Phi06)#ONo`CSIc4O3)Gye-gNa2L3*aG&k0&KviClo?xL@;UF@z5<+~Rd)Rxot%JF0#Txe+CW-uO6{ zqlN_oWcVG;wB&W+rJ*?haAVYIe*MQu5HFNK%#RZ5%7exCFB^(s*VBGHh%2!WLVK*xyo)1#3+2yZr7>_%? z&Jokl7QK#(rD5ttl#@b~DM-)EeFeif?rb6@ClcK-_f@NWAPgvwQP7rE4WsL`QAL)P z5gAH}-Xoq%(E^yc+PIsPW&H2= zsz6x4cpTW_PWnL);0kFl08W~a27y8|y1+C{8qM6q9y-wm z6N^5mkteAzjiM=~XTXSk-@LPe5}W!lJE}(;28@z0r$>6aiA6Sjhox3-lb2 z(SvnKXzy8rH+I-44s<0VHrBu&kcO==v@aLf>OogCjW4=*S!2nUWd7^ng%BLuKamk;_g z=H~?5|H8uGKde9S*Rz`2^h9yp9Kzk%OS-L3QIB(H`*)_FdkxTHB0_$xYm8oD@0J9@ z#UsxPT9Y0cwYZ8lLp+5y!iCqP%JT-`GtT{B;1byvkqM*wf?SUVIAL4zOjG;@Fm2)HHV!h#L?-Y8Un0t*eX!VEvi?OoqE6JLw=fz1DpBw_S2iPenWqkS2J0yEM$ zEf_0lMnXwmVmK@+@&xm#OCjfewwA)OBHVmcM4n(MTDcH0$9I+pGkpVNko>a!kYQGaL zM7cCVs}u$cGfol{6&~aeH|m_A9DX_QJi5AXkRzlG(X0BzI*vFw(Q(j8f(mcbXx-2oE>iWH`YEUfHxwG)1K zpgtZNKV#Li?p&uCi+>EDuhwZG<>)+rr0}k<&ZiQ-+I(7UEFiww@Mif0pRHQ{6MT-_ zwdC%h=JEOe__xU~PcX7c$n+Y}&v(8XLl8nw&1`$X?xMf$h+BYHed@AC!WfYFT(cBcsYy2b(;uQ1`F+J%eA! zy8$Tr`&3s$0?}-DwBJVh5irJoRBkf#Qo|X(;qRO%k<@K}ac{jyU2(c$YnVCT6BCFJ zHJ$>NkA?zBF{!Nm$7l9~*(+z#fL8KS`O53C&aSees{h&F7mE=NjxsUQ{9<;`Yd5MG zF`|F5^#tbUFUS5V>kU*Uy2&gztlz&|w#JTlrqB0!ukPI4Je&Ep(?Z!sI7mc@MG42y`bdWsB{B`b!;p)(iqG3HTV5zOxJM{6)T<(Yb zE(UYZ*+Z+B3*GPawNEH4>{1G@8uvPE5t()8!4F(*t*{?{zczK+%4qc&ayx88-?+T^ zxfA0oCIy%4Z;J->@meAcsQIe!^ELW0KOF6QDwf}9viagSeb6%B$X%;6kVG{p*g*+_ zT3QlpHT&)MQ&<;mydDbblj-(d=3ct%f#C=-Csdl&GgP=l#P*MFhakYzE|cz3?pbS#@V8TD!+-Pb|fhxIlK4?!sD- zFNHy5e6vT&m%NDKw1u8VR>?xFSm6VMKg-`?)a4I9y(&LClGz>|{<(cvXHSw@BIYin z@HIH<27vpzx zb9bX`Fc$sU(TYzqNjy3x^%LRWD;zSaq^iwtHQiXQ)t&Hy-@T`K(Gq0|+TIAMae5*8 zO@%t%j{KkqOWmiBBtIK^|MsR_b7NSYxzok?TbT&HM{|n=Vz84HeF$aHSzGIFy*$vA z{JFitVf|Ju&WayyO1OBr#BSi^JUHVjf1)Cmqp9ZB*doENXc5MfpCbMhdUt=nSVrDD zCpAYzrk``uTf}UJk+~-GQ()ljtJ8FUn7=517whB|*WXntntoNOcPMZXzN(A-lb76BS?J6*g#sRmjzi+CGboIPjJ^Wr3na zcrV99)l{fa5+>k-LgmvqjT7bdS4aGvJle^}D#Fh>abJgj1gj%czxN;_GMzBKA|&^z zBu+E*#+$G7A%9uzoB0K~ostzy6?3?7Rz#l(t4Tsjj>^&vqDs>=#pc`|&ByWWUk+)& z=%>*<1CSKaR+UQ31mwYi9HzaqG`YPRBGA~d?mj|vmN z)5Fbnb-Y0V<9d0XcHLCVM&e#m-S6*u7K9^zB1!|ZH4)%teMt{KB$7HZp|s1cJD^N^ zIBdkr(uV90!4DM7?ADPYG~M@D~yr(g%x1doZ6!T z=c^KrBmS!oPUpT|ijkO)7%!ParOEFOj*J?fbH+I6c zw*<3!1Q7PjC*h%DMSU5^hVe}=Nl3nuz(eCvp0*A9{hF=+7|T2%aZ%f=qh%P*fd4jD zP2w--!?G@6dRBz~!DRoZ>l)Kl-Ec3TBOI^I8RqoV@G&Nhx}7-{PTNPF4x- zj@s=TFZYvi#1N=Ct7pWIRcz@xyriNzB5)6)8whKhoOZJ0(GeI!zYm^+?k-Pz5Br2y zpJR@>+!mcy-5v~e>K>U=@X?0BxeD5>;CKx~54_K@$>W73FhZbm4|?4VCmu)n7Vlep zV#&0EVi;lvTW7gb6w`a|rG740$}kn{pt>=;OBQ%J@8Ivz3&&CjY91~#wQ^`8mss{= z_}!KhSf!W16^C3I7|ih|hkns?p>@4E;%lq!=R}2q7Tcu3SC~BDQ#xJ@&@RSIU}#ZN zUa7;3l8pD>{SzkMsXTS_q^ZL&r63>m4o-Gp2Qh@Q(_mz`!(!voMECW!GeOsx1mdgl zddi|Ob!6uSDNI;E4ej&^_ur5a#t&6g>Q54O=uccZFo^_HKJEiqlmVb`BP;VyXT`(o#oM^ge26C@Rc^_B9vvUU&21 z%Gt|e!Zq*Qv{P55Q{^kYc@0chppflc&&7+A?AjK|zwst>^yVcN+&`<+IXj^q7D~kg zSH^*2yCf+6h~~$jmRDA&OctN)@#@)dcTsyrc>X5v q#zy^jrQC24Ou^;+?;3ZJJ;SVA?FnE6FN8pWKXOvalGWlSA^!t2=ae=8 literal 0 HcmV?d00001 diff --git a/hexagonal/etc/layers.png b/hexagonal/etc/layers.png new file mode 100644 index 0000000000000000000000000000000000000000..cb5a9c90bbe953ff87197bfb1834c34fac450f3c GIT binary patch literal 15887 zcmb8Wb8uzN7dCq06WgBHww;NMiEZ1qGZWjI*mh=OPCT(~1m|tJqm}7%q6QJHz+y;m3=Yd)BGjj zK>d06z9dD!t~gC6(O^nOHb&@xl0(?!$UiOdvCL0fV*BITat2s$jLO{%Zf<}fe(G+F zI>{IRO{PYB5mSr?646bHOlGw3)IG6Fhl8xXdKr$JysOr~L7FO#_xepEpnzV%)@&)j zo<2a@Gd6`Ew*1iZNa+*LMaGs9hh0&cJO&>YD!eLr&a_71*h|4{c+uEqCsjzR){l-h zzcm0RpK^<7n+oUsT%fPtUFdJEht835TB>ZJs=Y!@h`Gc7`!FsnovP7dpJjoZHt<20 z&Z}#VEo2f&<%r@dZf&Zuey2BtoVYy^J^~U>v^ou|Lb_)(W(oLev5ab`>ASKG?18Rw zhDx=}E;yK&FcO`WLCk~yEM(K(fxX`h@TZ!u{JJp*49Tm&zEQ%>8ANR>*odUx-|9um zL5M^~`6YAQPd@9VkLrMs`|@AjEPoY=gKGDQAJQt)r29ByJ@K-sr8Dr zz_!!A$jcm2gw2SOfLj$iOdoujb2{8MtdM7clV`mOK5=$l%JaEg3b5<8wVM2oAuL=vbj&t2H+Vw>1Q0^6$s&8<15i0(Hk-5z8XD(jc9Lcn?-|VA^(W^-ffnep~m@zWsv$1o*Vr3%b z(s(-0QqG=bO|L@}o^~SOaE}#t6Jidt!y5 zw=k3hUMSdng*dEo%_0gffFyh$yKxCBU7S|ldSuF7t?~V((IP~4n|U%Ivq(R#Eb^Km z_Ik94EFqQOJ98H0Ot^&?J>pAChy*d_G7O4F5zomB2h7i(fEJN-L0Fh%h&hM`2rLVj zhirpiWRmb`fd*^~_YNY;!e;9*Ml{Oc3rNvuh18_u@o1|)Mq(h-&X+LU-ZEz+BP98; zxOPbY*Uj&|6&`;#Y*x$)Z{)4%m{TX75AsY%p*X-a^9|rP1ogav;|;-Y7n11$YfmJL zn#;k#GjRbhTmE_+C*;~9H!X`czGo#26bZ0d1^L-2`)JXMWonFp+tJ-oU?8EgN+94{ zST_)vN+=qo{rHlWqzbhOnX};=V7q<28dJ}n2+|R zB4)6r^1opA@wTYxEq?Q&f4&=(f8ik)AQ$ju_x3!xsVxQO3oOIaMm{s7JzJS7lKIRz z%v}zq1&mV#YIjOqF%f3nQSK^c^;x3h5C(|2_YIu)CD8?7PzEB&d(Yk>%LgdmML!ky7?biQfr;W|Cg#t*0fhgeWI6=FpK5*!LY;pP^iyaTjynvYzNBRxN)C7jKD3Ij?Cb|icy5&z?!a5gjZpNUjYgd z7j$v}JA8M_%fv!;83EZQpIbrO7jKw3mATo2uvFMm;YIb{TUR;{hET;o zY{s0(z8AB#E!9Ez$y}>Yp~Z6%M=g?z&98lNzqLX+YN7&X@Vasxd}rX#4Xh&YmFu7C zeu;a&`WWvfIT+cQ#Hq6_?V796uXnGbxCug!A`=y=|2lAVO(uOA;E;QHF|pOVhZ*?f ziSV8rV7A>^vs|qqZJ2AUH#*i>@9>7%;NVZpNQJ7X#t0GghiJwR+qtQreycNNGiLlN zoM$A!>^n!YcjUUj$Ct(yesjU$`P4?SNwbcc2If^ht0c@+H9t6A5SV z2iE&h?w$`)Ax_xvzD{H=Z^NSr>*57!#brR#&pA}4*n9m8uv*lNr?DS zh^sv_XuY+YF@GAl3>TU_W?hu9Ly38jn^oc-^zueB+p`kyNT8%Xd869#DU0?SWGw5F^7-MfBSbCII0Pr!s0jMmb5G>gU@S3rD^}oe5 zN-=Ja7u@oI#Xj8-=6>49NA&#}ggQ;2KirI)Cw?{HUhSPr9XA;|uEG&=gnmIdjTgN1 z2HI@^J4{uZZ?2;&0&IOlYB)xU?W$@DGaqE>Qi`jV<<<7SZzJYCT#jm>2bEqgrxtLlMK+%kuRd_yrjA`So1_aLAP976DH za+Lny1~Jy}UAF0R70H19b2;BZ>M?t$i)DQF@cjaZ^O`}yU!)oQ>b$9WeeKEp(f6WW z&f5a%z%EU{&ihnQD@LBH$Z`=SNhvOj;EOhWypgtDWv@f!}!y4D{&t`PTha)pN!VW-pcvmp0D)jcraMn}trJC#62Ro%dN9OCk=*!|X z*CE->-46u%6_$`z*{ae0AubEh40E$bSab7+yY%~@w1#{YtyU@UDDoh6ao(Dzqb@Rz_*pd{dFZF+9wk2gNRtAD%$m%M zhi@iaz(z#0(&4q*2f{i`4K>Sh)j#jGIyyVCZVBFoP;k3#5olawB+PX5gYG>O41zN0 z?GIG$zM7(XciL(t)8aMa@a}zu3s?02b)~zv0vdcn%G{F~gvLdMp^=icC)aN`As7?y zmOLjM$b*G>WyU8y@XTqbfXTxdUj?2s{fTq<%?ukd24a zgm#LwFLC#h;)amly$E0eghm9wdr2IA^3*|otH!G3z>CgA48ES6YFDCFUv9d??h<-t z2!UaKf2T-qwg@aN!)XTI2nrVZB(pLog_TMx#ab-`irw^=rz=Pz4=4w_yBPR}+g262=C*xXw+3%B9;GhQ^m+{hw-_iR; zRU4rTj0>mS7Xb&bXL9NO0=zBFOn>?+@$^`AO;-k{WprIq~VBfxBO?1Sd10 zEIEwV?{9j-VOLSpXHm%w|xd18(DKh54 z_zQ&B3L1noN2K*nj^oyH5skna4o~qwKgadDA?NlG)ir-N9Jwkm=OZ*}5ZUhZ2aEm&C7h!zN zV7ES>D`fz7succ2Dc z>u!|x4u6&~MCdd@e%w8ugDmi%xj^~Qa3Ctyhja<5bYxTIK z7R>x%<0{yM5!gD}j?EZMGa6Z)MtJPWYsT&5y!f>~ndcHhs~ZdOPj7@GD@7V30~oH2 z$zS(g%+>#GuE(|43zZ4v^A=dlOC2(Jjv$&o;vj-2n)!PjE3tnzE_?c+Q z+CB+~F*Nk>)eGtJXI~GVF*rUtg>;875K)#EZ2rEmTrU;mq+g8}S~}mg0U+uuakLHF z@}9hgz+bOD`Z#(Xenr6f3(s_a+PAM$G}?a%abWm+=)-cZl&JRby1VRp=^)_gPUX8h z;>`KE!qv@f-x+exfGT0;PEq^i&DBCV8;cf;nZQSxVq9K8F+_P!Rj1gIwpo&6)ji_~nGNDvT8UrO4^DLy30b>9}h1DRN_cnlQs^rLH;6 zc!tUkmEa&Dl5NS8x5e>&@mFm>*YB*Q*S(M1)|LULFf43~d8(A`VJnbJgrXmgmMO^W-3cF*y^H0ul|HeY4 zl|uqs$yKDi5Pl3bLvnwP$IUc===*!S^SPWL7`+fT>~VBNxlR?0EybL3HRE@ze?^Fr zfwHBp} z5p-@(eoS@TYIscbT$<#9D>apBj9pk`KrII#4Qjpx=HJvBt0KbwdwUYdv2fwLds#{# zNj@b(8;mgae^5Czu;h#5{YZ*0IJdJMcD()?q9U?`r`OXr>#PdB{{yE1#`fYElmKL8 zCeQZQ88iSxkk*(QRdYzH^Y7e@I*TQH@qKh*&ohy;m~|vgO^+wf*QB{bP?;eKJPU+c z3p(X0x`icSq=3d(WDE=GhIo4qu_80r-~26wZ*Mioa7=S-m2ut|m&HN}?3*I`28a{EI9O~{GBJ(>U!>FMKc3U(b}A_d zR@WQ)2)^`FJqst9AMgz#p926Q3Dz)bw3rv~*a;x^_`($&1xr$FE^q7)Z|)DDVs)eS z+k~{!tn{x69cEj=r-(8nii}gk|FIh@I#8x!D5MZbLj9vK@F#Ug{=_WQ9WRu34*0R+ zzJGP}w-WJzcky{5VI^vx0*?RduGC1tEdY&}JcBYYFcA>VMEQ@8ty&1X_lcedN|uQ3 zgzS9*k}TwDd|H)&+NFkzJPQn41#4CbD~6$gf;HU!91$&1@8g<*;pALo2QNk?i32dW zLQ1>brTD~uC_g616buX&t1aByr4mEac41C{7SfiMmjBP4ERBEo%sJT@;I)rej+9z` zjKHt1+`_7J7)GVP6DE%b7~j!1ZpGYb96_>O0ASRU)>=;+sPM= z!e7PgPr!Gk8bxI{4AVi~-)A>_3ZD9jVlH!smTogvxBH6HWcAHK>bNgG?CI%q$lF}I z-c}3Wj$D0fOSi{nPwsy&44?F$Fdd-`h8`!WRW6ZTm&{rwRgH&9R?w(0$quMc*A^d+ zxfoO}esSovPFlfP5~J@lW9Ve>Fjm0DR4yyrTUbHzVLqp$GRuLn zAaAL>eXUd6c6PZ6&6;TZO)Ky_l8c`>?WfSUAB41NHJ(}|aXCX^{)|CytthqLZ)^*V zH6NX2ADyJt{28Bqd=ddFgjI^7FM1zbbO{V9Sw8hHjAPy@Ek7GlRdZc?7=!B4xG}~C z6lg>8Y-W9UAkQXgbk=_%&s~b9P!X5(ORazIutI60e40<6x&zN4l}Ku! zsS!R=te+a%9}?@^PJO)6u<^K$^E+DJUiY6U*($Z)E>lEz@Iw{V4Q&k7wr2Zv@RYJj z=|_&C-$skZ;Ts3Q1y3o{LMwuKyQGQ)JUBQrCMKPHQeJEt6}%K>3xeH?HJS`Xw8op% zkQ<@Kn=BR!IXc4*1iwTe0%L z*$S43AY3*X&Pp~F7}_ij?St*jqNFV@mf@6DM+fhiK!W()rkOwLr3lBC2h0-Vt90Z> zAb~t*z`|^!a?;mgqz%K*$?h{fQ9}kN_Qz|P_v|+#wV)Rkvn8wBM}_ptt{fMjZSinx z-uCndwuf1nIF?V|eGV<#W~2}tNsKi-8N8|;yOc)s_k`ptj-KfrcvfAN*O;~EDh zXyyqsn)k1Od59c}+$BYM%TQjpba=A|ewgQ(Fj)jRH!ZZmM7XS81vwAYqJtq;HLzlxE(B}0psg#B&p=YxXn`_qY<-F+gQk)mX(KXxX5)Fjim z=~FhL5X>m0x7wjTc4)>32DQr2>=w4LQL@~T8Is2H%-sQl?Gs+zJVf-s>d^RFLT@3! z);@E*5O&h zMXWWuVOyD+*kQPl|DAKX+MAIZw2Bvj_%&uMP0+ zS;>wh+v2alB|G5ls@d=*VtAm9UT z(L@7onIi>Y7cXBFgUp1cYt53s5vwsbbK{stFLJyb5ov>VWq$yC8{{jOf2Ij{{-=Na zLpVQxbBQ;k(GWiZgWDo+k~!iA$9H zOX~7a`@ah1UOm^Y6N(-11Q-$%;mjl74891FXJc>|#3aZwGWl(2-e z;GCthTW6{gh>Tf<@G=iZ1!F$~&yYnlw#KWNk&eSE9sMVgM#g*?2!i1h23iZiYu0{a zA1W-sM64d;Z7Os%6{-w;pFtNcoD~FoQeGk1O2TuqBZ|YfHzmrt_XVE|umAA_iJ&Z9 z5Sbcs*{J)X{|jGAG^mlC9mF>i5?upSMm5NBaAn@kFNf`EKMTxwkO=0Mlk%oo|g8A82EaA!} zAv|BX{*x#{6+9AH@uXIY3ESfLvk0A}*8-Jdd~{(yPZ)Oc$1~VY3oQPt{A1$G57Ji^ z*fZI?_RX7VaG8!Ch*2*8Ak8@MtD4!sAOC($Xw)>5qOT56y!8xQ8z6{bsb@*#M_d(*vxOcYv(=5!9(h^B>Tp1%P>Ju;)xuOwWJ}0;rGxpuj=8z7k(wVZcsJ9;*c40$4F0FAA`_Nue|# z{r%oGh+)d>79qOHXXUd2f;a5o(Ag@p$~pp*Sqz~lTCGXs2H zoG(;ScvqxdK<>y96DQfT5f){@I^n$FdDPQu#gp^)WgGe@N);A@=s60pFS8R_LqiHd zO-zzUz3I1rg{t$2>&6z7#}8S{`9ex8|7U3XVG5(0x6LaO7D7I*SdquHOwtDhv{L$~ zoXsqOYmT$`L%3AmM=srL!kHdB!rZcN-yw*ZENnl_xqrySjox^7&w=}VwolAMKeg|U zoQq3SaB{z`4T1lC8dQ{GG3$4bmLBU{el!?p+h!u;o@wl3vpRPEnAk7(gna4THL~VB zJ0nlO)^=cbAh7j(Na#MScfA)}Ue+4ioJOQUZZvdY8eVFI{z5(jzxh+(cfIkmJl;H_ zi(mkuhK9zI)41}_RYx3^3PkG&Z!#JRbT{jlovd~TosQqiue89R;@735w=K%9ftQm( z;V>E!J|C)u%1=2cOtBS^f6qInC7zyjq~r9FEU0{*I9?&GaN(%!t3$<&Lk^fG`$~Ry zDy@GTj>GRn%8TspEvq#dTfTU*p7eja)8U>v%Ne+2f%w=AVMp+36lnQy!h?|VOBf~g z*d58yn|{;|g-7)uNz&RK=&1lAUF~@ha%06E=RNE}Zxk#_v)f>V#=Mr{Zhbm$6Q^?& zcqHw2b6xRxa=zeXr6P;9PQ5hNy&&jB83f>{m%|U+xx1ubc5L=Mg6qb|OAQIJpGPfzpE;f6DXYg0s3`*L1J za&Q1)dGYhWlTrVkYh-#gsQtVCui}J`8w+O_m+Qp{n>w?7M_FtxYXd0KMAuK~WOVy| zbig>5w?ja#AIK-_N-RI(O33oL!t15uKJXS7HGq~pM2M#^WN)=hp7U9~>}&}DjZE@D z?QwUL4=$g2-v{BYl}<#iGumb>h4=?A$U4ddfcNbi@1sF9GPIj`@AhWFU)5&EyVh%9 zFN%#gpy&o@NZYhZ@aA>}=j~=SHIJ>H+ns|EZ&Y->(|BKhG~Q#WD+H*pT5O?^&SM+Twyf#iozB9oX(lii|LwU&cnP=?5X66G#Zowi|HRr&V$dX|aK^%OutUv+%MPizbw|(t43|!>lYKOj9`m7gzUw-J% z-1Z%J7cf5BTQNi-a?x7i<4q34k`|=)|>e#Nar1=YuR|s2=?|3;E!Bq+)<<^ zOD1QpId!%#_|O8z=XRSusQO+7sEhOjq4|q>MP5ZDy30Z(TG^)_>Cx#~urur0QLnJa zKzo7FpRS6Y(HUn_6s^QgT+<@CDdCANs`skGymp+%56EH7&4?!)$I|eDO-dGvqI#V~ z@HesBXl?DhJG&KYb#K4Kmb-TJy6(Mo*aNIM86}3roLqR$&h6TD2?d=9K^~ie4fIp= zPmlYP6>q%DwB6=T2X=X97lCMiJhCV>ZM;=Z%;Ggsl`c?ERjYXTVX)oTQm<6S;o0(N zoZXEPaZP3rJ|Pkfnr4A272#s%ES8JRDAQjhoZJ_f=0_VJ0-#VESF4-^s~|iCjS%w6!1N=hqmhRudeH`um8kyAsokt8AwGe zr8ySra$L%XHa&yO<3VoSfN|cNg&mzfUi~dKk^VXvUeyRe8FvvZ9DuxV$qb@SPMcf$ zqR@)JfDAV?YK=D`=UkgEZFgWanr8|jV)6#a{M-I@<*)bF4@=KzWwsgE8R6_{i)_k8YhJ57n4kq!Zur=v8T}UoYi62?;?J6O^s~!z)=tOSQ4ht1qv7XHCnZ-Kt zKKWy~gmfdOrFvs|(7j3W|CpMZRVDhGk>=ePov*yva6`wf1ZwYgf`V)f|KCB?d=vuHLAxTA=)mJ1%Y))7)) zw7c!9n?be(0`|>uq68hX;Xt-fow0^cEYT_|e9zy6>BEnxie3HT*y#?DiW$SLBe!&c z9vHkowLwOC@1crPuA&f}0d`PwI&auhy3vEVaYc1*hdc-b!@zuabH$_nOOK0QaF`Z9 z)5Ph`kB&&e!GOLd#SY__GCi*kB%|G#pGE-2i#$`$iy|7nt6?do-EoOd`P9ev;Gieh zgUjU>YicGcHq|IRhTcA*wUK=J@fq-!nVQ2L{y7~W7dCEy|KkU6y*n>DDP(o`j|iR9 z+XRF7+bvY^yFg;me8FkHI=A07C*yfm=$0_@*|HmvgKr&{3*|!}wn@j;8`q~hUdV{; z&`;REEM^mQ|NLlv47>HPlqhXi=lrhh%k9NS8Rw7dLdBwD`sqA-`uDQlYM(1bh8xm>1l7$kL0i#CeBcW zw3sR`^s5J(YL@qTO(PRKL^}l}bNYAUmNze~V_X?eA6}yYn4GJNK=*YmzutZB#Wz>9 zX0dM1CWNfPPj7GH@@AfN=0nA^RpOu)2GKf4XQuV8oY)H42Se%JmhiWXBm%y3%^n;+ zue>~(8q1X1V#zq)d{`saG`+^)p`6!xaKbe$My>rj+$ATpCaUt!M zjtB!oa}awu^;I$P_FbyRc=4v!h^{%Px0ddLqIgh)wtq-DXZHG-*|+h6x<~g7du|Rh zyURS`5}MA2?(CfkjxF_kpR}MrglHY2a{Dxz7z>HKyL!*%GR3Tgfrb=mG|FQe^`&yw zDqm3K>H)qq2{MlScX}cVDW741yKrtwe47sHGk!lpSUm}=kQTgpwZoy!|AjNEBDEOp+D)7h`JQ6++>3PsHbfFSCV7lqH_fYO9r_cnlMNF}BO0BzR1=soHGAw|@Xg=AAVKVyOU zjHXBm7>aV&L*~QiLZcp;4cuO|c^h`J&PtpDk@4Ih(q+A(&>j0C^A32Ln+ZvSNO7M`bLN0k0gDCFlu zcWO0}M-Ala>h_a<{t7A#YR^_vUA8U#}KeDS1Q_DQKV1nQkm-qoPu zA#!pms(oT8(rhTuer#xdzHoB%2{ooE;@69>7gfXM)HF1>qobpg3J@tgB;=t};9qp4 zTM})Jn(M;;IByHlu;7l;(3ArEh)DZgv6Lv{)(fps|0yy`_K+7Nn_?OooZveCrJKM~ zW%BKj?b*7P7Rm08=E#>(C=%>I-Tw)$I~PM@jG70%Xvxaa+a*``*2y>DK}DzhMl}@1 z&NHghh1gjl2@>U-J$4A||K*<9z#~{;^-vfkuJi}689~5*i5DPox12DtGfOEEu!l^B ziY!H`$6YFgBT;7y-JJZ?|~_W-V{uKPhKFDP0n8yeQqRns`6*^j4fX zJ|{*;!(?()ONF)hbnrpU;JU%qj^gF!>^^Tosgk2Z^qzx}T1wORnde&$7>th&tZk_K zehOJry&NKdn^Tl9v|%jdtM;jpJujGxOCHk&k5g|7hmbz8jd`SO&oYT9ib3-?n?wnd zu1TvREvzAmtjdJ8^<(0FLcTBG!i2gwMu$lyJQ8?)$v3R!VKmIb=ZIaMb$et~mnny*94 z{;E0qLH#j0g)v8s_Plu$G5Z$Bc9zWhBz&?p`DqTFlhS{K9_wR8YGi}e#qWi-5KXR+ ztU>HvuZSN-R?O<>HLS;)AStndwcB@NDyg-}=(i$@FH2ig{t6CqDuDq0jZ{pPs`hwg zr0dQHql3R_Zwgi3+(N`?21#!V(gySjbE=5T4aRtI+ehhK^f*UrwJ{+pSKPHr35_QG z^nQ|+NUk=K#I|1Q1F)r}xGDGpIF0*Q?Zg-NTF>8>HK*<5H(?iIh%akR*C-L(Z8Du% z>Epziwld!IH0TKLtFH*4z?6QBkrI{@-l3waVk!F||1X056H}f4e~YRA3t;l7b=2TW z6nppzhBYc=w9d@RC6T>&Le*XkymDZjv8Q7<)DDDk<6QO@Umu74)N)@u*{yZ+9l|~s zqqH)7E%#sE(RM!2$HRGUNbR}4Pfl>Z6D91_+!!0EZ4B@0tP4104ZnOb93P{DRV+{l z?g8$@zT2*E4%|M!Q_PL>3vk$%IpIg!e6L5sIaIH+dp5%kvs1q3y7&Fsz@(t6(t}A# z2R_fL*i(~rh2577aIJL* zvx)?T5>ZJ}a0gB6jo&(b1?1ZvcMm~B8yk*>dEXO0IyGoe8a@Ek$$Mh!j8Qp+1nsTb zZ(z1^Jh;!Acf&99ZFyn-G)M+4@jL#qorAGWL@?p9Ex7vC`Ald&eB94ZqSg+`R0cwf z78j(XVSDn4WYsD`6QPhuU)_yGb8WGQW^r0~R>#l8lyB(mnX1x0_!?m(40haq6jKG~ zu#^SJjA&OQcMNjO-eWKsUq5 zl}6L28IGbM86B~0g(odRyb9tYmC-=G+t1eVr?g@f%DX4VjqmGIZzP`+e;#0&e<9=8 zV1R=e$N-H{tQq!$dxPGJU*_?+&y<(B{e&ppcI5?s9JsXyi?ay0fh9qi+{7_lsivwZ z{-ALG;$Au8PQviP$Y{4YQZ({}kr)I3#{s*m#bVMUrIXf3{AtM168z`sk7YK%-FBJ^ z(BgUJ(Yy47CmNCPOWnlsH+kaM`~omUMEW(P;$OdZ=W6-n(1m}om{bjmnyVXF7QSdE zKzW>4oE%2$1E*wUhT8L5uikaTbNZl>4ez9yAY}wmfQTOg!*wWln65g;8+ z_ZkKUF?8cAuw;=z3|S0cBGjcv$|Z9Zr^i-1OtgzUz*{u6TFI=xf{!F08_k)tdW zibNvfuMpr08v`r*W%Z~pa(6ChEx{lAVd0)e( z{Oju)4SpApMo2nZvL=5=aXM1^cm*Ip&Rly5LYel*Y&O-I^~39sw_$NW#Y?_))6L&pqzs+ukTTic5Y#=oS038sXBkP~h#q0Cwg z^M^~Ov_axr&D76cuOsxe)xPi}u|N{?>deLQ`lc9YnMqw3^(7NX@ek>f>}&=kB_#(h z&RgK3_OVT$zy?yPTCq06$(4>!k{gXJ+AX_X@LNB>kSwg>KdPwCQZu8dzTS(-6U}8$ zn?a;9{K|#Lt~WkHLGbT^m}}Ux6tH6bwp0TZ_AM?1H3@j-DAmd9mROivcCBEUZomXZg7gywiTc zlRO20aHpmdfjsY1#4ptjd&TgTxG4H=<5q!7>xm&Q9@JM!|m;jN@d~1$FRp=Q)bbFAYH#94m_Uk`T%(C zo<<`9t1V$MoiOdKdm9=VR(%kfUuF)gFmYC%B_@cM^Ok((dw;Qbze~m*-=LY_pN{W) zy(#L{A60{K;}M1s#iSXpSJfJNZ!RI6cM*7CpIb~x)|TOb#Zu3FT8J^Yl{id*6)ycg_MS8qO@ zi22i5qYm%XV`NZGJeNl=5fHkY4`K6Xhg{eJvWTltJ%wxFJRwqi6LZseFNVp`|I_~s z(froqy#MWQz;-9;rD5N^9gESayWII-_^F47w~xa$|9+28f&nICzsRXLd}ps--$%yP z>D-81hAfl$$n9{hg1F5N#Ch+>;G%BA0Q;Sm^QViv!R6~&>aO)RmTs1~jdYEYGc)fK zG4UJ$n@j+>^`f}r`Rbo^Vk>^lKO>DWWJNO;!!ohH*IpAoMNADpWcY;~NE?38hAQTP z^Wo!n_1Z&lCU|a=EJf6gu?pt$6{#*-; zBirDLy-nCFIse-LwTK*$F!IT6pagmYb8Ff!(>Zj~fC0XsoWJWc~%-(5s88yNVuS+PwGZH$~P`P`!NW!2#Ho@4*y zamHvtgYCh8>N9Cd%ormj{SL| zCc(nJ2CcZBq2irLgh%uwyzo&|qJ@o#|FKqXw>!)JI74G_%h$8UCbxK95M{!#EBIfq zdwaSrgw0pa;;c)OroSanv&Q@{8|x22&=oor9D3lDN;)(m{=o2`lyxC^x6h+U6W*P+ zF9}$bUX|WAt}hD}1OF|cGh>ajClwlXsmn@+nklengVMCO_B zeggzHSz-QS`Ryh!RS^(xsnqGdU&-(l`5vYoSPxtYf@_4B<#PB!$H(`X(+6^lRuvZL z(8;wv28Wn3+kaeL{BMVPA^=S>Vt1hM+0n&GGAG}V7kH*TVyHavWfXf9dzev3gb&4! z4@-OH#ur)GlQg!s6&t+E&+<&ngczRim0zTqEHC;@hN7Nsw$*`5);=20)wOlG|8*7* zqguqFqmWB4>EG6)rr;*P#hF9M|IlqYWpqO_PsDLIHiM7}LkG{&(y0K%sNks+HRgx|l2Jf88@NU_PqOD|H$K{J(JwkxLV@t#e*^ z#ubCT8#Q(VDEUtb>IU3>yPqbmLYfKWhHj#hGhg*RFX_w@joWo=9?-O$C)4xHdb8?Z8 z>Z$@C!T6+0-rAJIBuzZ4f;GxQMCm?qb+-Ji^m`3W%n&o|o;P&PY;7#4=SIfhSaoO) zeWFq@&r0S*cZG5kVA?gt1E$p~yjJC!Wj-?=bKWOQK^ifllnza(Z?*P^ir>dbKl6_7 z$~(QXz9>}AnJwb6DH`n0>T3CTMcfgY>eMu{y`nkmg2jCd*jk*3xx4-%|3xi*xfCi* zo22hmboI1yL==k}b~O^d`v-Kgu6hxths zvIGWJjZG#CpTVR!wdnS_|NbC=w^Oom$)BS6cO23sk(s`lCmg8->VAmZPr0G&Pm12- zF!Rc49VpMD*x_fy(7Uz$6>3$lWSVNFQ-JbAVbi@VB2$39kYOXe12yY9AD$r#?Lf0Wy_ zUNOH$z0r;Hv0b!`c0mp9%$BqCGWm9dE`|=xCY71pv)*f~<nMAz z`FLSh(Us0&S};vmi8)QDCrj0L!9J96^A9%+j-ib!TDB5B2_e&$3FnisD}WAq1HMWq Kh}Vc32LC_vUU`lH literal 0 HcmV?d00001 diff --git a/hexagonal/etc/presentation.html b/hexagonal/etc/presentation.html new file mode 100644 index 000000000..46e26c550 --- /dev/null +++ b/hexagonal/etc/presentation.html @@ -0,0 +1,95 @@ + + + + Title + + + + + + + + + + diff --git a/presentation.html b/presentation.html deleted file mode 100644 index b19c85a81..000000000 --- a/presentation.html +++ /dev/null @@ -1,45 +0,0 @@ - - - - Title - - - - - - - - - From c850295aab8510779b60faa837697b9478f1eda0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilkka=20Sepp=C3=A4l=C3=A4?= Date: Sun, 13 Nov 2016 11:23:22 +0200 Subject: [PATCH 18/37] Add new diagram --- hexagonal/etc/hexagon.png | Bin 51788 -> 0 bytes hexagonal/etc/ports_and_adapters.png | Bin 0 -> 34860 bytes hexagonal/etc/ports_and_adapters.xml | 1 + hexagonal/etc/presentation.html | 24 ++++++++++++++++-------- 4 files changed, 17 insertions(+), 8 deletions(-) delete mode 100644 hexagonal/etc/hexagon.png create mode 100644 hexagonal/etc/ports_and_adapters.png create mode 100644 hexagonal/etc/ports_and_adapters.xml diff --git a/hexagonal/etc/hexagon.png b/hexagonal/etc/hexagon.png deleted file mode 100644 index e2d14e91dd692d888f85998087c881c559191900..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 51788 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 diff --git a/hexagonal/etc/ports_and_adapters.png b/hexagonal/etc/ports_and_adapters.png new file mode 100644 index 0000000000000000000000000000000000000000..d285045dea68721c586bbfae5d303265f738eea0 GIT binary patch literal 34860 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 literal 0 HcmV?d00001 diff --git a/hexagonal/etc/ports_and_adapters.xml b/hexagonal/etc/ports_and_adapters.xml new file mode 100644 index 000000000..0e64414b8 --- /dev/null +++ b/hexagonal/etc/ports_and_adapters.xml @@ -0,0 +1 @@ +7Zpdk6I4FIZ/jbdbJAHEyx7nY/diqrqqd2tnLiOJSDUSK6ZHe3/9BkmUfFiDDqBM2TcNBwLxOe85nBOYoPl6/4XjzeorI7SYwIDsJ+jjBEKA4kj+qyzvtWUag9qQ8Zyok06Gl/w/qoyBsr7lhG6NEwVjhcg3pjFlZUlTYdgw52xnnrZkhXnXDc6oY3hJceFa/82JWNXWJApO9j9pnq30nUGgjixw+ppx9laq+00gWh7+6sNrrK+lzt+uMGG7hgl9mqA5Z0zUW+v9nBYVW42tHvf5zNHjvDktRZsBqB7wAxdvVM/4MC/xrlnIKW6qzRXd44yVE/RhQ3m+poLyk/X5ZPqwW+WCvmxwWo3aSYFI20qsC7kH5Ka6I+WC7s/OGhxZSI1RJi/N3+UpagBMFD4lL6D3dydnIa2lVcNRMFZGrASSHa99giQ3FCc/MzhKZmgaGcyOKBrMAPQwO2r7V5iFDrM549ThJgfJEKc/B7LMi2LOCsYP46oYg2kq7VvB2SttHCHxIo7ibhCGATARJshBqDNfk2AXoot+Lrpr4RFMk6UXXpwmdLHsCF5s6W/qwkMe+aEO4MW/GzwEPQmvJ3jT0cMDMxNeGA0GLxk7PDQ1H7VDKm82fnh2zoODwdPlz3jphdCUHoyGkx5oUeRdTS+iCQl99BK4QHFHxUoUWfQ89V5v9Fq0FXdOz9ZeMCC9Nk/ckjxVfa7cK1lJTWJ0n4tvje3vcjuotks5k2/Nne/6rJJ8zqsJHQ7Vd6PE6ZEtenJG7I2n1KhQBeYZFU0duJAbECMPRG3jtMAi/2HOwkdW3eGZ5XJ+Z7vECFjOqWevRjWbZOtCCJkXCu2Cvv7NzoUOjj7+7Ha+b1MwXOz7P6IefQwfPr7Qx33WNYNkR5s60nXuANkR9lnXDEIPWc8WNBvu2aJn+8v5JfDkF/V0Ac2nS3e5J/Hkntkj91yWe7S7O/U/OO/9/nzfWC5/+L6d70dfldsrOSEcbiXHs4R9ZeTUGdEXO41E2mX0TD3Rc1+Vue2gq6Mn6S963BX4Z8bF1hGBlLcwPW/GhFJGM4CUCRd5VsrdVDrz8FaoCpY8xcWTOrDOCSnOBWcH8YVmoYHzGDgNWYS+12pdxJe7SP/PVlKQZ1Q0ltVvtVEfXrRSojD3/w4NALvudd9hAN97x7ALQO6ywN90WwUDzqiS903h2CvFiZucZ32xcdvmv6RqMi6zFCtvjuZY4et851lN6g2N221+xAIv8Pb28RQHJhcwG04yOrU1uHxl6au0kLvBYz3dYOTi6S3doPF2irpKNAqe2I96mIIHWJ6Mr20XgF059dcuoD5axWEEoOsRQwDThwAuFECbfvE+Ox5dlxkCSB4CuFAAXbW8vpcRvldRHT4CfAK46WrhKAXQ5quzOxUAdAWAbrpkOEoBuE35E8Eb2Y//XuseVh+CPP1ZR+secvf0dXftkdMn9OjT/w== \ No newline at end of file diff --git a/hexagonal/etc/presentation.html b/hexagonal/etc/presentation.html index 46e26c550..74361ad27 100644 --- a/hexagonal/etc/presentation.html +++ b/hexagonal/etc/presentation.html @@ -60,29 +60,37 @@ Use Hexagonal Architecture pattern --- -# Diagram +# Concepts -.center[![Alt text](hexagon.png)] +* Ports are interfaces +* The ports that drive the application are called primary ports +* The ports that are driven by the application are called secondary ports --- # Concepts -* Ports are interfaces -* Adapters are implementations -* Driver ports vs driven ports +* Adapters are interface implementations +* Typically different adapters for testing and production are provided + +--- + +# Diagram + +.center[![Alt text](ports_and_adapters.png)] --- # Real world examples -* [Apache Isis](https://isis.apache.org/) +* [Apache Isis](https://isis.apache.org/) builds generic UI and REST API directly from the underlying domain objects --- -# Implementation example +# Tutorials -* http://java-design-patterns.com/patterns/hexagonal/ +* Blog http://java-design-patterns.com/blog/build-maintainable-systems-with-hexagonal-architecture/ +* Source code http://java-design-patterns.com/patterns/hexagonal/