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 000000000000..9188c8b4128d --- /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 000000000000..ef6cee5eff45 --- /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 000000000000..91bdff8e24dc --- /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 000000000000..544b0bacba8c --- /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 000000000000..3e18fbf3a902 --- /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 000000000000..2bebc093991f --- /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 000000000000..624a29132531 --- /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 000000000000..feba71a1b1d9 --- /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 000000000000..9b26450f065f --- /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 d7758b6f745e..35cdf7625d03 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.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 @@ */ 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 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 aae396f1dc26..abc75a951fab 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 @@ */ 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 static void main(String[] args) { 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 a591818fe7db..265f127c4f8c 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 @@ */ public class BattleFishingBoat implements BattleShip { + private static final Logger LOGGER = LoggerFactory.getLogger(BattleFishingBoat.class); + private FishingBoat boat; public BattleFishingBoat() { @@ -41,7 +46,7 @@ public BattleFishingBoat() { @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 3074370385fd..a10e9096798f 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 @@ */ 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 1c5c1527c459..e86a84563ccf 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.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 @@ @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 String getProductTitle() { 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 14d0a32c421c..c736462e6c57 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.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 @@ @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 int getProductInventories() { 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 0a56dc16649a..ee33ea1db599 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 @@ */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point */ @@ -120,6 +125,6 @@ private static AsyncCallback callback(String name) { } 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 2523b35579cf..28bcf13fa69c 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 @@ */ 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 0cc31b4719df..a57d75abc2f7 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 @@ */ 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 91cad9cc2761..e9d65bc8c03d 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 @@ */ 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 d421de7b6012..0790e305813d 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 @@ */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point * @@ -60,18 +64,18 @@ public static void main(String[] args) { 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 7296f63b4e46..9c890b108fc0 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 @@ */ 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 5b71ce57d0ff..5b5fa6247519 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 @@ */ 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 8e5a84085ff9..377a4bfa68e5 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 @@ */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + + /** * Program entry point * @@ -80,13 +86,13 @@ public static void main(String[] args) { * 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 void useReadAndWriteThroughStrategy() { * 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 void useReadThroughAndWriteAroundStrategy() { * 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 void useReadThroughAndWriteBehindStrategy() { 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 5903f82193e9..3b3226553a3f 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 @@ */ public class CacheStore { + private static final Logger LOGGER = LoggerFactory.getLogger(CacheStore.class); + static LruCache cache; private CacheStore() { @@ -52,10 +57,10 @@ public static void initCapacity(int capacity) { */ 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 static void writeAround(UserAccount userAccount) { */ 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 static UserAccount readThroughWithWriteBackPolicy(String userId) { */ 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 static void clearCache() { * 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 5c5549afd9d7..614b42ac4839 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 @@ */ public class LruCache { + private static final Logger LOGGER = LoggerFactory.getLogger(LruCache.class); + class Node { String userId; UserAccount userAccount; @@ -117,7 +122,7 @@ public void set(String userId, UserAccount userAccount) { } 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 boolean contains(String userId) { * 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 bc1b2890e2f4..ece6f8cceb84 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 @@ */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point */ @@ -39,7 +44,7 @@ public static void main(String[] args) { 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 78ca63e0b423..33a49a461d48 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 @@ */ 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 2a738560791a..2c56bea070a2 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 @@ */ 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 78d68e5dcbab..2fd774f99565 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 @@ */ 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 void handleRequest(Request req) { } 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 2e49ab663a6a..3bfbde9260a0 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 @@ */ public abstract class Target { + private static final Logger LOGGER = LoggerFactory.getLogger(Target.class); + private Size size; private Visibility visibility; @@ -56,8 +61,6 @@ public void setVisibility(Visibility visibility) { * 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 bd0ef85d49b6..abfc499677b9 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 @@ */ 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 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 void undoLastSpell() { 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 void redoLastSpell() { 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 cfe37876faa2..07d4f0b68063 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 @@ */ 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 d6a4005d24b4..c8a6ccfce141 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 @@ */ 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 Letter(char c) { @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 eea1d4b1d29a..ca8698f4fafd 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 @@ */ public class Sentence extends LetterComposite { + private static final Logger LOGGER = LoggerFactory.getLogger(Sentence.class); + /** * Constructor */ @@ -47,6 +52,6 @@ protected void printThisBefore() { @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 819f166dc838..4e5cfb31d92f 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 @@ */ public class Word extends LetterComposite { + private static final Logger LOGGER = LoggerFactory.getLogger(Word.class); + /** * Constructor */ @@ -42,7 +47,7 @@ public Word(List letters) { @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 bdc574fbce2f..2f0b1aa4ec5f 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 @@ */ 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 3b4b86276941..9a4a136adddf 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 @@ */ 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 SmartHostile(Hostile decorated) { @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 int getAttackPower() { @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 628adda4bc7e..0fff3b812c7b 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 @@ */ 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 int getAttackPower() { @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 5e3966d851ab..1664e86e44ba 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 @@ */ 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 d37fbf613fd8..f67f9defa1ee 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 @@ */ 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 f81debf62e31..fdd89081baf7 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 @@ */ 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 74a564ab58d1..c003007e0d2a 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 @@ */ 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 98309e181498..9ce9690377a4 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 @@ */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point * @@ -58,7 +63,7 @@ public static void main(String[] args) { 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 176203a44006..09a14d3203a7 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 @@ */ 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 boolean addItem(Item item) { 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 40a0485a5e85..601b0fcc07a9 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 @@ */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point * @@ -58,8 +63,8 @@ public static void main(String[] args) { 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 static void main(String[] args) { 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 cc68a85ec7b7..fcda7f3125ea 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 @@ */ 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 void collision(GameObject 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 e7a55d0eeb84..c1f75005999e 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 @@ */ 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 void collision(GameObject 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 fdda59693b9b..1a0ad3345149 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 @@ */ 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 3ef4e8255524..ded6b76ce4f7 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 @@ 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 0311d5781813..a0bf28c5753d 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 @@ 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 bdc839f5753a..61e64a15399e 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 @@ */ 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 54fa821f4747..2eb464edf896 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 @@ */ 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 f27054c5333a..48ec1db48a08 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 @@ */ 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 @@ private void action(Action action) { 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 74d8b89cc5e6..54fcca73abaf 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 @@ */ 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 f27bee170a8c..c091cb1eb564 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 @@ * 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 static void main(String[] args) { 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 cd7a6e6e7045..a49d8bd32069 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 @@ */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + private final Blacksmith blacksmith; /** @@ -70,8 +75,8 @@ public static void main(String[] args) { 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 debe99580828..c2bccb851e84 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.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 @@ */ 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 static void main(String[] args) { 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 static void main(String[] args) { 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 static void main(String[] args) { 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 1be2b1e701b2..30678359dbcd 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 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 @@ */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point */ @@ -74,9 +78,7 @@ public static void main(String[] args) { .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 static void main(String[] args) { .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 @@ private static void prettyPrint(String delimiter, String prefix, 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 cb351bfaefb7..dd5405a02c4a 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 @@ 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 @@ */ 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 void storeChanged(Store store) { @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 6cd9005dcb24..81d1e49d5a2b 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.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 @@ */ 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 void storeChanged(Store store) { 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 507de7a6a463..5cde4c248d7b 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 @@ */ public class AlchemistShop { + private static final Logger LOGGER = LoggerFactory.getLogger(AlchemistShop.class); + private List topShelf; private List bottomShelf; @@ -88,13 +93,13 @@ public final List getBottomShelf() { */ 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 464675a61aec..e25107bdb055 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 @@ */ 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 b05b4af11cba..83a5ca6d1759 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 @@ */ 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 5aeb5d3a4049..1e3087c4b703 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 @@ */ 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 a9d13088e9a3..83c32b192008 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 @@ */ 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 2c21e7df1a43..81f5a9d46735 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 @@ */ 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 a7cf8ca273e1..ddd27d0e83f2 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 90e4c7896c58..f3b7e308ee08 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 @@ */ 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 cbfd4bd2e221..00dbc582bac7 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 @@ */ 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 17839bb32bc0..3186b292a7e2 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 @@ */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point * @@ -128,7 +133,7 @@ public void onPreCall() { @Override public void onPostCall(Long result) { // Handle the result of computation - System.out.println(result); + LOGGER.info(result.toString()); } @Override @@ -141,7 +146,7 @@ private static long ap(long i) { 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 ea2f33699416..e83521c22a27 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.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 @@ */ public class ConsoleAdministration { + private static final Logger LOGGER = LoggerFactory.getLogger(ConsoleAdministration.class); + /** * Program entry point */ @@ -53,29 +57,29 @@ public static void main(String[] args) { 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 4150dd4011f8..c63759e8ee03 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 cc13d389d248..00d61b668a3c 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 @@ 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.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 @@ */ public class ConsoleLottery { + private static final Logger LOGGER = LoggerFactory.getLogger(ConsoleLottery.class); /** * Program entry point @@ -59,25 +63,25 @@ public static void main(String[] args) { 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 static void main(String[] args) { 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 static void main(String[] args) { 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 708f06e6f474..1cf732b0d522 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 @@ */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * * Program entry point. @@ -56,21 +61,21 @@ public static void main(String[] args) { 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 8da0a7433cea..44bc1dacd24a 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 @@ */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point * @@ -44,28 +49,28 @@ public static void main(String[] args) { 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 bc489e16e422..bb636af7ad64 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 @@ */ 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 CakeViewImpl(CakeBakingService cakeBakingService) { } 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 3c94b178c6de..67a554873388 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 @@ 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 7a658a8c6914..b33520243fc2 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 @@ * */ public class App { + + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point * @@ -43,16 +49,16 @@ public static void main(String[] args) { // 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 57e8e263e32e..ad4eb3de29fe 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 @@ */ 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 75c65d1b9833..0e3d2c718d9d 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 @@ */ 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 c6e0fcfd9e77..35dd2e4f08ae 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 @@ */ 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 e4ce394cc668..95e8856c9063 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 @@ */ 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 7d3ca3dbf441..9d9b9cd2d68c 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 @@ */ 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 e1ee349b1cc7..c346b7941451 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 @@ */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point */ @@ -52,22 +57,22 @@ public static void main(String[] args) { 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 dab04bd37c3e..2e132213df59 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 @@ 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 @@ */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point */ @@ -66,7 +70,7 @@ public void configure() throws Exception { }); 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 dd4361487c0d..61815aab8f82 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 @@ */ 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 7b28fdcf84a5..e707156d6c68 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 @@ */ 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 bf700a57a302..86a4985cccc0 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 @@ * */ 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 int getPort() { } 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 1ffd57a34bd9..55cc8a2aa045 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 @@ */ 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 8a2aca41efd0..35c9d2a557f6 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 @@ */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point. * @@ -88,7 +93,7 @@ private static void closeResource(Resource resource) { } 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 58cbfe8938b0..a7a010c3c498 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 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 void loggedMuteShouldLogExceptionTraceBeforeSwallowingIt() throws IOExcep 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 d2225876c89a..d31ec3fa8d26 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 void run() { 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 ca165acc7864..000000000000 --- 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 b55249569eca..000000000000 --- 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 62fd8ea5e213..000000000000 --- 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 46787ac96993..c2fd66849c9f 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 @@ */ 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 String getName() { @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 66b3e3f9033b..b49dd70d7ea9 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 @@ */ 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 dcced00d4644..d6a8e0df6b11 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 @@ 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 @@ */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point * @@ -58,7 +62,7 @@ public static void main(String[] args) { 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 ed9636bd6530..74ffee713136 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 @@ */ 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 ce9c09944c04..65ddc840f289 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 @@ */ 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 f6aad3881878..c89ffd366495 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 @@ */ public class Weather { + private static final Logger LOGGER = LoggerFactory.getLogger(Weather.class); + private WeatherType currentWeather; private List observers; @@ -55,7 +60,7 @@ public void removeObserver(WeatherObserver obs) { 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 da84b9aab1bf..f70a1a62e63f 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 @@ * */ 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 9f41aa6cc944..3171f4e7c0ce 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 @@ */ 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 137000760b73..631da479e9a9 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 @@ */ public class GWeather extends Observable { + private static final Logger LOGGER = LoggerFactory.getLogger(GWeather.class); + private WeatherType currentWeather; public GWeather() { @@ -43,7 +47,7 @@ public GWeather() { 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 c811225e1aef..6a586c52d0e9 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 void consume() { 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 15dcad40ee99..af07ed679995 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 @@ 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 @@ */ 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 void send(String body) { queue.put(msg); } catch (InterruptedException e) { // allow thread to exit - System.err.println(e); + LOGGER.error("Exception caught.", e); } } @@ -75,7 +79,7 @@ public void stop() { 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 144b8efffc4c..d4d7ff581d85 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 b9d2ad09c26f..73bfb948f8ee 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 @@ */ 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 ImmutableStew(int numPotatoes, int numCarrots, int numMeat, int numPepper * 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 9c90330187f1..665edf418621 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 @@ */ 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 Stew(int numPotatoes, int numCarrots, int numMeat, int numPeppers) { * 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 42f6dfa79f59..dca2457c4c04 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 @@ */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point * @@ -72,7 +77,7 @@ public static void main(String[] args) { 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 f1fa920f31a7..880b76ba501e 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 Consumer(String name, ItemQueue queue) { 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 672c20bfa969..7e1f174ef796 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 @@ */ 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 @@ private void calculateLowestFrequencyChar() { 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 @@ private void calculateLineCount() { 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 d451600a359f..769a6fcd1825 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 @@ 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 static Integer countLines(String fileLocation) { * @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 static String downloadFile(String urlString) throws MalformedURLException 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 e3f7cc92b832..576bada184ce 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 @@ */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point * @@ -67,16 +71,16 @@ public static void main(String[] args) { /* 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 cb04ec5f2062..bb98194cea2a 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 @@ */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point * @@ -51,16 +56,16 @@ public static void main(String[] args) { 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 573d3837417e..d5daab305289 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 @@ */ 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 985184afe1a9..1048724d48bb 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 @@ */ 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 void enter(Wizard wizard) { 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 c4e423b045b4..ff66e4e58fe6 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.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 @@ */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point */ @@ -61,7 +65,7 @@ public void configure() throws Exception { }); 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 29c2f83fad84..77e4e1f4ff64 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 @@ * 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 @@ private void sendLogRequests(PrintWriter writer, InputStream inputStream) throws 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 void run() { 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 ab2bcfb1a0e2..e1095d34e691 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 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 @@ */ 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 @@ private static void sendReply(AbstractNioChannel channel, SelectionKey key) { 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 4e493163f477..52d2d68b01f4 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 @@ */ public class NioDatagramChannel extends AbstractNioChannel { + private static final Logger LOGGER = LoggerFactory.getLogger(NioDatagramChannel.class); + private final int port; /** @@ -99,7 +104,7 @@ public DatagramChannel getJavaChannel() { 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 3d5ebf5a07f8..0facf19357dc 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 @@ */ 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 NioReactor(Dispatcher dispatcher) throws IOException { 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 c7d67fd13949..d1c6bb62acfd 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 @@ */ public class NioServerSocketChannel extends AbstractNioChannel { + private static final Logger LOGGER = LoggerFactory.getLogger(NioServerSocketChannel.class); + private final int port; /** @@ -96,7 +101,7 @@ public void bind() throws IOException { ((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 fd5d28ed52c0..90f7d5e59381 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 @@ */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point * @@ -71,7 +76,7 @@ public static void main(String[] args) { 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 2b837b341925..644772bf1680 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 @@ */ 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 void run() { * */ 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 fc3c3bb88276..ce946f74f5d9 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 @@ */ 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 void run() { * 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 a2496a3c0c98..dc8feb04f939 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 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 void testReadAndWrite() throws Exception { 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 void testWriteAndRead() throws Exception { 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 7d51e977cc87..a51120bf8dd6 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 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 void testRead() throws Exception { 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 765c491ff044..729b5eff3fff 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 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 void testWrite() throws Exception { 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 2807ae7caae1..ab61852d2419 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 @@ import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; /** @@ -43,6 +45,8 @@ */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point * @@ -67,12 +71,12 @@ public static void main(String[] args) { 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 static void main(String[] args) { 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 3e7093358971..09f6753bb663 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 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 @@ @EnableJpaRepositories public class AppConfig { + private static final Logger LOGGER = LoggerFactory.getLogger(AppConfig.class); + /** * Creation of H2 db * @@ -117,12 +121,12 @@ public static void main(String[] args) { 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 static void main(String[] args) { 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 413fb0eabe80..bb722a36dd0c 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 @@ */ 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 3a1a35f2d606..ac8512d15869 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 @@ */ 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 e7b7ebab6965..f020b5fa31d5 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 @@ */ 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 0a4713438db5..e0546edbee61 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 void run() { 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 92829441d931..aeb3798467d6 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 @@ */ 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 static void scenario(Servant servant, int compliment) { // 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 8282d800cb13..bf15c5885adf 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.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 @@ */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point * @@ -180,27 +184,27 @@ public static void initData() { 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 b30b97b65ecc..eead0e1979ec 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 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 static synchronized SessionFactory getSessionFactory() { .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 8063fc81895f..134eb6d8945a 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 @@ */ 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 7e2169fcb9a6..89b2a66388a5 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 @@ */ public class ServiceCache { + private static final Logger LOGGER = LoggerFactory.getLogger(ServiceCache.class); + private final Map serviceCache; public ServiceCache() { @@ -52,8 +57,8 @@ public Service getService(String serviceName) { 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 543fb848081c..328926ce2f1b 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 @@ */ 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 int getId() { @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 4b505085ae6e..31dcd18031a3 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 @@ */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point. * @@ -70,35 +75,35 @@ public static void main(String[] args) { // 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 7cbd384709c7..7e85d271352d 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.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 @@ * */ public class App { + + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); /** * Program entry point @@ -62,22 +66,22 @@ public static void main(String[] args) { 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 c58f85ae156f..3ebbed1424ff 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 @@ */ 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 AngryState(Mammoth mammoth) { @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 23f4e893ce20..870298632b8c 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 @@ */ 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 PeacefulState(Mammoth mammoth) { @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 aeb759ba8eda..fe5c5a8cd814 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 @@ */ public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * Program entry point * @@ -67,18 +72,18 @@ public static void main(String[] args) { 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 be8826fe31fa..28485701c7c4 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 @@ */ 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 d17ff9041928..d67f8b559878 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 @@ */ 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 7cd7311670e5..ea88fdc8b3d1 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 @@ */ 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 6309ed31b5f1..3264799bf084 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 @@ */ 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 7a78576a1263..49cbbd7dc727 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 @@ */ 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 @@ protected String pickTarget() { @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 c8c584cdd5c5..85896d922ef8 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 @@ */ 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 4fdb5d758486..c7855fe4e919 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 @@ */ 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 @@ protected String pickTarget() { @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 16fbca35aaa7..20d773c82a5c 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 @@ * */ 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 static void main(String[] args) { 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 1354cab41473..1740b289e22a 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 @@ */ 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 Worker(final Task task) { @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 066b6e7373ef..14ebcab40f88 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 @@ */ 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 0188b57318c2..0c47bc91c2c7 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 @@ */ 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 void setTwin(BallThread twin) { @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 194d85b06df1..6dea979bec0c 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 @@ 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 void run() { 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 08d7dcce710e..da2cef7a2635 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 1e943d054ce6..238258441bb3 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 @@ * 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 static void main(String[] args) { 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 6e54c7861bb9..466c12f51d72 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 @@ */ 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 void visitSergeant(Sergeant sergeant) { @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 4fca0a5bddf0..aa06cb2adf02 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 @@ */ 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 void visitSoldier(Soldier soldier) { @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 fff24f699083..0907a25310a7 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 @@ */ 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 feba71a1b1d9..ebe536d24bcc 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 void unsuccessfulKingFlirt() { @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 144b8efffc4c..7aec509d41a3 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 598386753977..fc68a3830470 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 fc68a3830470..76e108a57c50 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 000000000000..d3d6b8746172 --- /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 000000000000..bc43e3e094fc --- /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 000000000000..9dab6a00cc5a --- /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 000000000000..879492248545 --- /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 000000000000..b591c17e1665 --- /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 000000000000..46c12ef381d5 --- /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 000000000000..797e7f26a179 --- /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 538058a81988..a739926073b0 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 | 191 +++++++++++++++--- 7 files changed, 397 insertions(+), 66 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 d3d6b8746172..24bd3f54358c 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 000000000000..d2519b856ae5 --- /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 9dab6a00cc5a..0ca43d5c21f8 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 @@ */ 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 000000000000..097f85b0ec20 --- /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 879492248545..d1df062deb15 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 @@ * 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 FileLoggerModule singleton = null; - private static FilePrinterModule 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 void unprepare() { this.error.close(); } - logger.debug("MainModule::unprepare();"); + logger.debug("FileLoggerModule::unprepare();"); } /** @@ -87,7 +100,7 @@ public final void unprepare() { * @param value */ public final void printString(final String value) { - this.output.print(value); + this.output.println(value); } /** @@ -95,6 +108,6 @@ public final void printString(final String value) { * @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 797e7f26a179..cf34358506d6 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.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,117 @@ 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 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 */ - filePrinterModule.unprepare(); + fileLoggerModule.unprepare(); } /** @@ -79,20 +175,20 @@ public void testPositiveMessage() throws IOException { * @throws IOException */ @Test - public void testNegativeMessage() throws IOException { + public void negativeTestFileMessage() 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(); /* Test if nothing is printed in file */ assertEquals(readFirstLine(OUTPUT_FILE), null); /* Unprepare to cleanup the modules */ - filePrinterModule.unprepare(); + fileLoggerModule.unprepare(); } /** @@ -101,23 +197,23 @@ public void testNegativeMessage() throws IOException { * @throws FileNotFoundException */ @Test - public void testPositiveErrorMessage() throws FileNotFoundException { + public void positiveTestFileErrorMessage() throws FileNotFoundException { /* 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 'Error' in file */ - filePrinterModule.printErrorString(ERROR); + fileLoggerModule.printErrorString(ERROR); /* Test if 'Message' is printed in file */ assertEquals(readFirstLine(ERROR_FILE), ERROR); /* Unprepare to cleanup the modules */ - filePrinterModule.unprepare(); + fileLoggerModule.unprepare(); } /** @@ -126,20 +222,58 @@ public void testPositiveErrorMessage() throws FileNotFoundException { * @throws FileNotFoundException */ @Test - public void testNegativeErrorMessage() throws FileNotFoundException { + public void negativeTestFileErrorMessage() throws FileNotFoundException { /* 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(); /* 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 @@ private static final String readFirstLine(final String file) { /* 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 0ca43d5c21f8..a3ecdb31cb2b 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 @@ 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 46c12ef381d5..eb348d75801a 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 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 eb348d75801a..0f20b4959b3a 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 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 000000000000..d78f12da82e2 --- /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 a3ecdb31cb2b..cfa50975f369 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 @@ 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 097f85b0ec20..8f5941951267 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 d1df062deb15..fae66191b60d 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 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 0f20b4959b3a..21b32407da94 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 @@ */ 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 000000000000..ecefb307a071 --- /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 cf34358506d6..000000000000 --- 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 c8a6ccfce141..088cdd44c6f4 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 Letter(char c) { @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 ca8698f4fafd..bccf6c751c72 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 @@ protected void printThisBefore() { @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 4e5cfb31d92f..0174dc88ab39 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 Word(List letters) { @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 | 69 ++++++------ .../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, 1446 insertions(+), 1601 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 84b0f6d20132..652c1fcdc6a0 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 @@ */ 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 void testTrollActions() throws Exception { 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 6a19c9a1af78..c1f32a8e05a3 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; + + @Before + public void setUp() { + appender = new InMemoryAppender(); + } - @Rule - public final SystemOutRule systemOutRule = new SystemOutRule().enableLog(); + @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 void testHpPrinter() throws Exception { 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 void testEpsonPrinter() throws Exception { 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 d1f5e574c5d4..a0578626fba3 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 void testSmokeEveryThing() throws Exception { 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 1d3d679dfde6..81177367889b 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 @@ 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 void testSmokeEveryThingThroughConstructor() throws Exception { 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 @@ protected void configure() { 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 e5a856e8d612..cda3eac471f0 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 57272c511e92..000000000000 --- 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 000000000000..b4c60b8aaf76 --- /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 485c9573eac2..9f5f608b02cb 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 @@ */ 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); - - /** - * Keep the original std-out so it can be restored after the test - */ - private final PrintStream stdOutOrig = System.out; + private InMemoryAppender appender; - /** - * 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 void testAddItem() throws Exception { 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); + 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(); + } } -} \ No newline at end of file +} 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 dbc8fc55e2ce..6576d6d2f137 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 @@ */ 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 @@ void testCollision(final GameObject other, final boolean otherDamaged, final boo tested.collision(other); - verify(getStdOutMock(), times(1)).println(description); - verifyNoMoreInteractions(getStdOutMock()); - testOnFire(other, tested, otherOnFire); testDamaged(other, tested, otherDamaged); @@ -129,8 +81,8 @@ private void testOnFire(final GameObject target, final GameObject other, final b 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 @@ private void testDamaged(final GameObject target, final GameObject other, final 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 3e0028ac4382..e06d10b6a168 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 @@ */ 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); - - /** - * Keep the original std-out so it can be restored after the test - */ - private final PrintStream stdOutOrig = System.out; + private InMemoryAppender appender; - /** - * 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 void tearDown() { 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 4a3b218e2452..7718f7d41ad4 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 @@ */ 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); - - /** - * Keep the original std-out so it can be restored after the test - */ - private final PrintStream stdOutOrig = System.out; + private InMemoryAppender appender; - /** - * 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 void testFullWorkDay() { 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 c4d9ae62553d..0b5c9f593064 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 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 @@ * @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 CommandTest(final String request, final String displayMessage) { @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 0822ffcd0b64..46a26e6fbcae 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 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 @@ * @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 FrontControllerTest(final Command command, final String displayMessage) { @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 bc32a1b3ca7d..000000000000 --- 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 cdabd66ef469..bca070305533 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 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 @@ * @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 ViewTest(final View view, final String displayMessage) { @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 000000000000..1747deac52ca --- /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 00d61b668a3c..077b0f235bb4 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 @@ 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 a69aa23bbbc5..3a9214ae1414 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 @@ * * @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 void testRender() { 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 67a554873388..000000000000 --- 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 0bf43f9cd6c9..e5f7e2719db0 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 static Collection[]> data() { ); } - /** - * 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 PartyMemberTest(final Supplier memberSupplier) { 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 void testPartyAction() { 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 void testAct() { 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 void testToString() throws Exception { 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 89d503d4ec1d..9ea0ae96ee10 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 @@ */ 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); - - /** - * Keep the original std-out so it can be restored after the test - */ - private final PrintStream stdOutOrig = System.out; + private InMemoryAppender appender; - /** - * 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 void testDisplayGiant() { 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 1375b8949d4a..98168fc0aa7f 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 void testFields() { @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 0c0122132335..000000000000 --- 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 6c77cd236902..2712b03563c7 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 void testTreeSize() { 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 void testGetRight() throws Exception { 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 afd870ae4962..000000000000 --- 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 a06c199524f9..1ccf4bf12e46 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 7a38e7137f0b..9d53b2e235d2 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 @@ * * @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 void testAddRemoveObserver() { 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 void testTimePasses() { 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 void testTimePasses() { 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 758dbca8cec3..61d619a602a1 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 void testAddRemoveObserver() { 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 void testTimePasses() { 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 void testTimePasses() { 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 33d8daaf5719..d01d30992d4c 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 000000000000..4e6e49768c79 --- /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 01a5dfaa6659..983287c3cd25 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 void testConsume() throws Exception { 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 @@ private static Message createMessage(final String sender, final String message) 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 f1b3c4840801..000000000000 --- 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 58867d303f49..431375ef7d4f 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 void testDrink() { 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 f90551020a60..000000000000 --- 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 a894e4ae0490..f2e3c5fadeb1 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 void testMix() { 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 000000000000..4b2def101c31 --- /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 2ca547a0ba33..dd725df75952 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 void testConsume() throws Exception { 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 1e1c41f75107..000000000000 --- 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 48831444a1ae..000000000000 --- 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 b87b7a0bc4f3..921624f63b59 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 void testEnter() throws Exception { 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 9996434f51d9..ab56115ca386 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 void testEnter() throws Exception { 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 000000000000..857d3e548c2e --- /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 dc8feb04f939..7d0ac70bfafc 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 void testReadAndWrite() throws Exception { 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 void testWriteAndRead() throws Exception { 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 a51120bf8dd6..9830eda670b0 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 void testRead() throws Exception { // 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 7a1af09c0907..000000000000 --- 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 729b5eff3fff..4bf6d0747d69 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 void testWrite() throws Exception { // 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 000000000000..44fcb084b5ef --- /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 55bdaf19c438..638b06ecc1ed 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.")); + } + assertTrue(appender.logContains("Treasure chest closes.")); + assertTrue(appender.logContains("Sliding door closes.")); + } + + 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)); } - inOrder.verify(getStdOutMock()).println("Treasure chest closes."); - inOrder.verify(getStdOutMock()).println("Sliding door closes."); - inOrder.verifyNoMoreInteractions(); } -} \ No newline at end of file +} 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 42cb42e6bfc5..000000000000 --- 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 4fe37bfd13fd..be4c0d892b3e 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 @@ */ 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); - - /** - * Keep the original std-out so it can be restored after the test - */ - private final PrintStream stdOutOrig = System.out; + private InMemoryAppender appender; - /** - * 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 void tearDown() { */ @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 void testToString() { 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 35f4c1a8288e..d04e0f5c1e1c 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 static Collection data() { 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 DragonSlayingStrategyTest(final DragonSlayingStrategy strategy, final Str 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 e0cb90d42da4..0ea337f9312a 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 @@ */ 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 StealingMethodTest(final M method, String expectedTarget, final String ex 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 void testPickTarget() { */ @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 void testConfuseTarget() { */ @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 void testStealTheItem() { */ @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 4bb9a211131b..439a64da19eb 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 void testDoDraw() { 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 void testMove() { ballItem.setTwin(ballThread); ballItem.move(); - verify(getStdOutMock()).println("move"); + assertTrue(appender.logContains("move")); + + verifyNoMoreInteractions(ballThread); + assertEquals(1, appender.getLogSize()); + } - verifyNoMoreInteractions(ballThread, getStdOutMock()); + 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(); + } } -} \ No newline at end of file +} 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 b3baf8abdb4b..000000000000 --- 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 075f235f5023..000000000000 --- 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 4a131bbf2e00..a0c8b4eea63c 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 VisitorTest(final V visitor, final Optional commanderResponse, 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 8a4ff0b8d677..f30b20e0595f 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 void useReadThroughAndWriteBehindStrategy() { * 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 void useCacheAsideStategy() { 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 5a2565940839..c7c54343443e 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 void setUp() { 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 void quickRun() { 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 void runInteractiveMode() { 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 5e557fff2e0e..bd4687dd5f59 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 void stop() { @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 dae995e382ab..e181e87042d7 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.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 EventManager() { /** * 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 int create(int eventTime) /** * 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 @@ private int createEvent(int eventTime, boolean isSynchronous) /** * 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 void start(int eventId) throws EventDoesNotExistException { /** * 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 void cancel(int eventId) throws EventDoesNotExistException { /** * 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 213439203326..f032c8971ccf 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 @@ 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 void testAsynchronousEvent() { 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 void testSynchronousEvent() { 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 void testUnsuccessfulSynchronousEvent() throws InvalidOperationException 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 void testFullSynchronousEvent() { } catch (MaxNumOfEventsAllowedException | LongRunningEventException | EventDoesNotExistException | InvalidOperationException e) { - System.out.println(e.getMessage()); + LOGGER.error(e.getMessage()); } } @@ -129,7 +133,7 @@ public void testFullAsynchronousEvent() { 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 000000000000..b19c85a81b3c --- /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 33c2ba9cbd0b..30f70f54cf2e 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 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 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 000000000000..46e26c550df9 --- /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 b19c85a81b3c..000000000000 --- 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 zcmagFbyQSgxHk$T!XO|F-QC?tcXyW{-5tu%NVl|fcXvw&N+{jZ4Bbde+|4=PiSMqv z*8R)1aAx*?>v?|lMyjdEqP-z}0|y6(CNC$Y0S5FlfqF0m2rn`YbcaVK<&(qmJylY8+mtlrF2i4A zBK>rWJ>pK87dQ|MK~X-}@RZye+dt)d&55=@l;ab_kW$K|yM!j#UePDiU(Lc-t48UH zsdcpPT3pMC_Q%3iSXkHp?Caj1Jtm`&Ut4eVyN5AS=_E!UGl#)>vby8$__af8?m24- z**`v+ac1wr>{OiOzqQ0MDDhWo-`t>SGd4=m6SU9u=y_o-6d_;%@5Y>$9$NjLY9PZgS zz{2E|&>Q1&!fFI3!XUFf6}fDR`q9nU>1b!;wDxcZ^~QG^o3H+56!+l;Bj)ty^hmVg z*1Wkx>!?=onCxF2oU_WbmVJ$Gh$QRGjAWx{oGTk!;g7Wfp*kjkRbr_xI7WA!31eM6 zI?C%M{S5T@xN?%8cAk)dP}ow_uerWr&{#Ve*j)K_gtMWwTO*mJ3x?DoISfbZy}MD{ zJZ!AeIFZU)p=dbLNZ+Hw%p{@)%Is%P*TWq*;2TE6)iNs=A!wy;!0pT>%15ByBG2Sk z{k0ix%axdN`D9S{Mq-&TZDkjGx@5Jo+4mf@YvnvYId6G~woId3F!*V!BBK*bhF4aZ z?uuxmq54NSet!TimQ={2ie~pAJ4gsR{-_nNrA(2$vNB2bwj*8bNK)b7gW#)Xv+B(a z#H&n_R&u8r;nsILSAGKd+6yVH<&PMS@j7P-ClF8AEWw^MERk=7ryVJ8Gqmtk3CZ=$ zPts09eS=EfWq#yRTL_So=DeI5Y(|XF7-uBa5%u3u`a8Jm?AI zBpW?G!O-DTNbfv^BOy!~lh&xVUuSlbdcUbOee}Q@77w}OXYroLzgvmF45YwI_dUe!_`*DEaK=V@U65@~s*2^{+K&LApxlKgFt8CgE4gPM3Ercv~CO1Um?Wj*K=fk_)9)jiluetUDQprHG9V4 zaFV$}$O$K?p-CptB=Iqe-+gH#O+lF8XT|GjAwg(bXxTz#BEG7~JA2)C6LyiI@uel{ z%_<5^qKg}G)M%j%L1_%o5tP`Cj)LbgxBAyvL6l!rzqjppo5C~owfT#hwJp6 znY0W)gSX`=1V#K?LQDl^W$Os^l%UV#h0oT#Oc#!n@1Ox#6-KC*9Wury_W( zo!5kn%RK?lB3|sE7&xk4@c;Q|?@iDfr3(+w90ydYGYpXV&$z)Z=wEys88HaLj~IgB zcK2Pz20Z6};Pb^)z0|cHFuQq6&ircJWpvp5x_zK&O zZ*lyC{U?df3;{nV5n__~Qx%CSPZA-O)hH@A;E4bNfe19kDQj?nC@3hru4Z-5e-JsB z=_}90LfBD&-%lUpXiV4%5!2C0ZR0g;v_e~IwzpO(X{=@xGa1hj#%DJP1Y?zHl_$R8 zHp9V(|0^9RpL3TZY*?d-K&z4!;d66hy3rph(ER1Mh9Ia=HeO~h3g`Sc-&&cG_FOz< zf(Hc5kzbcXRy&0YYzX3Uyo7_t`aZC-va&sW{JH`mC^;E>rpAaUlh0Y^@6K=S0-VY| z@K-Y6Tfa_!Et-)~O;j85UG7c3g2`_H|A7gAK^-0*Za!V2T%r|xV}EE-idrk9*5VJV_+LR;Nwfef^%6AuRt*; zrE1OmGY_Kjzrj*jIk{5?(ZuY65sPV69cZhySeL0)>cKSWqvuI>aX_J=p__z9|4w^kfl>Y*`N*r|19n*Hz$ui8 z#Wa15i;KI&706?Sz#RdXB!osvSosT#0Rkra`_tJ3F+S>HF1l>cC0%3uBUKVOl6FHNiWF7RxR&WDoQI2X`vTFOw1{e zFK9s>o`+^*S^ORM($qwH%z7zc3{wJ8e<3q7Gp+Jm!W8ej?X*FkoXwwJL&0!^{8Np0 zhqXN;jX}sooWor3dtEeCCiEb(fCrAv&CRoERZ#-Q&+{C>R$OnMHxBOU5#38?6>(Z_ z4_nAAb-lZOU1ah8=gKlF3=h^fGDVo;NW6ZahUU-O3|S`yk28u?)JY@LEU&D%Ucltz z`jQ|HQIqz|Z5&RkT?|{SBT-g~rOc~cL{uj1AYczj0xK`o5L#PX+vny*L6wJyQ1iZ> zGLc;+TOic?>R`j8-;}tci-cg&_ROOSSvUN^rO7=sJN6Yb3$wbKUf|I(YLRs*ISmzr zZ;Gw2Zw#5`K?1UORYjH-Yp?A5>@4p12R8L*?bl2k{jWrK0y=;`__ESrBl7h=nl&vHQGKSf9b_OI*kGM@^hBIZi27w9 z_=cVoHu=ZZ3QeZzSxuM2+nb8a&M)pNj4Mf~S;V#qj|$FYB2V0AA`f2V;Y{*J@XITV zqW}6F?dMr&cBb&^v)QGSHLaNq)1yboB+(uHF{<)a$IF~rSI|Y?SRyEhuaAp956qNn zLP$t{>v4cO!~#c(j-ppSfAst}Fj0s!@ ztErFePnT{Lrx_>uFr|)z=|A^Q`EjXzZ#HcoDZ;P7Ptk49z>MWvQsU7HshHc3^(}j| zY&Np@GJZS1DLuAEnZSc^62XtCKzrk|CtmP+Bp0jq>LE4`WQ{e}{8h$M>fhgMy*4ZD zkOM4$8M-(>-xSf9(#6Of+?j`rm=gl&F#`FGKXWcb4HV>u$G2f{fP*k=Q#$a`EWWJL zXMO7^nzy-wp{4Xak-W0VQj25s_i*&@{r#ZS)Ku`BH~l`R-E^CQibQvJcX~iaL_{Zj zm??j$#45QWv1IN=P$Ro6Wk>uZAufFH`8T!dwkmFtPzo7FrL{5GVYv;m^)p^pNht+dW=h8`V)eq?OLBG>>dQ&G@2y2eMVXB{wBD~_stbNPA>Olg{&q)ORaJHN zc(b-O{~-WpAX*4IJUmP@MwNIoDND8i^!@_u8KCB}S}^N3NDbw3T1K^97}cA-F5444 zmTtgfGmiP4$+ra*tIZozprIgeILwqmu1{8&=KTNu=G%NeoUcv8b}M&H)#85@!ZFMR z$8FpX9t!%eRx=!6JDkrnYJo5k-D|z!obT+uU8}s7&5kXoOTtv!QIVxuBwL}5IgIl5 z?T_cjwdcsHr=uf>4e>&8l21Ut4r4KF5t6#tYfjvO3{y3<*iO?@1b6v+kSMu&!|JK} zWjTT(BO^b{O^rvip%K5sh{k1+u(6?M)TyGM!#t-_CH0#e`t>U$Iy(C7K;O_%@pUw8 zelwB5Dvz8NiU|5SiVx2Kk&~0dAYq9k=KtK=E5;z*$Sfm<1FoYRZ!`b0^j!;c*xkcp z;6uP;D6iuZ_>?e#aVfLL+J2^tBErB`l@v1m@@9p%-P@ySC|mKQ!chQx4fbD4hyft( z8#7%swZNevIW-9+vCr zrxIEZV{@rtBniC=+5##@G8mOi<5%y>UKKv|sF9-AoN$3o0OP)IZO&vNB zuaehX#Gc>9Fx^62QBwp9ebS<> z@PE8-^S-Kxm}jDdO3M`&6`Aw~!tX6LSKdC#4V=Y`KC!H+xY817FmoaL3D$;&_x6p-_4ztBKF|Q0FExZ*FZ3YBSMj{>tLV zDnc?EUH#@~SXC%a7RWHUHLLppr`}6S;Bcm#%1JoFBQZ^Ngo0;G__*TfhyU|KvwXjx6XBU@`9K%OcMDQ>Z0U-^dlI^QGLUrVkZxK$$1>Pc`+uw3U_2oyH4u}5=$%siH z(Cc{(L_jESzaqU*0yT%##FgAa&0u(!nj?z#{qj#qbz8p(V{D!&geq_4Sl6^bS27|> zq2{*#4qp0NarV2OF|b?=TnaH59X&wpwXxYb(CF2KK?(EMRFqb)4CYU0Y}pJCv^$^s zbHU|*i26jTwc{nB*fT(bjz3lyn|+y+WM6MDwno{&C?Ac6*Ep|>MVbM~<1V#+wAlFd z@e!5#NFVL@W2eIABo+EZr*X z_J2(fe&Ga>3VV}NQzML{*~Hc*jY5w8^p)WYNA*Q_HJ}I+q0eR`)$S1hSV8TuvG%`V zlSeq5wp}T%Fi=9JiWO2ktjUN5z{#(JPJ5n7?dPiCX~-t?@VkFc+Pkowl0K{iuWu8p z;c}R%NZ2ut(UFFCXA5`m66aOocgc!R0Hgd%!6c;qA4uvJe)ISj9{k07HG5LKh3kPuAxcBk_f3yKr1*`(Gj5y>CO0x`?zp8 zP-!-*TUV!es!mQ$3XmL{?Pfh3OBrH2{T~Gg`J7?^dYhqvCVyjDzbMZg^9y@jF?#1TT9~~`hUs<(HTiI<65;_+i4$U0M^Lid+XAj zVdK_WCVTQDmS_;kts9jV>di0TBH0X9<8mf+-yPGgj;q3_BBuk{+SMWBT&!coto0%?fyk`k`l2BbPW#Eegu!hxmfed7_S0)L}!3qetn^JC<&`z zQt|K9;}J+9X`CQcNt6Al;@i93TtL0(6MLB)F>&#rp^|JKdt88+&wuz@u7$_q zn3J1}Zf|eDu(b51nT44dK|b$Y`ozS9Te?I8__;3_Db1clHT5n01+S%*mD%~`;1sf7 z6m^YsIrvvsWEci8Q~BS`v;o;>AQH>)iG zNt)p_hr*>q>`fI%)9v32hCI3w0EG&$4mE z5NXe0O$FC@By`e&&#zGsAk>t27#QSsMvw#mkUZwrpz=Ad#sE)^mI@T{yUzn2b$}qT zWuTlZV&prd-)xs6&z!$YDJ1kBVfLl`5CE#oj_^b9HTWqc1qIf*s)(GHK}0Z+lAPq&g@e{Ha#7iEPYsQUg=s@Zvt z)J2qq+ON4l_*WCn_PSlqPyf6_CM|f?%aehPha6u)h=^nQ@#DuIztXv8^WGlzg6Us| zI7qRJb`=4LQAK5~QpT?o5Z6udLB$DOx3{-Q98j%-Fd^Tb=cmpxJQ)t?pgbu={Nh19 zh7@`Xj0Y_Wr%>Fpp8lKjRFQlb!$>8mtIsi76_g-Y_cNrF!>H4~?<@ zZA@SRFf>hUr&Xm|FhD*u2Pgo2NTrsR(M;EtIzCyi$G@B0-b46gYl~|0=;85^j0(!< zw2YD7%+1Eg_@=h!spB@SCJ-o>tTn#J$HzGJqr|-VH)7#$Nwj3M_Jex?l&8IA#2s!O zk*e7Ga; zi=di*zR|euC3H^IY_Qnf!*o;1?@C@ai(-T;VQ z30*HO66s}d-x(TX6RChYXE14{h(d}w96O)hdka&_YWF3oN8WEsNDLL!Zyy?G3rtC& zsnBW&Dz&FU@Zv8B%0=l~c}LW`cUz7~f>ZFclj+QTCB*N-De8Gtm~N)7;#Z_zwo8!j$KvAph$cYG9Qc7=H3KnwXg#lh6lHt6BA zgoV{MISmU++^5ClSPl<+b`QmWjP%&^HQr ztNleLdU}lcrswx{B$xl>DENpk?LymWWk@(;D_`f|H_!4`;*fi?FvK;-)N4)xk;5Gj6xFtkcL`ZA@nRiy?d^-xbV@K}g+xb)(1@l>+jK?n#4 zGMv^vZI9q2gt#8eFw9iysz(3p72pC{N(9Oqr<-ib$MlN+Z`G^!iw$Z}_RlTx4@L&_ z;o+6%^`7z!=?e|d%mTdUxF2@dKOQXvQAmbG*c;H%(J5ytv7E+{2!?qc&e<-#)yaW) z5dypZ_Ra)hBm(YAuGqkYPBn*l>rGAxF2Yc7>v=EEB`R`AQgF6~U9qJF74s%{N9zR- zN<1kIi<;1%^}b-5?-R+N0Z77Z0PDV-QY_Ju^Nw&(1UkWa}wKN->19X&8VpRnTrWrko$agNNZ`dI)_)Wz7mJ` zIiCi5%Lf-*O`bae9E`VUXgH_v&dz>D%9^5v3eUq^0{s;Nffn5i~OydeAmC%K|jdECPF53546EZ^(Uo zZimkP{6S&OBf7MM6D;Lj3YUWjO2oG@`IK7iaUD`GYzt6JDrQvQ6fbCg;EZDHd1xR< z!9E?7Bm%1~Qz!fd2ziQp4sTpcGdB*1xY3*uMlmw;1!;CdeYO%eOzHmZX;;Df(dtv3 z)7~ik({-JGX~|igl%KaiecohDs<8!R3+Fmz1HFZkzl~mgzr+@xdK5HU0w+6G4<*{%#VqQAulb_`i_x4UsSQCH0LsZ3lhXaw|@J`n9_`9P_3ymTl z%e29TAN$6&GC6rgZX}3L$ke<&q&=`UBHl^+6h%qXpExm2L|mk{w-o|L8o_aA^- zQ4QFx3IOfCKr;O8gnPiwG;+A>-o?ivtL4wKIHF!1xBZi2I3Ic6)-}~hiJQVVxO08U z$^M)iBeg8ogMcJR*K~#=oj2d8Az32;#bMOyef)Q$U5dwa>46Y67F%n7CvS?NAQpIN zlYTM@6bR8XK=O$+YYvMGcy@im(=9wQJJ~^Vo4;64Q z3i>#U^yCPl1qk>~-hbcO<7rF#g#L6Qe&+U;zA+BDygs6nAT(+YXR>(% z&dBHbD=g)%UTs#27Fr?jR!7DW>>}+uofCmAWqm&-xi^`gU*vhNAQ^hF6M7o;gU-2$ z-q9|yR#DsqZS|oCWed;%c#eTSHrWMrHyRFG0Xl&0d(p+4~4l{U_Xq$crR4EQ5_MKiG4{`*zUrdr(`o&B+?h zSc-5AFWZ$9X54_I4Ab+N&Bk-qTTsQ#S1W|Sii!+;DMp`@i->);j8U$ zKKn`UFE#w%>i1We?O!9nqsrXsWvmS~8gXNtXenh2;Riv=?$MNo ztD@Br9NqwyQ?_Z!Fft_eERQ^$R!O##&?v{Qh_$x0EkD{A?IKE%U&QNteSC180Hrfg z{pH<+yjPHU!Kid$5ny4l2uwS3U4t46l^D)S`T8#22j6^4F7EP9V%;Qzs-&Bu@0ygz zg?V{m7SkF`MF6L=zaa3=m{Pp?ErvE9w#}GiMi169-nLWVUbW$xRfAL*{G?XZ{;6(d z3G7+|#vGfsFP@+F<#y3i6E5zErFq7ymf}Tv-9&L;H(Ffhcd@!YjJhD$ZXFf=q9Deq z({*vW(a!vKe`y;Ci%vyKMg|d=&G@}lcN1rV*||S|7n~7ccgfcgLzTynpz&{&(F;OA zsSxH(bQ+*m)p)1>b?!y7q5%wXDh1gyHC%XxBo@-y_iWwv+h-oQrp@L*-=Y$5N;R>% zyCt%2X)TtP!B(z~mP72zbuqLg+m#OgN3Sn`jTn5z9tLX$OkHe5EId4D z%KFbNzz{FAZ2$X}`*=#vkrLp&mX)&l!7+~K?Pdy$c=`CGwK0o|k^#a*AJ7ML8Sh_! zeS`n)M)*Zp-oks}wZ(rEm6O1GH)>4k3iFxh9-t2SeB8Nk9H1@Ql2O1tvDl^*?STV~ z@-mHK#GINGjP>mZM1R))KQy0yEl#@2FSrUp{3L=c!c88p={@W;NPZs>eDFDzA5kD_ z)N4YrOwt_An|dl6ew(L6^uIg;&Y=JH2oi=Fw+9FnFKUdt8SRV#DR?Jn3LDd9Z-N5g zGZLQEr~gAEooS&X!d6{aROIL&d3pJQy~C50P6#nE^Ej;)dCJht{}&jO<}hQ#%t}uQ zPHtkRrY+ralXydX>{#!5^}g%oKDwdhETi*;x=YyT1@bu1K|Dnu|IuM{eaF>YCEgoz z8YON_m#Y4}`@0*YAD<=zt=zg_$eu#Y~k{Jb9V}J)lv$ zLJN7#?JNJ!Lq z>}w;B%KO8I59+)T zLVj8j^gKK`ECx-zfSnOidNK(W5fLHZ?G1W`D*M zVH8|uv7d1y37MJEe5+os{)Z{E!2T>QBGY|uvYmFhIWd~4(%0;wTUlO4^%q%4vS#<_ zQd0%14TG(%tpPPxQ`L&W3MCHSq%l+IR}v-2FZ+JE6GV?N!fr1yQ`(|KWY@(hdjd9e+tJW zORF@W?V;~X*VJPBe6?7z`BCy|lFEyknI(A?pY?xS657gSEPLkR!kFXMHGd-5WMfMU zE_JM&x|UWlIrI`$gXh&nPWSym<>s!(Z=d}s8VH?2j+M90i_9;Ankah)s4W3v7jnEt z^{o00FbXyL^oTi(NJ`M{X~44~hKQZM{6KWX5+L~_Ecybrh^eLJ>x20Rz*mXlfekCF zsIa<{CJ0gH!V-##iUA+SXoy_+^XJd(mLu5W%#lTyw#D6Yyo24CcU=L`-^h#o?k^#y zq8Br#E1kMkG@J_0d?m?%V6(kS)s>_GS!j2s3qvEKO=NL!aL}qK_MR2M_ak9y9Uw2# z4^%hiy!b3l96Pwq>N(k9%A=1;Ys5#|_Bn?lDDk?X*tppgQaah4QtQxxMJ{b2z(j{W zK2xdg#7W{Q0^c%+i=JS6!HkN}F6O0nDI|gtfZ~_Q6ySJ&5|Y2ru0Uoa8Sw?5Gos25 z@T9+Tn1_*j3wvK;w%>iLZ56GUhI4oXZ z3>VHTWXMv-4-pr82uV3jSs2^h@hz7~ofXGjNetwx=eSx0h zK)euCnnE%?J>A9C6=Ez*`6CR_0$;Kg9-(lLAVLl^gs`_H6-=GU>{h$yUK6@$b5}Iy zaS415qfd={3j>C}!yHXzTpQ#_>8qW#G?bK-17vF5=+`iUPyIi zfVi+3%wyDzIb68;C;3cfm_RzX#*V@16hJYQ6cJ#(bMZ*L%YT{R4}f_-pnX^vTq7la z0@y`lU0UsKmXkG8qoaym^ATDJep2kihq6-DZFKQNj`DvaVCoO67u%zu55Q@Blg%(0 zV(}|mP!~h+fqYkL6NF61mr6_;OtI{Zf z<#Q;?&Iwn@#he-Mi#0D9l=#9JOd?Xd&D=0(+q>dDlHDNFm9leYBW;kf4?W*NsxkX5 zObr$fkZTz{3+l~k-J&Y4X!Bg ze1*w}Qjbm&gD!UpEKs~PHM)@E8>sTaZ(9OtMA#_lPQQt}hCILb(-B+yV$kqo-8Nk* z?J+XZiT3fFHR_7-K5et33nX;*==_(zb55+Rm>df8EKFp8374#OVh88|)zy9!kdQ?q zOsU*v+TE=Oe*B0!)K>_}(@6rD89%&1GeHhR{$eHAJ( z@bhPMrH(=gIi^C(L^Cs#&Xxp?u~+q4otbiQ6S7~WSsE81PCX@WEFy`NBqW)z<(VP7 zp8aVR;w0nsRblI&6znZyW4m?}`B zNT^yc34cJB{C?#GgG zXQ&U_JdT{2k8JPw1~`Jg>HabB=L!t=`UolfhvLwFVp3*t|fdx4MF%(ae(-$ZDnBK3P}p6Xw4LO42d(dF2?_Ff9{`) z%Qx%>vXpu{E8!&s4{?CTxkc!{r+rZ*(<~%up^3di5>21siVLU7P@^JkW-C&3W^`h6 z4CCHQKU5Pp*>BcHm@Q;-t8M{h9R* z$_43>rKv3%O65ph%^oU~Am75$zuvh%ypJmIbq$`WTBVex-c-|CR7dI(vgcY-JESxo zH8nL2CI-|VcR~6t^|f(uH$NJVv3&kg|3@^YQoi9hzsZCaszAm1+h6ITs4t<|1_Ay} zNwIiyv{y1&(0}nu?U2@oPNA;P0%q@{RQvz1@p9^5pOj=tSWT&0tO`W-cPVLkl)dd7 z(KdD51!YF5)HT$H7kf(U={?k**_fJ=zPUJ|5aq*aznS`y=0~*n$$7(AhLXAJ*z`j) z$B}SGenaK?Jq|&cC8x6ZUOcA2n^ZQHov5b|UHaXV;f6Bs*qN;sH@kZ?CU99yifbR< z0W|JomVPkgSTw{MCzsQ%_{kO!Ndsh5r@s6rcjSeGSBNg9OwkHVYDj$<$i5T!uWt0P2$Tud!+^)%jrgBwZ;TtE)DJ;q_xIIL?I3%X0N8ux5{$+ZLE9B5Yyp>KL ztWTP3R9sh_Zl}fHhdYIdyCqCC7u%lN49KTpH~~|hOjpmo$rI{7@-t)rjvMix5h!^B zzIgB16X90UY{IS(AdqFpxoBeq>@~D}c?3WfM?UH*XTZqQ@>OUJIIM0}s_$mKCKe4q zm$`OCW>Q2MJQ`-BAJ|-bYc}R{Jko6a@m_lQ8+KTgVd=)+B3R`F&D4BXgOy-AJuB0X z$d<1#!G8;zQ5!8p@pn$0dzCgR1bwF>R!K9v{iRy;iR^czjELEo{!iAclA2WbV*NNC z`Dc2z?s;x48S6&=YaxZ{1bJgyaQR<=`W*=2%_*26lo9YYcjZ%N38Biack@H=xypPk zM$cBBTHXGW3KuCATr?yl_?ogbI7#;nb~3!L;9;2-V4z$1=8xLC6`!v$OWrnnf^IL^ z>K4g|lm6ttBGNTCx4|JHYZ(S?PpxE~!(btAQ@S*&h1Oto4sYyWy#JG8bFF<6HL^P4 z8lK*n9{W$~oc0R7g54NM5Ci!~nM*~O={ryfC7IqvT+vr;m%p~56+B7-MjsCk z{HZ?(!o_z4uWK~QrUwC!Cgr?TUhedN;E>ooaeA2jm>#R^MLD?V7-t;p1HD;4CDp2l z!~efk5J+(8JYkm71-3ss%~G6vj+9sf{uL#=>!y^t@I&Y6H_h5a!bv5^`3UK{gqxEe z`_jFS#9p_}X;%gJ~)Oh*pHCbp)LpZh@;yH@1Fg0C3}BHI%Dk>7q)vDv`8*GtD1{y1%# zSb9x&JABUp%uIXzoTbz{kXw53(BxXabaG1)Xir^o^Uxw#(2~iT&4Ai;oZsp?U(Hb~ zMvBHH4^WknUa}soWC&gHt1+d|U4A!|*&c4h^ZCooy7nzFIp(k}GZWCVh4l0d3L9cy zy(g*Y8!zSsEx%Iyl{0Jp!Qo;@BjLafC}I%#94kA7nh!m!T^E24CKdW`xprV?x9{I* zARJH8$z&mtOgt$|u*YAl@|G!5+xZp>ek-1eSt#lC*vRY&*CmWgbIaxNVa=uT-rZd4;cxA~QeTAugs_{|0QjdElLJ zbAoLo1v`=JjGjLbbSO~oo`A`?)R_Z@%>uU1P|V3E)rpm@)!} zZZ0r1K7dmcm6W{rvcT9Lc1VTOLP&mMP1148UH_hQj+ZE;&eHOqfqB|15xYIs! zoI#&!Sz@uvPD_eoDxK@A9wUF}Eu3>zjmXLJ4?eRG5r~)|Ty13oDQ?y(ngZEYs+ah2 z=y#Wx9PhXkvom@jlk1~JayB^`-<*ZxCI+IU70|3t@k&_ZJ7rad=*;mC629dezyq{y#*s@6R#W-OVZ9 z`qb*phJi4C+zFaxlZyW2K2R(Z@gp-FpF`i^Fq17UYgriRBV6|U0r+GzFj6XJW~JvJ z4WSiMfJDU@ADY6*2CCGl?gwr?xSXx`U9fK7ZA-12TzWbPxx5yZ1koH@Dt6m_r&KBQ zVfxVIaNFaC##aykccHnlzgC`=Q4w$-+eQ+Y!X-rX?e0rM3HkJatYRi1K!-5Rf5i0V zi3c~?!r52b0w~7z{#Fkvkylrz_C8vT7<5&>O(6;rjQ<(@t)r=iEmAgK$jk6LSNbRI z>Sm?QOV=%$j$U7bd1{sAyn1OzYfbqKa?9#a-K-O!1u34n-EIB3Z?O=*qHR`pj6L*IN0KjYxxDrIpM%k#A9bRXm>e1w9cAk^ zlFQBp@jiUbK6a?H1S3eybM`sb9Y4XCA?;6RH|0#!tEy2_U-7M ztb8=5l~XPeL=r62{TbdJW-zGC7j3P^beGfm&zSRe&4+Xs8;x9XX7UFrTxgs{x zC1|wD8Pw6fxCWdct@v`&?_sxqg(6On-${v;kdyvOlucLblY2;|Ce4CwLug9zYd~jC z_z@Thn?KSpCij_4{{i`gnguyO7<=t^49=9u6P&o;2IfM^&r>Ass+n1<*9v z?OtKL%fU=}I4>=y+yB2r7Y{v&LK$g;qPCjP_wu;}HiV_Sv@(^>_tKca5ie(^mW5(l zbO5p3+oQ(uGa!VRF=6m`xkJCvs=!C;`RVaD7F>&gEATQ5Z~2|+aX^3>HwavXBCSNB zPVr6EVXNHEns$<+;G%lHs;qFMKqOhBNV#X%CqC}2mfe27 z^^=O0R%YC)!I2U02y>#|25U12{_h(ADSnXgWP~6ff=vuCiUy-Q9GK$aYr zo`HNpBW?&bE{tkt{rwE`BYf&yiiI|Gy*G%GH>PF@N*~>8U)zls5D+kN$`1IP%YY%D zL}Z%E#{Uxee+5mXKU2Nn}zG? zJw9<)PO$k^OT$6=0RM!cGfV+7kg(XgnkI zluj_^!n|F@G*)CbLI?w4PEO83lPy*bbcf(v82T{eBTLQ3$A_n*qf_u~VP;l99(>6~ z2?fGxXqD1-lMDvN_tN8^^1*MgFKpGTX}|y*24)2hwULehVrw z(B}`}4>v4Jt+pDp{0b@x5sP4?S~acmIfDep;Uwj8B4|8N1>nqUnOAq(h?0cdg*;=I zm_zB}g@RxSjjgQ#ff80$v~S5oVt{%dQ8@{i^(Y|Otx!B;jQLin3;)L}UDs}ffttKL zxP*j+q49A%>iDM~0Or+)MR84gazgqxspD%5ZF38{<-Mu__cC-2j>OU$1SnK%7E zM_-8tHM=t2Q_95t!(?ckevSO_P}n-zXz24xzwJ%w`1^tLq}_>sp%}hGp48uN=i_f} zJ>R*xT}%`j3jWIGM@~(h;>}j=Xu{%+3v#*kGsZ+!!0ONGn!-pt^}L1+hqEX?Apwz^ z2Wp!)@aEB621KbjAt9kU%TZi4HEy)1Q6fGk;tr2}$_O$@!~NCa z*1>FL|92g!i=ppw1fAS_BPm^;9^Lv`u@^2cP6rSYc^;F;&~5R z`UriMrV?&?RhxOf_=~JA;7>fbY(G}}@af0y2R58F!3EtPqqQnBa-Ajk|E`%5_YA0E zbIpE%)qE9*Lu6mZIiQK8M(rW4O2+N$o5P5dKwwF1-7DP|gPpcBRmhshZU!R~ckobi zGR1K;l|@{6Aksmd4lQa}&|?n+xTF|gte8d#q`0W{UsO7&C?Mq&$*-@kPx&#f0Y<-- z7O_s`+(ohZKz|)y@kcWeF-7SmcbDGh(X6=I1%Q|6!?lg?;n9B4a-_pWzdl?LYY36y z_|dXaB?xse^3JM###rvSW%}a&O546EaX_gjO!)k9x!miio$iC*5927=>5r0MydCNG z6f$Ho$G&q|KCr)!?Fp)j?X16xf4#XI9HuHcZGB+A>GPaCP2s#gzxEVjl!>cYaQG_m z(-oY_VPr+KajMoyQV4_ivL&BHA(6|+Y8iADb35RGF9g+hU=UP>%?$qol=)D+*hCsq z5~6%WhG*dar}E)kWwkZXN@*cGKDN)rkNa(EK0K=|?N z!|irW5?wQ0t^PmV^SQG$cC&?~dO634u(T^@SXq#GGi293kN6_Uls=@#lw`@ZJk8f?tF_cv3bV zG?3k)m-u{_2alqDn>U%;CxtHpw5N~gyPFe}(+iI`-_wUZaO}+;V`=-Y&Xh96?U#MDM(Av2`BK(%;STtv#X!p@G;>vc(%n8!bQc%{K#>__L?RQRd2Wb-M$(oaF7)We*4Hr!3~b7Plc36BV-Z{7fL2Gr7Fe= zKzG@U2VwC$lxE``uF9)b@~?dP{kRQyovCwva_w%i+byF~uPKCPXR}!O3m|3-w)B1; zv?rs4a^H;Vi<&KtoB@x1WoNSAAFtM(ky$j}yzF_A98sN&jX{F^r_Hr6V!AjZ0|?#I zyySEdM!Le8!Bs|`Iy32oi8MmV(qgOyy(DaK?SjTb(i16upyqZW%R|*1A^m~#3loH7 zF#zyk(*GrGpb#4dJ1#Xrq=SJ{9r#|?f4NiV+iG)`L;jIZ(XEr#p&O7=D7dCUml0!l z0iL1Ur&K7Q{B;EN9D493&b$CQBVm*5cl^9&<*X@d7-(a=;4?&X-~?>N=}r@6O| z%4%ENhXFxAM5IgU4oN{N>FzEGX+#<+K|qjh5Kus*TR;IRr8^}Aqy+@&wvg{$y3g7B zyub5)-|x?F562$Q(C1le&AH~h=N;E|-Gl9EeYN<{;$kRS4Xj!-6FHSn7&N@|4Xf=J zyW{Dzb(#M8D3oa0uVNH4e*)yDYO5vaEVLP^e-o#L9rj=O>Lt|DHHuNLnrvp;L!$eH zq??OH+FJLL=KHF+)byA>Y*y#jwKAa#Uu<=UaeoR_K9&ghpFcuH=o&nCWFdIpr`U^8lWrauP;ocSQVY%> zWYYPB55V*bzc`KfkMbOaAcn@5nE>vnBB&Ge)n>x+3s_V5) z!lzj@m88JSWWDSqz8|)bS5SZ;1M`O;op4~HC5^AGt#wQ9;P)5ik$DTR8wMLj>~T|} z?$h1-lSEitHnVALK2wzM>z37Tw{v$|G0K+Pc|WJ%d~z?OSJgjZt3+4AbM)G$)#P)9 zQ}-v%5vznZ8M?erFhM{O9<;L&8Xu*9-~BT9EVf1W@vPX8Y*x|>nd?hmzZ@?fJms~z zpsA%*=~ek!iHG5T=K9gVH-oLcJxY-RHIo8c~Z*0CF0K2MW; z<>&VsGO>&IGoG$qJ1Sfn#fUN4>WIwmG;#DDkoW~VW^r>f3P`|DAJsYJDB@pc*a0vc ziDlqYlb7u|)QD#cuD_smZZBmX^16RufcSZ43Qz$7>B;uGM65RL4-O+LqJ>h4}0emN7+jh28cC?`7 zx`u{Nz_+~esNh9Gz@5XtNGbO6cdfKTOc@s!EIiLOVOJr+(mO_mxRvXGAoZ(Csdd*2r_C7_i?(yT$S6o-NjLmI6 zp#VLUh=_znSn%BX6svrXe0%hvl5>TdB+ff^bRSWpU+0GRBL0S6s^2L57xc29P-Z6V z7iza!NWnv9sao}|dP)~z6m}agfd>bHG4`z{)y+lvl_5B!2r+@7ch3x6IU1rqt>*#w zKlplnU^Y^EmYcgBQq1%QRgNrikzkD7e0K=mI4cgnf*?8mDL(k4?OnbDzi zlLgiI1=**0|E!_${9QxaYZrYrdTpV%WqlXd2jl*w#~;?U`m;0z{zob@wM=$%JSdIi z(Cc%CrsoDdgbGw^yTYwfKOU%$lmLrT4~PH`BRTqb3AN9V-HU-f)>rU707#qGtV52rk*V^K|Cnzhp;|0$fJ%%|Ix zjv&VuM+Nl~}J$sbt7MXp^_eQ+D% znHOhzWwTW5PtLO5upa1cwfx+pwVD>(nigQ_DwVAk8fu#}sGDrzWjzU2NGo!A-}vZ_1ocuuazN{h*trs`|4LNXdv9e~mqF4kc$d)D@S<03d_6k_Ub z4BpyIR=*jV><>wUMR_(xn6e_7`bvmMNW^FyJHn0eU*vSXg=F9E$;rcAox{_hXl$}aEl^k!Hy zF|%vO+0K_QhS`pW5jcH)s-2+G74YNc?(SVYN?}q19wal(g9BP%J)=oLiHO>FL8;d$i7TI$M`AV z@#YcXd9fem3U>|^_dAKbS2I_m>4R*{&GnTtNccopRk>KLiDw=dzOcs~O=+(4@VJ%m z@@jzGtOR4{yy$w*7~OGaQ`_sNdT?N}YOq(IY5%u+$VuNpOwMw3G$g!pf4w6|_8j`t*=a&~4}v z88<#_%`?=pFypq}+S=%H7XC#B)zu)QtzTCAbHwxVC6kosPdZ6CZ`TvuI{V27pdx-p z?2?x@Q2yU9e0UcyPtU*9-Edh#M<@XZ>&W=CH}EDzAbt*ujm3;-yN>Hd@6C=k^vIX^ zmQ1;Qk+P1wTQseb9 z%V_T5nO~`Ko#xuF?S`F*9Xo_+^mV=9d0b-RBcSkNWpHqw*;!cja|uUx5sGNi=oIsYH`#$K9IgMbC;9`*Ve6sHXn=x8o{jqWL|Y2jk70oiE2FL+XDcCf zX8O)wl!QY+00HKeVq;+;^tQ0NEVfl3u>=i|j8{B=PCfVFKtnyxZ8Pet^Ol(lZzP(ahQR5b5kBt1u)ZS#5Pd`DvgwLC%P#!R{xBDYfPUW{~_esc7r_r0pX` z{9zY$EsoSCK@K?vS+_e-eJ_`+#O%)A(XD~ zzN$(kRxgxycZNB7iQy%Sf6VGg_1%#Zpi0JxuWwZ5$#QD$Tk4{;yz4rS@ zSXB4d6rVJ@N~49F#SbFMw-4`T8$9J8^WEX$vL|ut)`PFy@^Tay7#Pl;o}^@C!T>7f z2+DiOtTy+&i`0A?2S@37=__&~Y5}(njf-pFFNzqSdHd&Gff!8x)i?C~i+1Oo1lLz6 z%QyT`@}u8fH{Ha&b)8Z7{lI7fqf+|-9z^RnSn}``h6!RT>b&T;tw^F57R(k0=!SIR zomYcE&!Ys&?nknEh0^I%S37#96U8~XdWM#r@48q z;ELR4r)}=T$Ngzc#GLJVhnmENV%F#z5&$!`ncSuPyt*1O=}_OaK3SPFF=pd8K!n<( zK$Xn)V)-$mVd4a`cZ$|og6HGwfOh6`TR|^_m|d6X7IP~x71g!!>&z-ogAvkZ`#X&p ziuhagj-1;sd=E=|CHD(gE_&mI2NR&?rQW2wOGGWd_fUEQL7v{(SETbkq`3VlfjPE3 zxW_FeKAu+O;oT4A#MmSd-k-P9P6$m1qhow@nI~6Y^nGG^MEFlgvCpi@4bI4ClDxVb zEoMoG6BZraVPncA9ld%wlIP*4AmX#!@)5Xy`&xrbn#&~dhq;GYZ)$JHhszK32R=_> zFK)QmI$lJu$vzeFwsK5KkdGac)y_a(S+#2=nCQmz$84#J#>z*rOBDxRB5O+ao5BKn z=l%9rgweF}mGM=vzF!>#0h0@835kt#TqN<=_nk+GneoMX3mGM4J|x3vHVCF()VnSJ zas-_KmTR#I*I1q&nVM@;lFJ?-L5Ej$cl|ouE9qZri8SMS*>9vRLhIs1 zL??Rqj>+SEMZM>Ww530!$lY0aLKe)A!_6ieduNv}rt^+-N_}gj^qlX79WOZARs>e4 z@qAsG{3F9;R844uzIf3#7c37_$FdRq2i-Hm`?x!Y8S^*-r94q(O|}54$aGUdY?8pG zeH|3Q!Jx+8dH1#&cowS@d#z(b%vRa&PUd`<@IIblz5iW_4x-UPaI|<>1R=@~4oBo# z`?yYqc@5}XzpuCA?v@!)s!)C>msh2R_`dOo;knpM=;Oz|1ov~8(SKJ5o=nIsPFF1&P13v6@%9 zN2xy9iikkyDM%IPViZd#m|tAx$t^K23Y{P%%M6ayo>Ypio?9jknN;W0E^g|DrGSt} zU*ErDt-9a+^H1O)gf_F%*BjO3P4I`{#DIH?_HmJF%ZhY8>?8(zJvN?hEg1y^O=k18 z7ewI%nW~I~`jNis>DN1)wN4lzwL*e~LmgT_UJkCV_0W&93OMy_4~-PHpxn@VB8DaO zABaTi-&Z#oiw>FIVZFI5-#YB0Va{klk}PtUb5rKSr$gFMks=cl6GQbh4@-0^#J7G- zeZh^<+uid2&`F`U=gh>T3IGHlg}=~6t&9tvS~3s6x2Rsv>lM-{j-_tgAgaa1T&l^gd#Lw&M+y_vl4Jh5 z5%P8`G+ZcbRlvk+5kn&}p~_x`C%5tG&(#z{Tm6y;R+<;9(|Sv!O_iJ51Bb}imMT4D zdPorBxh1cG`qbsD`U35tWFW4>D~&?J=I5CZHq*tLO!ll`9dDUwM^SYw$ov(z?`c0R z93dkl%vmhR`B|(*LVJ6JO31zNXC$K`tq#HYjwQ}HXNs4{+D!Rz{bx5fv1E@gCFS~O zYTuA|=dfnZcbu)y4!c#Ix7>ndi-;*uh>0?JpIxE)Cx{Q7>vI6_b9)e9S#p$pk?kSl ze(%PD#6_y=qJxu@t}g0_#?}Ug&*eLMi?q?b_mywv%C}CsF0(B;tz_LMeAuBpAH#v2q`F$$^MhHgt;DET#{R^7B1TOTa1XniGhg-Q0D|uPR6k~h6)#K+t z{PKYaMmUuxra6c#|^4WcZ74qzzO`D8tAc+*mG0}u$6Yi)g>%+b65 zZxDXZpNc9q#l-&MVXsr%`J$#2{Nz^!271yg4jVH|Cqc$vC|YONibSn}P|E_~UO&*| z7xT^u(eR~Ea*m#!=_fte_@H*Eezx!kum1|RfGHOiR>BF`%*e?{P&wP^xHkJy!sA(? z`W86-#lA)=b~O0wf63_a=227u1?l;dP3=*#8_qOn=g#4N3Fh(tMHRLAkpNQc5ot-L z>R}!4uC}M2Op`Y zSd=5jd&60Q5>$-es`(s46TXj9FpnRWRDbE=6LnoJLiJW3O22uom-}-I)*5yoCd13H zwXN9(Qh?%J#?ZJat0pR^!s9h&Z4Xd9Tku^8MKEGzU#@T1+DF*6LNBWw@v`25IK zJGEn-3M#*w{6(!~xybHjgRVll7Z+s3eZ)*<7kCo7;z0YiIS~-~{V_$~N7;@X?3z?F zHE*Q-5c7$xyMA(D^#ds~6LF(iNsDt$dFF4b8Oat#XXYQpkjkEGM(Yg@xM?|*f{m4# zYXm8r^< ?wgl~rLJ<;Zx^H*X&n_Le=^Qw(AsFao7~!Ce8Q6=l)CEk*5Tw9?5t1B zf%q(#XofGt)TSPd)o%iaaizlWnN}<)FT{KbUn8VoXh7Ylm3yI;h*Vajj+?yBeZuFi zjS=Xi?<9B~fgCECS2phPqQ9Q`sL6S1mn_uyZ`ZrHug2AVPLZ-rHB9)DI9U6CGuoz=-dg<=W~k!xErGosO$Hacvvu(q-!CW{HBL;uA{_Q z@j)clTlG-MQVjYm6nHm8C~39BTz}+!5$YKt@2g`|nE7Lr;+#OT-qc@ZIq$mc`e*dU z8Eh?Y6F5sbIOD)#^p{@A&9$QCxp_5(P;w?_JPo7!Vq#pSa<`)d_@_Ylq(aiJ4s1N46Us9cjlrO%&zHj3eItu`XTFQKCMEQ zLdL8&i8YJ;J>VIh&7irhtFdDagAkqgI6p7ICRxRn0sJ(|e_^*gDj*zLAxq~LwvHYl zIOtsph>9;l49TBnZXb=$PfoKkld52H6IE;d5CY`i0zeIpfN|F3G~kpKH-YEwiR1!@ z9{mZIX$%0J%mAs)^eR1!$!h$)2WRX)A{qWOwa7&VKuJ7z+OaNP71ECWQmGmhK!-do zy7gRp`sKBWGD@GrwLnm6Vs{icD#*Lh2*@sjy{4lo+C-79=gX}jIQUdlmwGwCrl#`2 zTIv6GICbCPa+ZG$q)$zFxpLv=ku5Tcd9JvTr$2oKHO8= zovbv%|1zj>5%}?bC^dKlDqKB|WG4m5mzK`v=h6Z`yXT*s32QdU)2pcS%G+|#u9_MR zkCl&UG8MCy-Q(b!$ZskfS-->bKEm(X3mrvf8AC}%#`P#s#p>)A+Js{S+0yM3wucXA zhkjDu2@@bWNx$(`M z*->ij)R=%R852p#AR$lfV+|qC?euj5%jAFuetzR(F0Nv^4)ZNIh&t=|%p1stY{cY% z)KJ_&EX=g`tY2Njxd@RB>o)+(_k!FXHyE4^fuQ)rfXC<#ocqfhQU(|x5`&$_!4;}^ z;2I@vZJqyg`O4L+xCY})Hg)?!LPG)~B3D3v_5*HcX>PLO9Awnp56qd{h`cBI?<*@` z)O~3Zy}WFBS0F$mG2jxq1N*-8!pib8jevkIX6dm2M7pS;k##{7g_V_cZR%BlVKA-o z>$hHFWfRhoH?Op?|4*;nygUOY4P6}m z8#l-R)_0{IV~o4l*lo3cL?qg0dO}1$k}S9Tm3;Pvke>N-8!J)xlv2%4=+qt$SQ zQ-8|CLrwe4az_ZN4Aht;RmFPA5`zWFcIP!2m%qK9_Q3i*>E;SM_I3F8vhWCoBLg^P zKzxlFDy}y%)n1xlh_9}N1P9Xqc~*{Vg6Fo^+u<}N=D5t{#}=e93lAKb%9mG`Qhri; zb>}ejrtAmD+USgxYGVfaw-joQoMlEQJuK`Vg1UR@xmL7z&1C}`g%C;pJJ6=0@@SXr zUs!-JZbO2v(Qs#~ckR*Nh-p55ym@kU=`{@UV*aiCmN50MjyQ7V^&D!sk*L+K= zx(@6jqbeo^tL8~4)0C*VeYg};_!CqWnib$$s%XofPMDfg7%O(#RZG=wKkmGqDV=2+ z);7y1%1-3R3Zp5J;q?s(Qdd-XECBQq-cMuiyR%NXx-fq^nFv4pl}WY2HT zIhDoP>t*2G!w`syN54Rr)ot-`I65H1^oeH6#|Jm4I5!T(LwND-c7EMIik$SeygH43 zByDl_h9uw2udUdi&kXN7@VD8M4MOZ@hdj^G*=fm=Y&B1;$%EG z$kQe$H~ZxIBX%DC&FUZJZ^t<+9UUjjPbb*yZUZ+Oq$WyL*_V(jJVdTQ`}+#62E7f1 z+KU~m-$+^cTAe5e$7MKFf|dYu0hnOq8D_=S z4@Z&7Os=x3)ZhAAr7T=cDg0h=F+9tp-sbMd#p|}jlk1)zOV+k02d++5&Kol3f#(@; zWu?}3gsvpG|AsYLYZ@*&fzUHVsx^pja$(Ac_OUGa2A&Qitiu)M) z^9CGL;bS9q_h3jv&;n~BV^_1T>HsILblAF69&L~ytK01f&GUE6s0~dVR@dgb8b0S} zwUOd(5I=i+dU@zNWk;Pi1wpORyYb5z<@xoVJ27ysSwL>B{`(6T0%vBJiA&Z8K=bbe z1VMS`Tkiv=8)lU)neFYK`pEYDVEu44_kc z)PA%xPuw?0>5`X{i(Xoi;4P8?lnh^{u^i7<#a<625~eQX7PAEciof5 z1J(EwI9wK;9{!+2l;}0{6wP}Q7;Ps?$t|rW<7lNSK-gO6^e)JX%=zw!{#81X1JXcz zYAV*lv-wMTDL;T=6^#Jsk#O8lgK0?Qa99d~@c!CQd6#8e=lXTS^eh6R7nYCL?@qJ> z%##OXgW>NnfLku<;J^XKpU3yu0cb``kYYiCN5FMQsfm3MPa zVc{a630%U@>Sm{U*)Vroe^~(|3-a(@>v<{MAo2+!PMDgsV4&X+xK^<_fJ;=Y$qnWj zQ0F)j5)$@dhw#krUU5mi1yDH@nR?fn^g?$cL z_74t5D$J#-W3@r?pWAI!`RFqY+YDMqcmc&S?#YvUCazcr+#pFBeDRjjbxm{zcJCOE z2)po{;j%q$ucTe){(y68EA#zbHa|$r@1%UYBr+hkEgL{LByuYGw&1D2z2ca?#2sPe zMRw4`ixe@zBk~3n^QP~b30A)t6_eCY`sQ=8v(>9C6+}*E+`_`cH3-A{l2~)Z&Y*m? z&APwrhW`-bwJ;EQe!`U0UCv<3oO3_4G*MX2;Q_dqniJ6g8gmKn$^}(d(b!2 z0Hw0xAqYqwA%(K4mO?5zwR4S6ct(!Db@ANtNn70Wud=!JYlO4Y`Q7%HIC$DL&aaui zE5zHFcA2Hz1ne;Xqclb#?B0;V)orT?A>|5t1A=kC@`{~+fz}Dymb=i)WB~*j`Bn#> zg+jzKtF;`ipY-UBRhW+SQl&+g_E8y>I*>Lg)2dkuY(_Pu-y4(xqv_2{<-Htl^c;@r z1qjvbZSO;IPam@D-<8>XF&=)9TAs3VBxLud_{p2rj4qRjoq%En)zL51U9PH}ur^S; zz<%HC+^Q+K5Gj)OnMo>-ZgAT(TNa#_L;Mh)6t$yeSyo#bFQjj6NwSDb-l6 zi}<#1?r6BD(s;6mx3Jr|W7DTS0YYcT7voPQ1gvgs84wH_`Ev zD?O3-HMPL+VnC}HHskY+1|zjO)_qHpOpf}v;-}j47f8&*77~kRLD3y( zC@)sO^h8twygy5;KvglSC;Os7xRG;@{S+uG;qwx)M_#j(Qa8|GAL=m{ovM)`QAJw1 zxGoQY0UbkMff8@wmbxX&Bq&&v72lh!Kk}2wytvo98^+N}#@G3c^XBGp)w0;1*BCte zy$m~Uo}~4KROpy(7)K2_CXc6DEkqd1SixvNQT(vgLelS_f+a-bJ_Ss-B zMfO^CL{*I5f$5!o?>6_e|MruS%W@~6Sb}CqgL*nntkgLqS=io?YmFrKzr@}W^K&q`(uSEUd0-(gb-_Fg3^%*5|K(Vm;~YEX>^0t{T|sa z-W|2z=LXk=-*SwqZgs{Ss(8^Arfl0y-uJ>a#JDf%Ts{Bz#KY76941`RTA`$01KP`V zh?2bL*yFoIz)cBW=-)%uo(vq8Y8$_KKygm8?qTXg+}5;H^{T$H zFH|BlBKs_HSPnRpdwNHky1J6qK)367cDd8b?x%bFX+5 zY+EHb8I3Yu>xQA2J_*o1oG7>^^@&1F=(?QR>cW=rTZ~z$^A$k_2TtTa$_4{=xTy&U zvIW9G@us#iW<46+K^)BId4>Brgx{)uQhTT6fO?~%@jI8RsQ%IF1Hu*EtT+Gm7!y+b zL(W%IxSdtdjk;~h9vgMNxw$`fxIS75#@{1f@b`eQVL(GkBxkYkJhh$}Qzk2Y7N#^O z(=yt7#Te8>a*H|>m{v;OtvSJ%`%bH$3{9@NmS=Q*n;E^4=th)jMJ;>qbZcCIRRp^^ z)s*wt$l?a|Eq`Oqs;^Mh)Tnj5ZIS*S2YWK=j|cyJ+Tj(DoduL?T?PiA|G>pIODik# z&tr6%xm79u7w-EzBhfxS(IYipnap2N9gnVjAiI1y>yNjXg@}(ck_vS_@Vs{*uynOqrK0UpD_s~On1D1S6SvUJ-pO3Xpa=ht+!1NA;&<_m#%>c4=uj zxf~!95_zdsaP;PAhB!{YW?jw=fO#ce!JpHT2BRT^zS4ZJKs7@%k`wZt=ZcOG=uioU zQv%9lGP9Cj7^U5+@z~H!7xq*&opyAX{qTVlL?!Jr=|4x1C$1?ZGD);oADWuP;J^7u zmzqo5FkJaC67yP+OMgz&^MoBtgIxiSFWSD3%r+F7Y0zp&z0bSkQxXiPH$$8|?){vX zW3JLdZeXk7m4r?0D;FC9pK4B4Rt1&B_yaqoB$gK`l+%o;1T4}4bg{F6=p4!m^Jl*V zfvFY=C!)a{;?9ur@y@Xf%EQyyV}Z`<)~A_Q~c|wQudAd%m z`M8BmuYA)adbIGmsWk&VBR#gtIia?O#)GJ;KM@WV?poL?>Q(-T_o4&oqQ1H+>~Y>h zfZMr0BwMA!V5SMP%%pO$jV^HMG9pU~$&E_ek?bWA>qy_cpxSTFB8C&|ffuZ(CQ1iV zUYfQK(r*ki6*5!&s2%GsZy=`-a3E`JYCrue)zo2Pbq^6snyAZ9wr zb=pOm0_z?QOxUTRVClSFTjb@NSQ_Z;1u6GT%?R&w8&MDWM@ zc+Pcr+5d@!uv^BT5`SVndF#;%+~dp^<;E+S{i0-_w5-2+*s%w zv$oX6CObdRgZuE%F2H^+us-wwoAA|JnYRLH%b31w_g%O&`25z(d_2(j)yU{?jYOAk zzK+CGZ5bvC;(}-(f65Dz373j;Cyx^9yr_3FV^wiY`7gHQJKbt`8<2Hzq{?FJvFc4~ z0dZ^GPik_owcf!@cbQ0_Im#{o@a4;cVd#gp6waLK{Az-@?5424e0%ujC)-20Pt))I z5#?~o3pN4v<#!fHNUsi@e#dD=fk^aH2^biK_njmLbq+LWVIYQN=3pa`Zrt>&`<657 zwy0N`Pb*c8(Qnx;u<@Sf@UB4TZEm5l7^ssj0C}z%LX#^#nRv*_AO|Od@RQflAi@Ft zXE4D|V}flG)G?Mt=R1iEx7BEPmj7c(l*MsM(CGu-b93b%c6jyU_in|8hqu5`;?vVN zYwlUL$u}#)6qP1%b}FKE(8MJq1VM_l*!)!lF+0g8g^hV3P8Xv3>s04s38)@lXF9VM z6Z=?;McB|U*k6!#1rmG;DujTlle4ugOp~S@n3@gxpuk8)ub1^k5X11+;rNNF1 zpalQfEyuEo6<)>}ee+H4O>FqYfTF%!Ng9WO{pKoadAUbJQk4Y!?Ik$+-B2i~X;BHd z1yQ#XZMJ`M3&AmL0mm?TTbc=6`XWO!A=kxV6+QTRJ|pa+=`n6@_=*kI?xvy5+MWS? z_M`!i=8}OWC4Apsj%I7jaZ`Rim^sL2UDf9Ag}c5Tc?rHCpH&F+7oiw&0xv~BrnxG~ zQ=_Og2kQ`Lg!A~{+r@Nb024P61;#@U-@fvq(*}OZAtAoH`d6YN1X3nXyVCtuIDWY~ zGd_OY^q7tK^m?t@BV@1(7vTu{>)}QTCq3^l3sA?%^$Cgci}vXb7SH~j9?AdQjG_>L zz6pzC$p5BIq(bw3^tb=c%S_~EGZQz8l2hVS4C4=+6Pk=+rc_2_FoR|a-V@z~ISi-- z&I$jkm+{$B_3I57!CM%?;ffM+@G#NQxE%^m>4$F!meV)C#4q;7B)M6yHMQQ|Jsr!- z*q7z@=xzEVJxkZdc-V_N@IzynOn-PlV_ESUy>I)Iq}@&T@pT&QTe=Q3ypoS3rZh8m zSr!9-KKu6ONlIk;-Ony!C;WrUS3+#2LPr{{eH{~*s!B(Aup##Zo(ORY*$y*2GbNhl zl+uu5TP2R1vzQ>E9wgRY-ysz`b_(3j6IuLZKzyBjTq4Vqo88kf(L*2@eG{=SVs+L^ z@FWr9S?=ray9Wkjil9}dv!D|!9vajGI0E>b9LdOGyf|21K0Zre5?D;%HsUmnGGfEJ z`+NH_ESyJY(;3(2SH

=xDiV8LRId~5=fj?m3Tb$7#A0^SD8XKRK6dVwM;`;mf zl#t82e?Hmfhb{1sA44>tT!tDvTlVCf&c(Wb_^S+5raos*RR_r?#gc|(5 zg;BBSu==*awT!(QjC{O+Z~HzM8@dVZ0@*4N2YEdGr||o{(XIuUqSs8rRaQy}DH|fL z|9*qa2m1;?51yY%>+7dZNm)HWR&Dd5;W09o1T1WUz&g1D8fZX%l+vJH^h5sHOcAYg zIgOX|V#M#Ik?H^44hf6kT=&qyI#fb~?>t3Zd35?{WS`>%+GKj4e{>#K5>P?2c?u4g zFmx4I1XKKb4g%P5&9m4dKQ>>jjTXdyUxY~&N7H43?Y*+e1Frye0Q(S`$C zCq>3o!4JPxDu``?O>L`U2JJ%;j}d~g*8(cO$WP2z;0sbNqsR)H!Uj>>*72WqiE>H8<<-t?D;N;{~P0Ne8*#s55@N0IP*h=K`stW*jl!N@#UhKo4Qf?pl<&ojZ zB1<$uzz@t$YGy#Xk?*HYTxh&91t14;lm^aQl#0|CiarZP(PdwoJqZb*H`T^5FN9}W21U4S6qahel(725k1 zE+D^v*nvq2^?Qi#fL9@(#FNb1%M=i8N9yj_Y5_UV8!Lb(>px%5_kq9*+x%DOr)ixV`gN; z$NxW9e+9U|9*(d&kUaDMTvxfdxeGwM>V&k#_5Z%EVAX`;b%DBs)pvbzIMPtCXJS!g zsD8i#M!_bc+l4G^Hh8N@pSwEvo49~HSk(qXeit)g7FDW4 z@{~xm%M8aazuR78;Nv5NPIh52F|trwu7pl;o(@bOrD2I6Tb&to-vz8GCgJ746u`1i zPEKOZ_X|hJ(9qGL0U(UXrz5-bnL;xatc=Zgo0ulZ9t7Pe!cQ4u~d zamNcIPc{CJa%de4kcLz?Ys`Qx;Dz4W)|UJ=?wdv9AuY|p6&dBOj*j(D0lKgnIS^Z) zU}rJRV0IPF-``(eMP=oR$W<*Sw?oTwp8<|~wP~0iUi>)tDF&PtQ7PygvI}?*zn(*M z5+Y^pH97Z8`P{T#G(`^Zc-u+(m$L*5(e=- zbLIElQ)GjOl4!bguq5&vcytLWXiy{YED~e~JDu}M2`UH>LuD0NnGk@1t^R;4k>6F| zF<(<$Kr%8GR->q7bPoA|rMA@E_*XpX>mlf+5XucHPTeVGFq1$dqV8mf{x3rqR($Xi zbb$~kh(GkU{h=8*q*rbn4lS_ACGUbQ0f180zRn9tj4ML!SkNv?u-(&~+0aEm#90W= z&f#b{yBuxpQeppK*)obnu>H#Q=nO#(ZmQLQ5o3of^|wmSd(>LPD72yyuHB{piz^2a#7K!A7pNuVz|iHDm8GEtlcUZ)Qm?I@^TC1Up@qhEyr6(n z$QBP_tgO8~o8!!zz(i)XC6K)Rx}2z{o+FD}AaqeCQ|s$jZtORV@V07|*(qhvR%x@6 zzp@zjfZ~gkynI;kgvaJ2KH%(N?;y5p{P{c-K917DYM@wr2U=d)LVG5Hd;3UIpXJ3d zfVVAxQCv(wN`Vq8)Vn5PD$=+5MJ;xZM zts3;|wEblQ#EvH|kXD~a2n2^d>pQw%xwv${WTPoUAof@St9YNy&d}vP8I-WX`k(w&^aMhkk(pYZyYs-HNza1 zT=;~L!P%l9DX8;Y0b?J^Qk_*+ed&sCb<;C01mVE}orusCJTTS#R ziDElRsrU}YLoSYeND6U#?_27mvA=P3bpnt35jEJ&Cga_?Jt1!`s^tsv)i)e8+V|>#IZfUSQ0_g*WWJ< zB5p}*4O+_z$?7Bq^5YdS8hiXu?NdwJ6M)b>j*Z336=G?t#BkeZaD)Fzv-IAHM0gLJ z`)^*kb}4519=g>8q4&#!?T9ikS7um{MUNu!t_qXXo#-7d4y#3S=$twrhnufE5V4T( z?Ln2M03Dqq?rd-I2Pm$UEPepIP08YHkYZ-84tGw(AcwkL3{|;%t)2B?yF!A+xhMhhnJaUf>BmS!m|-<w-?L;fq2(jaHg}^1OJh$9goe3<^qQS+Pa5DM!w=ZUjqm5!X;Rk zn*=a#^#qsqc>cgn*1vQOcK$iE^V<1;U(<{+)(>%^xY6ikqr_EJFM*B5J+LE{18Jq* z{ry&ObGF`F)+EA_9)_;p!%oLC2QKi!6;%BHkzid&y6N?|ufe*TZq_5G(3}Cwqt5OA zlmG!YIVyR5@;3{x`yJrdD3fG(wC)`pfh=$8)6d;{st5R6!=d;Mpe38(k$rz0o)zIQUCw| 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 000000000000..0e64414b8410 --- /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 46e26c550df9..74361ad27867 100644 --- a/hexagonal/etc/presentation.html +++ b/hexagonal/etc/presentation.html @@ -60,29 +60,37 @@ --- -# 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/